0

I have a problem with STM32F0 DMA receiving data from UART. I use 2 DMA channels (for rx and tx) both in non-circular mode, rx channel has lower priority. Data from UART handles in Idle Line interrupt, where I read the number of DMA received bytes and process them. Everything works fine until the number of bytes in package is less than or equal to DMA buffer size. Otherwise DMA strangely turns off and following Idle Line interrupts give me the 1, 0, 0, ... number of DMA received bytes. Here is part of the code, where I check if the DMA buffers fills and try to reset DMA counter to buffer size:

#define S_M_INPUT_CMD_SIZE 20
static char s_m_uart_dma_in_buff[S_M_INPUT_CMD_SIZE + 1]; 

void USART1_IRQHandler(void)
{
   ITStatus reception_status = USART_GetITStatus(USART1, USART_IT_IDLE);
   if(reception_status != RESET)
   {
      int32_t bytes_number = S_M_INPUT_CMD_SIZE - DMA_GetCurrDataCounter(DMA1_Channel3);            
      if (DMA_GetFlagStatus(DMA1_FLAG_TC3) != RESET)
      {
         USART_ITConfig(UART_, USART_IT_IDLE, DISABLE);
         DMA_Cmd(DMA1_Channel3, DISABLE);
         while (DMA1_Channel3->CCR & DMA_CCR_EN);
         for (int i = 0; i < S_M_INPUT_CMD_SIZE; i++)
            s_m_uart_dma_in_buff[i] = '\0'; 
         DMA_SetCurrDataCounter(DMA1_Channel3, S_M_INPUT_CMD_SIZE); 
         DMA_Cmd(DMA1_Channel3, ENABLE); 
         DMA_ClearFlag(DMA1_FLAG_GL3);
      }
      USART_ClearITPendingBit(UART_, USART_IT_IDLE);
   } 
}

After the first "overflow" and DMA enabling comes "buffer size + 1" byte that was in rx register and later the number of received bytes is stable zero. What I'm doing wrong?

Yuriy
  • 701
  • 4
  • 18

1 Answers1

1

Here what happens if you trying to receive packet with size greater than S_M_INPUT_CMD_SIZE using your code:

  1. DMA complete reception of block S_M_INPUT_CMD_SIZE and disable (non-circular mode)
  2. USART1 receive one byte
  3. USART1 receive one more bytes from packet and drop them, because no one handle UART
  4. packet finished, you get IDLE interrupt and reinit DMA
  5. DMA read previously received byte
  6. No more packets - you get 0, 0, ... number of DMA received bytes

I have to say, this is really strange way to handle DMA transfers. DMA transfers usually must be handled in DMA interrupt handlers, not peripheral.

In order to handle long packets you have to implement DMA interrupt handler. So can reinit DMA reception earlier than IDLE interrupt. So DMA will be ready to receive more data from UART.

One more thing. In your code there is a race. between you read bytes_number and disable DMA one or more bytes could be transferred by DMA.

But more correct way to handle UART is to run DMA in circular mode and don't reinitialize it. Because every time you disable DMA you can miss some UART input.

alexander
  • 2,703
  • 18
  • 16
  • Thanks for your reply @alexander. Maybe I don't understand you, but received bytes number "0, 0, ..." is the reaction on following packages in new idle interrupts, seems like DMA just tired of working. The way is strange I agree, but this is the only way I came up with to receive а variable length packages with minimal cpu cost. And thanks for race I'll fix it. – Yuriy Jan 13 '17 at 14:35
  • @Yuriy, so after long packet you send another packets? And you get `0` to following packets? How do you check bytes_number? Hope, you don't halt program using JTAG inside ISR as JTAG may corrupt real picture. Use global variable to record events. Also it is possible what UART and DMA went unsync each other (so you have to reset UART or DMA). Also it is possible what UART set overflow flag and stop reception until clear it. – alexander Jan 13 '17 at 14:50
  • The check for zero bytes_number is skipping if(bytes_number > 0). I've tried to reconnect USART and DMA, and tried to disable/enable DMA RCC. I will try full reinitialization but it doesn't looks good. – Yuriy Jan 13 '17 at 15:13
  • The solution was simple. Setting rx channel DMA in a circular mode solved the problem. Now every too long package is caught by DMA Transmission Complete flag and all later packages are good handled. Thanks again @alexander. Especially for race, it solved my another problem) – Yuriy Jan 20 '17 at 11:13