cancel
Showing results for 
Search instead for 
Did you mean: 

UART in DMA RX mode stops working after few mins

Abhishek Kumar
Associate III
Posted on November 28, 2017 at 13:07

MCU: STM32F777II

I am facing a very strange problem with receiving data from a UART where the data reception stops after few minutes like after >10 minutes, where initially it works pretty fine.The RX channel of the UART is configured in DMA mode and the DMA priority for this stream is kept at higher priority as compared to other DMA priorities in the system.

The setting for the UART are:

/* UART7 init function */

void MX_UART7_Init(void)

{

huart7.Instance = UART7;

huart7.Init.BaudRate = 9600;

huart7.Init.WordLength = UART_WORDLENGTH_8B;

huart7.Init.StopBits = UART_STOPBITS_1;

huart7.Init.Parity = UART_PARITY_NONE;

huart7.Init.Mode = UART_MODE_TX_RX;

huart7.Init.HwFlowCtl = UART_HWCONTROL_NONE;

huart7.Init.OverSampling = UART_OVERSAMPLING_16;

huart7.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_ENABLE;

huart7.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;

if (HAL_UART_Init(&huart7) != HAL_OK)

{

_Error_Handler(__FILE__, __LINE__);

}

}

and for the DMA stream:

else if(uartHandle->Instance==UART7)

{

/* USER CODE BEGIN UART7_MspInit 0 */

/* USER CODE END UART7_MspInit 0 */

/* UART7 clock enable */

__HAL_RCC_UART7_CLK_ENABLE();

/**UART7 GPIO Configuration

PF6 ------> UART7_RX

PF7 ------> UART7_TX

*/

GPIO_InitStruct.Pin = UART7_RX_DOWNSTREAM_Pin|UART7_TX_DOWNSTREAM_Pin;

GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;

GPIO_InitStruct.Pull = GPIO_PULLUP;

GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;

GPIO_InitStruct.Alternate = GPIO_AF8_UART7;

HAL_GPIO_Init(GPIOF, &GPIO_InitStruct);

/* UART7 DMA Init */

/* UART7_RX Init */

hdma_uart7_rx.Instance = DMA1_Stream3;

hdma_uart7_rx.Init.Channel = DMA_CHANNEL_5;

hdma_uart7_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;

hdma_uart7_rx.Init.PeriphInc = DMA_PINC_DISABLE;

hdma_uart7_rx.Init.MemInc = DMA_MINC_ENABLE;

hdma_uart7_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;

hdma_uart7_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;

hdma_uart7_rx.Init.Mode = DMA_CIRCULAR;

hdma_uart7_rx.Init.Priority = DMA_PRIORITY_MEDIUM;

hdma_uart7_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;

if (HAL_DMA_Init(&hdma_uart7_rx) != HAL_OK)

{

_Error_Handler(__FILE__, __LINE__);

}

__HAL_LINKDMA(uartHandle,hdmarx,hdma_uart7_rx);

/* UART7_TX Init */

hdma_uart7_tx.Instance = DMA1_Stream1;

hdma_uart7_tx.Init.Channel = DMA_CHANNEL_5;

hdma_uart7_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;

hdma_uart7_tx.Init.PeriphInc = DMA_PINC_DISABLE;

hdma_uart7_tx.Init.MemInc = DMA_MINC_ENABLE;

hdma_uart7_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;

hdma_uart7_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;

hdma_uart7_tx.Init.Mode = DMA_NORMAL;

hdma_uart7_tx.Init.Priority = DMA_PRIORITY_LOW;

hdma_uart7_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;

if (HAL_DMA_Init(&hdma_uart7_tx) != HAL_OK)

{

_Error_Handler(__FILE__, __LINE__);

}

__HAL_LINKDMA(uartHandle,hdmatx,hdma_uart7_tx);

/* UART7 interrupt Init */

HAL_NVIC_SetPriority(UART7_IRQn, 5, 0);

HAL_NVIC_EnableIRQ(UART7_IRQn);

/* USER CODE BEGIN UART7_MspInit 1 */

/* USER CODE END UART7_MspInit 1 */

}

I have programmed HAL_UART_RxCpltCallback() as:

void HAL_UART_RxCpltCallback(UART_HandleTypeDef* huart)

{

if (huart->Instance == UART7)

{

// FROM CONFIG APP: Save the command so the worker thread can pick it up

HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_14);

xQueueSendToBackFromISR(btQueue, huart->pRxBuffPtr, NULL);

__HAL_UART_CLEAR_OREFLAG(huart);

__HAL_UART_CLEAR_NEFLAG(huart);

__HAL_UART_CLEAR_FEFLAG(huart);

__HAL_UART_CLEAR_PEFLAG(huart);

__HAL_UART_CLEAR_IDLEFLAG(huart);

}

}

And in my main code, I fire up the the DMA for every 1 byte of reception:

uint8_t dmaRXBuffer[1];

HAL_UART_Receive_DMA(&UART_DOWN_USB_TO_SERIAL, dmaRXBuffer, 1);

where I tested with and without adding those error flag clear code segments, but it didn't had any effect. As you can see in the above code, I also tried adding a LED toggle code just to check whether the code flow is reaching that are when the UART receives something, and yes for the first few minutes, it works fine as expected but stops after sometime.

Note: Since I am working on FreeRTOS, I ensured that even with other tasks running, there is enough time for the CPU to process anything else, so it is nothing like the CPU is fully loaded or blocked in some task. I verified this using Percepio Tracealyzer.

I am also attaching the UART RX signals captured on my Tektronix 200MHz DSO just for reference:

0690X00000604DiQAI.jpg

0690X00000604ELQAY.jpg

#stm32-f7 #uart-dma

Note: this post was migrated and contained many threaded conversations, some content may be missing.
8 REPLIES 8
Posted on November 28, 2017 at 14:30

Check if the overflow or framing errors, etc are flagging at the time of failure, probably would be visiting callback in those situations.

Hope it is just the scaling on the scope, but the signals look awful.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on November 28, 2017 at 14:52

How can I program the mcu not to abort DMA RX on any errors? Is there a way around?

Posted on November 28, 2017 at 15:01

Perhaps you can IRQ on the error statuses?

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on November 28, 2017 at 15:54

How about re-firing the DMA RX on HAL_UART_ErrorCallback() ?, So that I continue to receive even on some random framing errors, etc

void HAL_UART_ErrorCallback(UART_HandleTypeDef* huart)

{

if (huart->Instance == UART7)

{

/* Restart DMA RX even if we encountered framing error, etc */

HAL_UART_Receive_DMA(&UART_DOWN_USB_TO_SERIAL, huart->pRxBuffPtr, 1);

}

}
Posted on November 28, 2017 at 16:29

Not really looking to debug HAL implementations.

Is there some value to using DMA here that can't be solved with exactly the same number of interrupts, and less complexity? The point of using DMA would surely be to provide a deep enough buffering to avoid service latency and overruns?

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on November 28, 2017 at 17:00

Yes, I am using DMA here to cache the incoming data until the consumer task gets its chance to consume it!

Posted on November 28, 2017 at 18:25

As applied this provides zero advantage over USART IRQ, and add significant complexity, perhaps abstracted from view, but still adding burden that brings no benefit.

In these cases I use DMA to provide the buffering and reduce loading.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on November 28, 2017 at 19:58

Can u please explain in detail, I didn't get you?