2025-04-16 11:52 AM - edited 2025-04-16 11:52 AM
Hello ST Community,
I’d like to report an issue observed with HAL_UARTEx_ReceiveToIdle_DMA() on STM32L433RCT6P using STM32CubeIDE v1.17.0 and the latest STM32CubeMX code generator (L4 series).
Setup:
Board: NUCLEO-L433RC-P
IDE: STM32CubeIDE 1.17.0
HAL version: STM32CubeL4 latest
UART: USART2
DMA Mode: Circular
Baudrate: 115200
Buffer size: 128 or 256
Code: Generated with CubeMX
Call MX_USART2_UART_Init()
Immediately call HAL_UARTEx_ReceiveToIdle_DMA() without delay
Do not send any UART data to the board
Wait...
The callback HAL_UARTEx_RxEventCallback() should not trigger until at least one byte has been received, followed by line idle.
Immediately after startup, without any incoming UART data:
The callback fires once
Size == RX_BUFFER_SIZE (e.g., 128 or 256)
The issue doesn't occur at very low system clock frequencies
On STM32L4 series: it triggers when running on HSI (16 MHz)
When using MSI @ 4 MHz, the issue does not occur
On STM32U5 series (e.g., STM32U595), the threshold frequency differs but the pattern is the same
As part of building high-quality embedded platforms, we aim to avoid:
Arbitrary HAL_Delay() or for(__NOP()) hacks
Fragile time-based fixes that behave differently across platforms or temperature/voltage conditions
We need a deterministic solution to prevent this false RX interrupt on startup.
Reproduction Snippet: (A simple example code snippet)
#define RX_BUFFER_SIZE 128
uint8_t aRXBufferUser[RX_BUFFER_SIZE];
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_DMA_Init();
MX_USART2_UART_Init();
HAL_UARTEx_ReceiveToIdle_DMA(&huart2, aRXBufferUser, RX_BUFFER_SIZE);
while (1) {}
}
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{
//echo back the received size
uint8_t low = Size & 0xFF;
while (!(__HAL_UART_GET_FLAG(huart, UART_FLAG_TXE))) {}
huart->Instance->TDR = low;
}
Why does HAL_UARTEx_RxEventCallback() trigger immediately with Size == buffer_size, even though no data was received?
Attached Video Evidence:
I’ve attached a short video demonstrating the issue:
When using MSI @ 4 MHz, no interrupt is triggered → expected behavior
When switching to HSI @ 16 MHz, the interrupt fires immediately after HAL_UARTEx_ReceiveToIdle_DMA()→ even though no data is received
The video shows a breakpoint inside HAL_UARTEx_RxEventCallback() and proves the size equals the buffer length, with no bytes transferred by DMA.
2025-05-06 8:03 AM
Hello @Abhimanyu,
When the DMA is configured in circular mode, the callback associated with HAL_UARTEx_ReceiveToIdle_DMA() is executed during three events:
At higher frequencies, the callback may trigger prematurely because the IDLE flag is set as soon as the UART is enabled, and its reset process may be skipped due to high frequency. If this flag isn't reset before the DMA starts, it can lead to premature callback execution.
To mitigate this, you can introduce a delay after MX_USART2_UART_Init() to allow the IDLE flag to reset in the USART ICR before transmission begins. However, this approach lacks robustness. Alternatively, ensure the flag is reset before invoking HAL_UARTEx_ReceiveToIdle_DMA(&huart2, aRXBufferUser, RX_BUFFER_SIZE) by using the following code:
while (__HAL_UART_GET_FLAG(&huart2, UART_FLAG_IDLE) != SET);
__HAL_UART_CLEAR_FLAG(&huart2, UART_CLEAR_IDLEF);
Kind regards,