Skip to main content
Abhishek Kumar
Associate III
November 28, 2017
Question

UART in DMA RX mode stops working after few mins

  • November 28, 2017
  • 1 reply
  • 2745 views
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.
This topic has been closed for replies.

1 reply

Tesla DeLorean
Guru
November 28, 2017
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 VenmoUp vote any posts that you find helpful, it shows what's working..
Abhishek Kumar
Associate III
November 28, 2017
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?

Tesla DeLorean
Guru
November 28, 2017
Posted on November 28, 2017 at 15:01

Perhaps you can IRQ on the error statuses?

Tips, Buy me a coffee, or three.. PayPal VenmoUp vote any posts that you find helpful, it shows what's working..