AnsweredAssumed Answered

Restore circular DMA RX after UART error

Question asked by AbbraKadabbra on Aug 10, 2017
Latest reply on Sep 18, 2017 by Gianfranco Favier

Hi!

On both  STM32F405 and STM32F745:

We use circular mode DMA RX. It works fine until the first frame or hight noise error occurs (which rarely but happen).

After the error DMA stops working. Naive calling HAL_UART_Receive_DMA doesn't help.

 

How to re-enable circular DMA receive again using STM32 HAL drivers?  Or how to make DMA ignore framing and noising errors?

 

Details:

1. When error occurs, UART_DMAAbortOnError is called from DMA IRQ and it triggers HAL_UART_ErrorCallback where we see frame or high noise error HAL_UART_GetError.

void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart)
{
    if (huart == &huart6)
    {
         // How to restore dma work here????

         // Last try witch is definately an overkill but it doesn't work
         __HAL_UART_CLEAR_PEFLAG(&huart6);
         HAL_UART_DMAStop(&huart6);
         HAL_UART_MspDeInit(&huart6);
         HAL_UART_MspInit(&huart6);
         HAL_UART_Receive_DMA(&huart6, rxBuffer, DUD_RX_BUFFER_LEN);

         // Also tried like but didn't work
         // HAL_UART_DMAStop(&huart6);
         // HAL_UART_Receive_DMA(&huart6, rxBuffer, DUD_RX_BUFFER_LEN);

         // And tried some other combinations

         // Shows FRAMING or HIGH noise ERROR
         //sprintf(dbgSndBuff, "UART6 error %i DMA error %i \r\n", HAL_UART_GetError(&huart6), HAL_DMA_GetError(&hdma_usart6_rx));
    }
}

 

2. We have "standard" CubeMX initialization code:

/* USART6 init function */

void MX_USART6_UART_Init(void)
{

  huart6.Instance = USART6;
  huart6.Init.BaudRate = 1000000;
  huart6.Init.WordLength = UART_WORDLENGTH_8B;
  huart6.Init.StopBits = UART_STOPBITS_1;
  huart6.Init.Parity = UART_PARITY_NONE;
  huart6.Init.Mode = UART_MODE_TX_RX;
  huart6.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart6.Init.OverSampling = UART_OVERSAMPLING_16;
  if (HAL_UART_Init(&huart6) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

}
/* USART6_RX Init */
    hdma_usart6_rx.Instance = DMA2_Stream1;
    hdma_usart6_rx.Init.Channel = DMA_CHANNEL_5;
    hdma_usart6_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
    hdma_usart6_rx.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_usart6_rx.Init.MemInc = DMA_MINC_ENABLE;
    hdma_usart6_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
    hdma_usart6_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
    hdma_usart6_rx.Init.Mode = DMA_CIRCULAR;
    hdma_usart6_rx.Init.Priority = DMA_PRIORITY_MEDIUM;
    hdma_usart6_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
    if (HAL_DMA_Init(&hdma_usart6_rx) != HAL_OK)
    {
      _Error_Handler(__FILE__, __LINE__);
    }

    __HAL_LINKDMA(uartHandle,hdmarx,hdma_usart6_rx);

    /* USART6_TX Init */
    hdma_usart6_tx.Instance = DMA2_Stream6;
    hdma_usart6_tx.Init.Channel = DMA_CHANNEL_5;
    hdma_usart6_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
    hdma_usart6_tx.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_usart6_tx.Init.MemInc = DMA_MINC_ENABLE;
    hdma_usart6_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
    hdma_usart6_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
    hdma_usart6_tx.Init.Mode = DMA_NORMAL;
    hdma_usart6_tx.Init.Priority = DMA_PRIORITY_MEDIUM;
    hdma_usart6_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
    if (HAL_DMA_Init(&hdma_usart6_tx) != HAL_OK)
    {
      _Error_Handler(__FILE__, __LINE__);
    }

    __HAL_LINKDMA(uartHandle,hdmatx,hdma_usart6_tx);

 

3. CubeMX version 4.22, STM32CubeF7 Firmware Package V1.7.0, STM32CubeF4 Firmware Package V1.16.0

 

P.S. Our protocol has data consistency check, so in general we don't care about single UART errors,  so if DMA would ignore errors should work for us fine too.

Outcomes