UART in DMA RX mode stops working after few mins
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2017-11-28 4:07 AM
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:
- Labels:
-
STM32F7 Series
-
UART-USART
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2017-11-28 5:30 AM
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.
Up vote any posts that you find helpful, it shows what's working..
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2017-11-28 6:52 AM
How can I program the mcu not to abort DMA RX on any errors? Is there a way around?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2017-11-28 7:01 AM
Perhaps you can IRQ on the error statuses?
Up vote any posts that you find helpful, it shows what's working..
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2017-11-28 7:54 AM
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); }}- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2017-11-28 8:29 AM
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?
Up vote any posts that you find helpful, it shows what's working..
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2017-11-28 9:00 AM
Yes, I am using DMA here to cache the incoming data until the consumer task gets its chance to consume it!
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2017-11-28 10:25 AM
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.
Up vote any posts that you find helpful, it shows what's working..
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2017-11-28 11:58 AM
Can u please explain in detail, I didn't get you?
