Jump to content

    
Sign in to follow this  
Alex_Golubev

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

Recommended Posts

Привет.

 

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

Зависает 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

Edited by Alex_Golubev

Share this post


Link to post
Share on other sites

я как то боролся с 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);

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

Share this post


Link to post
Share on other sites

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

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]

Edited by Alex_Golubev

Share this post


Link to post
Share on other sites

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

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

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

Share this post


Link to post
Share on other sites

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

 

Вместо

DMA2->LIFCR |= DMA_LIFCR_CFEIF1;

 

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

DMA2->LIFCR = DMA_LIFCR_CFEIF1;

Edited by Genadi Zawidowski

Share this post


Link to post
Share on other sites
Вместо

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;
 }

}

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

Share this post


Link to post
Share on other sites
Если FIFO выключен, может наплевать на этц ошибку?
Это можно сделать, но нужно понять от куда она. Дыма без огня не бывает.

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

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this