Перейти к содержанию

Какая то странность с SPI4 в stm32f429zi

Привет.

 

Создал проект для начало в кубе. И увидал странность.

Зависает SPI4 у меня, не сразу а через какое то время работы.

Причем зависает а биты ошибок не ставит.

Примерно на пол пути передачи ставит бит RXNE в единицу и молчит. Если в ручною сбросить его то все дальше работает. Потом проходит какое то время и снова бит RXNE в единице. Такое ощущение что не читается регистр SPI_DR.

В счетчики DMA_SxNDTR остается число, каждый раз разное.

 

Бит OVR не установлен. Ошибок от DMA нет. Проверял несколько раз.

 

Вот скриншот всех основных битов. Видно бит RXNE в нуле. Значит данные из SPI не переданы в ОЗУ. DMA2 3 канал приемник 1 канал передатчик.

 

 

Может кто подскажет в чем проблема ?

 

Пытался выловить ошибки DMA:

 

void DMA2_Stream1_IRQHandler(void)
{
  /* USER CODE BEGIN DMA2_Stream1_IRQn 0 */
/* if(DMA2->LISR & DMA_LISR_TCIF1)
  {
  while(1); 
  } */
  
  if(DMA2->LISR & DMA_LISR_TEIF1)
  {
  while(1); 
  } 
  
  if(DMA2->LISR & DMA_LISR_DMEIF1)
  {
  while(1); 
  } 
  
  if(DMA2->LISR & DMA_LISR_FEIF1)
  {
  while(1); 
  } 
  
  /* USER CODE END DMA2_Stream1_IRQn 0 */
  HAL_DMA_IRQHandler(&hdma_spi4_tx);
  /* USER CODE BEGIN DMA2_Stream1_IRQn 1 */

  /* USER CODE END DMA2_Stream1_IRQn 1 */
}

post-95877-1530073851_thumb.png

Изменено пользователем Alex_Golubev

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

я как то боролся с L0 серией, может поможет

в файле stm32l0xx_hal_spi.c

HAL_DMA_Start_IT(hspi->hdmatx, (uint32_t)hspi->pTxBuffPtr, (uint32_t)&hspi->Instance->DR, hspi->TxXferCount);

в данной строке преждевременно запускается DMA (до подачи команды

/* Enable SPI peripheral */

__HAL_SPI_ENABLE(hspi);)

что приводит к невозможности установки бита SPE регистра CR1 SPI (подробности его установки описаны в datasheet). Если откорректировать stm32l0xx_hal_spi.c и перенести строку

HAL_DMA_Start_IT(hspi->hdmatx, (uint32_t)hspi->pTxBuffPtr, (uint32_t)&hspi->Instance->DR, hspi->TxXferCount);

после процедуры

__HAL_SPI_ENABLE(hspi);

то все работает нормально.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Столкнулся с проблемой вылезает ошибка:

if(DMA2->LISR & DMA_LISR_FEIF1) //+
{
DMA2->LIFCR |= DMA_LIFCR_CFEIF1;
}

 

 

