AnsweredAssumed Answered

UART in DMA RX mode stops working after few mins

Question asked by Abhishek Kumar on Nov 28, 2017
Latest reply on Nov 28, 2017 by Clive One

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:

Outcomes