STM32 HAL_UART_Transmit_DMA issues


I met a strange issue and wish to get help.

I wish to connect PC by UART. I try to use DMA but failed.

The following is my test code for DMA.

main () {

initialization code from CubeMX

HAL_UART_Transmit_DMA(&UART_Handle_Console, (uint8_t*)(listbuffer), len);

while ( HAL_UART_GetState(&UART_Handle_Console) != HAL_UART_STATE_READY);

HAL_UART_Transmit_DMA(&UART_Handle_Console, (uint8_t*)(listbuffer), len);

while ( HAL_UART_GetState(&UART_Handle_Console) != HAL_UART_STATE_READY);



If comment out vTaskStartScheduler, everything is OK.

If leave vTaskStartScheduler, the first DMA statement can run but PC got nothing. The second DMA statement cannot run because HAL_UART_GetState(&UART_Handle_Console) is always busy TX.

The above is my test code . My purpose is to use binary semaphore to control UART DMA connected to PC.


[please ensure your code is formatted as code, you can do that using the “preformatted” button in the text editor, or by adding “```” (without the quotes) above and below the code snippet).

Is what you pasted in the entire code, or just a subset of it? Is your DMA using interrupts - if so be aware interrupts will get disabled between any calls to FreeRTOS API functions and the scheduler being started. Where are the transmit buffers allocated - be aware the stack allocated to main no longer exists once the scheduler is started.

I wonder how invoking vTaskStartScheduler (or not) after the DMA transfers can change the behavior of the preceding code. That’s impossible. Except something else is heavily broken in your code or the code posted isn’t exactly the same you’re running.

If I remember correctly, the stack that main() uses is destroyed once the vTaskStartScheduler() called. I don’t know HAL, but I assume this may affect the those HAL functions.

Normally, the code that runs before calling vTaskStartScheduler() should only initialize the system. Everything else must be done in tasks. I guess this is the assumption of FreeRTOS so it thinks that stack of main() is no longer in use and can be salvaged. I don’t know the internals of the FreeRTOS but I think it’s possible by modifying/resetting main stack pointer manually.

Indeed e.g. for Cortex-M ports the MSP is reset when the scheduler starts. That means that no local stack variables should be given as task (pointer) arguments because they might likely get corrupted.
However, this happens when the scheduler (the 1st task) is started but not earlier.
So sequential code before the start runs as programmed.

This is on now. Point #3 in the second numbered list :grinning:

1 Like

I use STM32F407. I copied FreeRTOSConfig from demo. The heap size is 75K. According to your suggestion, I resize the heap size to 48K. It is OK. Then I used binary semaphore to control console output, namely, each task should take the binary semaphore before output from console, TX complete ISR give the binary semaphore. Everything is OK now.

Thanks for your great support!