[code]void start_TDC_7200 (void)
{
  TDC720x_CS_ON;
  TDC7200.Register_Read_Write    =                           0xc0;
  TDC7200.CONFIG1                =                TDC7200_CONFIG1;
  TDC7200.CONFIG2                =                TDC7200_CONFIG2;
  TDC7200.INT_STATUS             =             TDC7200_INT_STATUS;
  TDC7200.INT_MASK               =               TDC7200_INT_MASK;
  TDC7200.COARSE_CNTR_OVF_H      =      TDC7200_COARSE_CNTR_OVF_H;
  TDC7200.COARSE_CNTR_OVF_L      =      TDC7200_COARSE_CNTR_OVF_L;
  TDC7200.CLOCK_CNTR_OVF_H       =       TDC7200_CLOCK_CNTR_OVF_H;
  TDC7200.CLOCK_CNTR_OVF_L       =       TDC7200_CLOCK_CNTR_OVF_L;
  TDC7200.CLOCK_CNTR_STOP_MASK_H = TDC7200_CLOCK_CNTR_STOP_MASK_H;
  TDC7200.CLOCK_CNTR_STOP_MASK_L = TDC7200_CLOCK_CNTR_STOP_MASK_L;
  
  DMA2_Stream1->NDTR = sizeof(TDC7200); // счетчик сколько передать данных 
  DMA2_Stream1->PAR = (uint32_t)(&(SPI4->DR));
  DMA2_Stream1->M0AR = (unsigned long)&TDC7200;
  DMA2_Stream1->FCR = 0x00000000;
  DMA2_Stream1->FCR |= DMA_SxFCR_DMDIS;
  
  DMA2->LIFCR |= DMA_LIFCR_CTEIF1;
  DMA2->LIFCR |= DMA_LIFCR_CDMEIF1;
  DMA2->LIFCR |= DMA_LIFCR_CFEIF1;
  DMA2->LIFCR |= DMA_LIFCR_CTCIF1;
  
  DMA2_Stream1->CR = 0x00000000;
  DMA2_Stream1->CR |= DMA_CHANNEL_4;
  DMA2_Stream1->CR |= DMA_MEMORY_TO_PERIPH;
  DMA2_Stream1->CR |= DMA_PINC_DISABLE;
  DMA2_Stream1->CR |= DMA_MINC_ENABLE;
  DMA2_Stream1->CR |= DMA_PDATAALIGN_BYTE;
  DMA2_Stream1->CR |= DMA_MDATAALIGN_BYTE;
  DMA2_Stream1->CR |= DMA_NORMAL;
  DMA2_Stream1->CR |= DMA_PRIORITY_LOW;
  DMA2_Stream1->CR |= DMA_FIFOMODE_DISABLE;
  DMA2_Stream1->CR |= DMA_SxCR_TCIE;
  DMA2_Stream1->CR |= DMA_SxCR_EN;
  
  DMA2_Stream3->NDTR = sizeof(TDC7200); // счетчик сколько передать данных 
  DMA2_Stream3->PAR = (uint32_t)(&(SPI4->DR));
  DMA2_Stream3->M0AR = (unsigned long)&TDC7200; 
  DMA2_Stream3->FCR = 0x00000000;
  DMA2_Stream3->FCR |= DMA_SxFCR_DMDIS;
  
  DMA2->LIFCR |= DMA_LIFCR_CTEIF3;
  DMA2->LIFCR |= DMA_LIFCR_CDMEIF3;
  DMA2->LIFCR |= DMA_LIFCR_CFEIF3;
  DMA2->LIFCR |= DMA_LIFCR_CTCIF3;
  
  DMA2_Stream3->CR = 0x00000000;
  DMA2_Stream3->CR |= DMA_CHANNEL_5;
  DMA2_Stream3->CR |= DMA_PERIPH_TO_MEMORY;
  DMA2_Stream3->CR |= DMA_PINC_DISABLE;
  DMA2_Stream3->CR |= DMA_MINC_ENABLE;
  DMA2_Stream3->CR |= DMA_PDATAALIGN_BYTE;
  DMA2_Stream3->CR |= DMA_MDATAALIGN_BYTE;
  DMA2_Stream3->CR |= DMA_NORMAL;
  DMA2_Stream3->CR |= DMA_PRIORITY_LOW;
  DMA2_Stream3->CR |= DMA_FIFOMODE_DISABLE;
  DMA2_Stream3->CR |= DMA_SxCR_TCIE;
  DMA2_Stream3->CR |= DMA_SxCR_EN;

  SPI4->CR2 |= SPI_CR2_TXDMAEN | SPI_CR2_RXDMAEN;
  SPI4->CR1 |= SPI_CR1_SPE;
}


