UART: HAL_UART_ErrorCallback is not called reliably
Meravid opened this issue · 3 comments
Caution
The Issues are strictly limited for the reporting of problem encountered with the software provided in this project.
For any other problem related to the STM32 product, the performance, the hardware characteristics and boards, the tools the environment in general, please post a topic in the ST Community/STM32 MCUs forum
Describe the set-up
- STM32H7B3ZIT6
- STM32CubeIDE
- Version: 1.10.1
- Build: 12716_20220707_0928 (UTC)
- STM32CubeMx
- Version: 6.8.1
Describe the bug
The HAL_UART_ErrorCallback
is not called reliably, if a frame or noise error occurs.
Background: The device is receiving several messages via UART with a wrong baudrate. Hence, HAL_UART_ErrorCallback
is called, which is used to recover from the error and keep the UART reception alive for new messages. But HAL_UART_ErrorCallback
is not always called, sometimes after the second or third or ... message HAL_UART_ErrorCallback
is not called although the UART handle indicates a error by its member ErrorCode
.
How To Reproduce
-
Indicate the global behavior of your application project:
UART reception and transmission in DMA mode in two different threads.- UART configuration:
HAL_UARTEx_ReceiveToIdle_DMA
is used for DMA reception
- UART configuration:
-
The modules that you suspect to be the cause of the problem (Driver, BSP, MW ...)
- HAL UART
-
The use case that generates the problem
- Reception of several messages with wrong baudrate
-
How we can reproduce the problem
- Send ten messages in a row with a delay of 500 ms between each with a wrong baudrate to the device.
- Send ten messages in a row with a delay of 500 ms between each with correct baudrate to the device.
- Important: This error is not occurring in 100 % percent the test cases. But occurs at least in 80%.
Additional context
The workaround which worked is to poll cyclic the ErrorCode of the UART and reset the UART reception in a case of error.
Things which didn't help.
Reinitialize in interrupt context
extern "C" void HAL_UART_ErrorCallback(UART_HandleTypeDef* huart)
{
if(huart->Instance == mcu.uart_debug().GetInstance())
{
HAL_UARTEx_ReceiveToIdle_DMA(&huart4, (uint8_t*)rxBuffer, size);
// Disable half complete interrupt
__HAL_DMA_DISABLE_IT(_handle.hdmarx, DMA_IT_HT);
}
}
extern "C" void HAL_UART_ErrorCallback(UART_HandleTypeDef* huart)
{
if(huart->Instance == mcu.uart_debug().GetInstance())
{
HAL_UART_DeInit(&huart);
HAL_UART_Init(&huart);
HAL_UARTEx_ReceiveToIdle_DMA(&huart4, (uint8_t*)rxBuffer, size);
// Disable half complete interrupt
__HAL_DMA_DISABLE_IT(_handle.hdmarx, DMA_IT_HT);
}
}
Set an event in interrupt and reinitialize in normal thread context
Screenshots
If applicable, add screenshots to help explain your problem.