2025-06-08 4:58 AM
I am having some trouble using HAL_UART_Receive_IT() to receive UART data in interrupt mode, the callback HAL_UART_RxCpltCallback() only triggers once for the first byte, subsequent bytes do not trigger the interrupt. I don't know if there is some problem with my implementation or if the problem is in STM32CubeH5 (v1.5.0). I would really appreciate some help!
HAL_UART_RxCpltCallback() executes correctly for the first received byte.
Calling HAL_UART_Receive_IT() again does not fix the issue.
No further interrupts are generated, even though UART data is arriving.
I did some digging and found the UART interrupt handler (UART_RxISR_8BIT) clears the RxISR function pointer (huart->RxISR = NULL) after processing the first byte. This prevents the interrupt from being handled correctly again, even if HAL_UART_Receive_IT() is called again.
To workaround this, I added one line to manually reassign huart->RxISR in the HAL_UART_RxCpltCallback(), when I do this I get the expected behavior:
uint8_t rx_byte; // Single-byte buffer for interrupt mode void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { if (huart == &huart2) { // Process the received byte (e.g., store or print) printf("Received: %c\n", rx_byte); // FIX: Restore the RxISR function pointer huart->RxISR = UART_RxISR_8BIT; // Use UART_RxISR_16BIT for 16-bit mode // Restart interrupt-based receive HAL_UART_Receive_IT(huart, &rx_byte, 1); } } int main() { HAL_Init(); SystemClock_Config(); MX_USART2_UART_Init(); // Start the first interrupt-based receive HAL_UART_Receive_IT(&huart2, &rx_byte, 1); while (1) { // Main loop does other tasks } }
2025-06-08 6:11 AM
This can't be right. The RxISR gets set when you call HAL_UART_Receive_IT.
2025-06-08 1:53 PM - edited 2025-06-08 2:11 PM
Yes, you're absolutely right, HAL_UART_Receive_IT() sets RxISR when called, thanks for this insight. It seems although I checked this fix "worked" I was just barking up the wrong tree. The issue described in the original post actually occurs when an Overrun Error occurs since I haven't handled overrun this error isn’t cleared, which prevents HAL_UART_Receive_IT() from working correctly afterward. I guess I need to implement HAL_UART_ErrorCallback() to clear this error?
void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart)
{
if (huart->Instance == USART2) {
// Handle overrun error
if (huart->ErrorCode & HAL_UART_ERROR_ORE) {
// Clear the overrun error flag
__HAL_UART_CLEAR_OREFLAG(huart);
// Maybe log or handle the error here...
}
}
}
2025-06-08 2:38 PM
Yes, it's good to handle the ORE error but really you should address why you're getting it in the first place. It's not normal for this to occur.
Don't use blocking functions in the interrupt handler--if you receive 2+ more characters before it returns, you will get an overrun. The printf statement is likely the culprit.