void HAL_GPIO_EXTI_Callback (uint16_t GPIO_Pin)
{
if(GPIO_Pin == GPIO_PIN_13){

  TDC720x_CS_ON;
  TDC7200.Register_Read_Write = 0x80;
  TDC7200.CONFIG1                = 0;
  TDC7200.CONFIG2                = 0;
  TDC7200.INT_STATUS             = 0;
  TDC7200.INT_MASK               = 0;
  TDC7200.COARSE_CNTR_OVF_H      = 0;
  TDC7200.COARSE_CNTR_OVF_L      = 0;
  TDC7200.CLOCK_CNTR_OVF_H       = 0;
  TDC7200.CLOCK_CNTR_OVF_L       = 0;
  TDC7200.CLOCK_CNTR_STOP_MASK_H = 0;
  TDC7200.CLOCK_CNTR_STOP_MASK_L = 0;
  
  DMA2_Stream1->NDTR = sizeof(TDC7200); // счетчик сколько передать данных 
  DMA2_Stream1->PAR = (uint32_t)(&(SPI4->DR));
  DMA2_Stream1->M0AR = (unsigned long)&TDC7200;
  DMA2_Stream1->FCR = 0x00000000;
  DMA2_Stream1->FCR |= DMA_SxFCR_DMDIS;
  
  DMA2_Stream1->CR = 0x00000000;
  DMA2_Stream1->CR |= DMA_CHANNEL_4;
  DMA2_Stream1->CR |= DMA_MEMORY_TO_PERIPH;
  DMA2_Stream1->CR |= DMA_PINC_DISABLE;
  DMA2_Stream1->CR |= DMA_MINC_ENABLE;
  DMA2_Stream1->CR |= DMA_PDATAALIGN_BYTE;
  DMA2_Stream1->CR |= DMA_MDATAALIGN_BYTE;
  DMA2_Stream1->CR |= DMA_NORMAL;
  DMA2_Stream1->CR |= DMA_PRIORITY_LOW;
  DMA2_Stream1->CR |= DMA_FIFOMODE_DISABLE;
  DMA2_Stream1->CR |= DMA_SxCR_TCIE;
  DMA2_Stream1->CR |= DMA_SxCR_EN;
  
  DMA2_Stream3->NDTR = sizeof(TDC7200); // счетчик сколько передать данных 
  DMA2_Stream3->PAR = (uint32_t)(&(SPI4->DR));
  DMA2_Stream3->M0AR = (unsigned long)&TDC7200;
  DMA2_Stream3->FCR = 0x00000000;
  DMA2_Stream3->FCR |= DMA_SxFCR_DMDIS;
  
  DMA2_Stream3->CR = 0x00000000;
  DMA2_Stream3->CR |= DMA_CHANNEL_5;
  DMA2_Stream3->CR |= DMA_PERIPH_TO_MEMORY;
  DMA2_Stream3->CR |= DMA_PINC_DISABLE;
  DMA2_Stream3->CR |= DMA_MINC_ENABLE;
  DMA2_Stream3->CR |= DMA_PDATAALIGN_BYTE;
  DMA2_Stream3->CR |= DMA_MDATAALIGN_BYTE;
  DMA2_Stream3->CR |= DMA_NORMAL;
  DMA2_Stream3->CR |= DMA_PRIORITY_LOW;
  DMA2_Stream3->CR |= DMA_FIFOMODE_DISABLE;
  DMA2_Stream3->CR |= DMA_SxCR_TCIE;
  DMA2_Stream3->CR |= DMA_SxCR_EN;

  SPI4->CR2 |= SPI_CR2_TXDMAEN | SPI_CR2_RXDMAEN;
  SPI4->CR1 |= SPI_CR1_SPE;
  
  INT_TDC7200 = 1; 
  
}
}


