Skip to main content
Visitor II
June 8, 2025
Question

STM32CubeH5 (v1.5.0) HAL_UART_Receive_IT Only Triggers Once (RxISR Pointer Cleared)

  • June 8, 2025
  • 1 reply
  • 376 views

Problem Description

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!

Symptoms

  • 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.

Root Cause?

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.

Workaround: Manually Restore huart->RxISR

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
 }
}

 

    This topic has been closed for replies.

    1 reply

    Super User
    June 8, 2025
    Visitor II
    June 8, 2025

    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...
     }
     }
    }
    Super User
    June 8, 2025

    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.