void DMA2_TDC7200(void)
{

  static unsigned char i; 
  while(!(SPI4->SR & SPI_SR_TXE)); 
  while( SPI4->SR & SPI_SR_BSY);
  SPI4->CR1 &= ~SPI_CR1_SPE;
  TDC720x_CS_OFF;
  
  
  if(INT_TDC7200){     
    
  if(TDC7200.INT_STATUS & 0x6){ // если переполнение TDC7200 то просто херим измерение и запускаем заново 
    
  TDC720x_CS_ON;
  TDC7200.Register_Read_Write    =                           0xc0;
  TDC7200.CONFIG1                =                TDC7200_CONFIG1;
  TDC7200.CONFIG2                =                TDC7200_CONFIG2;
  TDC7200.INT_STATUS             =             TDC7200_INT_STATUS;
  TDC7200.INT_MASK               =               TDC7200_INT_MASK;
  TDC7200.COARSE_CNTR_OVF_H      =      TDC7200_COARSE_CNTR_OVF_H;
  TDC7200.COARSE_CNTR_OVF_L      =      TDC7200_COARSE_CNTR_OVF_L;
  TDC7200.CLOCK_CNTR_OVF_H       =       TDC7200_CLOCK_CNTR_OVF_H;
  TDC7200.CLOCK_CNTR_OVF_L       =       TDC7200_CLOCK_CNTR_OVF_L;
  TDC7200.CLOCK_CNTR_STOP_MASK_H = TDC7200_CLOCK_CNTR_STOP_MASK_H;
  TDC7200.CLOCK_CNTR_STOP_MASK_L = TDC7200_CLOCK_CNTR_STOP_MASK_L;
  
  DMA2_Stream1->NDTR = sizeof(TDC7200); // счетчик сколько передать данных 
  DMA2_Stream1->PAR = (uint32_t)(&(SPI4->DR));
  DMA2_Stream1->M0AR = (unsigned long)&TDC7200;
  DMA2_Stream1->FCR = 0x00000000;
DMA2_Stream1->FCR |= DMA_SxFCR_DMDIS;
  
  DMA2_Stream1->CR = 0x00000000;
  DMA2_Stream1->CR |= DMA_CHANNEL_4;
  DMA2_Stream1->CR |= DMA_MEMORY_TO_PERIPH;
  DMA2_Stream1->CR |= DMA_PINC_DISABLE;
  DMA2_Stream1->CR |= DMA_MINC_ENABLE;
  DMA2_Stream1->CR |= DMA_PDATAALIGN_BYTE;
  DMA2_Stream1->CR |= DMA_MDATAALIGN_BYTE;
  DMA2_Stream1->CR |= DMA_NORMAL;
  DMA2_Stream1->CR |= DMA_PRIORITY_LOW;
  DMA2_Stream1->CR |= DMA_FIFOMODE_DISABLE;
  DMA2_Stream1->CR |= DMA_SxCR_TCIE;
  DMA2_Stream1->CR |= DMA_SxCR_EN;
  
  DMA2_Stream3->NDTR = sizeof(TDC7200); // счетчик сколько передать данных 
  DMA2_Stream3->PAR = (uint32_t)(&(SPI4->DR));
  DMA2_Stream3->M0AR = (unsigned long)&TDC7200;
  DMA2_Stream3->FCR = 0x00000000;
  DMA2_Stream3->FCR |= DMA_SxFCR_DMDIS;
  
  DMA2_Stream3->CR = 0x00000000;
  DMA2_Stream3->CR |= DMA_CHANNEL_5;
  DMA2_Stream3->CR |= DMA_PERIPH_TO_MEMORY;
  DMA2_Stream3->CR |= DMA_PINC_DISABLE;
  DMA2_Stream3->CR |= DMA_MINC_ENABLE;
  DMA2_Stream3->CR |= DMA_PDATAALIGN_BYTE;
  DMA2_Stream3->CR |= DMA_MDATAALIGN_BYTE;
  DMA2_Stream3->CR |= DMA_NORMAL;
  DMA2_Stream3->CR |= DMA_PRIORITY_LOW;
  DMA2_Stream3->CR |= DMA_FIFOMODE_DISABLE;
  DMA2_Stream3->CR |= DMA_SxCR_TCIE;
  DMA2_Stream3->CR |= DMA_SxCR_EN;

  SPI4->CR2 |= SPI_CR2_TXDMAEN | SPI_CR2_RXDMAEN;
  SPI4->CR1 |= SPI_CR1_SPE;
    
  counter_not_sample +=1; // прибовляем один для ошибки нет пробы  
  
  INT_TDC7200 = 0;  
  
  }
  else{

  if(i){
    
    for(uint8_t j = 0; j<TDC7200_ALL_DATA_SIZE; j++){
    all_tdc7200_data[j] = all_data[j+1];
    }
    tdc7200_build_mreg(all_tdc7200_data); // сортируем данные TDC7200
    
    ccnt = (float) (meas_result_regrs[12]-meas_result_regrs[11])/(CALIBRATION2_PERIODS-1);    
    norm_lsb = tdc_clk_period / ccnt;  
    startstop_tdc7200 = norm_lsb * ((float)meas_result_regrs[0] - (float)meas_result_regrs[2]) + tdc_clk_period * (float)(meas_result_regrs[1]>>0); //1
    i = 0;
    INT_TDC7200 = 0;  
    return;
  }  
    
  if(TDC7200.INT_STATUS & 0x1){
  counter_not_sample = 0; // обнуляем ошибку нет пробы считаем что произошол сбой 
  
  TDC720x_CS_ON; 
  all_data[0] = 0x90; 
  DMA2_Stream1->NDTR = sizeof(all_data); // счетчик сколько передать данных 
  DMA2_Stream1->PAR = (uint32_t)(&(SPI4->DR));
  DMA2_Stream1->M0AR = (unsigned long)&all_data;
  DMA2_Stream1->FCR = 0x00000000;
  DMA2_Stream1->FCR |= DMA_SxFCR_DMDIS;
  
  DMA2_Stream1->CR = 0x00000000;
  DMA2_Stream1->CR |= DMA_CHANNEL_4;
  DMA2_Stream1->CR |= DMA_MEMORY_TO_PERIPH;
  DMA2_Stream1->CR |= DMA_PINC_DISABLE;
  DMA2_Stream1->CR |= DMA_MINC_ENABLE;
  DMA2_Stream1->CR |= DMA_PDATAALIGN_BYTE;
  DMA2_Stream1->CR |= DMA_MDATAALIGN_BYTE;
  DMA2_Stream1->CR |= DMA_NORMAL;
  DMA2_Stream1->CR |= DMA_PRIORITY_LOW;
  DMA2_Stream1->CR |= DMA_FIFOMODE_DISABLE;
  DMA2_Stream1->CR |= DMA_SxCR_TCIE;
  DMA2_Stream1->CR |= DMA_SxCR_EN;
  
  DMA2_Stream3->NDTR = sizeof(all_data); // счетчик сколько передать данных 
  DMA2_Stream3->PAR = (uint32_t)(&(SPI4->DR));
  DMA2_Stream3->M0AR = (unsigned long)&all_data;
  DMA2_Stream3->FCR = 0x00000000;
  DMA2_Stream3->FCR |= DMA_SxFCR_DMDIS;
  
  DMA2_Stream3->CR = 0x00000000;
  DMA2_Stream3->CR |= DMA_CHANNEL_5;
  DMA2_Stream3->CR |= DMA_PERIPH_TO_MEMORY;
  DMA2_Stream3->CR |= DMA_PINC_DISABLE;
  DMA2_Stream3->CR |= DMA_MINC_ENABLE;
  DMA2_Stream3->CR |= DMA_PDATAALIGN_BYTE;
  DMA2_Stream3->CR |= DMA_MDATAALIGN_BYTE;
  DMA2_Stream3->CR |= DMA_NORMAL;
  DMA2_Stream3->CR |= DMA_PRIORITY_LOW;
  DMA2_Stream3->CR |= DMA_FIFOMODE_DISABLE;
  DMA2_Stream3->CR |= DMA_SxCR_TCIE;
  DMA2_Stream3->CR |= DMA_SxCR_EN;

  SPI4->CR2 |= SPI_CR2_TXDMAEN | SPI_CR2_RXDMAEN;
  SPI4->CR1 |= SPI_CR1_SPE;
  
  i = 1;
  }
  }
  }
  
}

[/code]

Изменено пользователем Alex_Golubev

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Можете мне объяснить.

При каких условиях появляться ошибка DMA_LISR_FEIF1, если в регистре FCR бит DMDIS установлен в нуль, то есть установлен direct mode ?

Порог FTH установлен в 1/4 от полного FIFO.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Для начала для сброса битов в LIFCR / HIFCR применяёте операцию присвоения, без считывания... Может все и образуется.

 

Вместо

DMA2->LIFCR |= DMA_LIFCR_CFEIF1;

 

в данном слчае надо

DMA2->LIFCR = DMA_LIFCR_CFEIF1;

Изменено пользователем Genadi Zawidowski

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
Вместо

DMA2->LIFCR |= DMA_LIFCR_CFEIF1;

 

в данном слчае надо

DMA2->LIFCR = DMA_LIFCR_CFEIF1;

У меня так и сделано.

void DMA2_Stream1_IRQHandler(void)
{

 if(DMA2->LISR & DMA_LISR_TEIF1)
 {
 DMA2->LIFCR = DMA_LIFCR_CTEIF1;
 while(1); 
 } 

 if(DMA2->LISR & DMA_LISR_DMEIF1)
 {
  DMA2->LIFCR = DMA_LIFCR_CDMEIF1;
 while(1); 
 } 

 if(DMA2->LISR & DMA_LISR_FEIF1) //+
 {
 DMA2->LIFCR = DMA_LIFCR_CFEIF1;
// while(1); 
 }

 if(DMA2->LISR & DMA_LIFCR_CHTIF1)
 {
 DMA2->LIFCR = DMA_LIFCR_CHTIF1;
 }

 if(DMA2->LISR & DMA_LISR_TCIF1)
 {
 DMA2->LIFCR = DMA_LIFCR_CTCIF1;
 }

}

Но ошибка все равно вываливается.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Если FIFO выключен, может наплевать на этц ошибку?

У меня так и сделано.

В первом примере кода было неправильно.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
Если FIFO выключен, может наплевать на этц ошибку?
Это можно сделать, но нужно понять от куда она. Дыма без огня не бывает.

В первом примере кода было неправильно.
Не смог отредактировать пример :(.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Для публикации сообщений создайте учётную запись или авторизуйтесь

Вы должны быть пользователем, чтобы оставить комментарий

Создать учетную запись

Зарегистрируйте новую учётную запись в нашем сообществе. Это очень просто!

Регистрация нового пользователя

Войти

Уже есть аккаунт? Войти в систему.

Войти