Skip to main content
Explorer
June 4, 2025
Question

Work of the HAL_UARTEx_ReceiveToIdle function in non blocked mode

  • June 4, 2025
  • 2 replies
  • 977 views

Hi all! What event is generated if the MCU receives a data packet equal to the buffer value passed to the HAL_UARTEx_ReceiveToIdle_IT (or HAL_UARTEx_ReceiveToIdle_DMA) function? There will essentially be two events: HAL_UART_RXEVENT_TC and HAL_UART_RXEVENT_IDLE . But which of them will be available in the HAL_UARTEx_RxEventCallback ?

    This topic has been closed for replies.

    2 replies

    Super User
    June 4, 2025

    Please use english on this forum.

    > Hi all! What event is generated if the MCU receives a data packet equal to the buffer value passed to the function HAL_UARTEx_ReceiveToIdle_IT (or HAL_UARTEx_ReceiveToIdle_DMA)? In fact, there will be two events: HAL_UART_RXEVENT_TC and HAL_UART_RXEVENT_IDLE. But which one will be available in HAL_UARTEx_RxEventCallback ?

     

    Whichever one occurs first. If the buffer is filled, function returns immediately. If IDLE happens, function returns. The RxSize parameter is updated with the number of characters received. If it's equal to Size, the buffer is full and TC happened. Otherwise, IDLE happened.

     * @note HAL_OK is returned if reception is completed (expected number of data has been received)
     * or if reception is stopped after IDLE event (less than the expected number of data has been received)
     * In this case, RxLen output parameter indicates number of data available in reception buffer.

     

    ADrub.1Author
    Explorer
    June 4, 2025

    Thanks for the reply!)

    Yes, I know that. The question is slightly different here. For example, I called the HAL_UARTEx_ReceiveToIdle_IT() function and passed a buffer size of 100 bytes. Then we received a packet of exactly 100 bytes. So, the question is, which event will be generated? After all, two events actually occurred!)

    I'm asking this to understand how to recognize that we have received a packet if it is exactly the same size as the buffer.

    Super User
    June 4, 2025

    A good question. There's a race condition as you have seen. As soon as the HAL "driver" sees completion of I/O (enough bytes received) it disables all interrupt sources, including the IDLE (or RTO if used). These interrupts share the same vector so cannot preempt one another. But the interrupt handler can test for IDLE before checking end of transfer. By the way TC is *transmit* complete and you deal with receive? 

    Bottom line, better write your own "driver" using the HAL as reference. This will suit your needs much better and will avoid confusion about the HAL library peculiarities. Examples are available.

     

    Super User
    June 6, 2025

    I tested this on the F4. It works exactly as expected. No IDLE events are missed.

    Sending 4 bytes at a time into a 16 byte buffer. event: (0=HT, 1=TC, 2=IDLE).

    event=2, tail=0, head=4
    event=1, tail=4, head=8
    event=2, tail=8, head=8
    event=2, tail=8, head=12
    event=0, tail=12, head=16
    event=2, tail=16, head=16
    event=2, tail=16, head=4
    event=1, tail=4, head=8
    event=2, tail=8, head=8
    event=2, tail=8, head=12
    event=0, tail=12, head=16
    event=2, tail=16, head=16

     

    void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
    {
     static uint16_t tail = 0;
     /* Prevent unused argument(s) compilation warning */
     UNUSED(huart);
     UNUSED(Size);
     HAL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin);
     HAL_UART_RxEventTypeTypeDef event = HAL_UARTEx_GetRxEventType(huart);
     printf("event=%d, tail=%d, head=%d\n", (int)event, (int)tail, (int)Size);
     tail = Size;
    }

     

    Graduate II
    June 6, 2025

    @TDK wrote:

    I tested this on the F4. It works exactly as expected. No IDLE events are missed.

    Sending 4 bytes at a time into a 16 byte buffer. event: (0=HT, 1=TC, 2=IDLE).

    event=2, tail=0, head=4
    event=1, tail=4, head=8
    event=2, tail=8, head=8
    event=2, tail=8, head=12
    event=0, tail=12, head=16
    event=2, tail=16, head=16
    event=2, tail=16, head=4
    event=1, tail=4, head=8
    event=2, tail=8, head=8
    event=2, tail=8, head=12
    event=0, tail=12, head=16
    event=2, tail=16, head=16

    I noticed your event values didn't match your labeling based off receiving 4 bytes at a time.  

    You have TC and HT values swapped.

    /**
     * @brief HAL UART Rx Event type definition
     * @note HAL UART Rx Event type value aims to identify which type of Event has occurred
     * leading to call of the RxEvent callback.
     * This parameter can be a value of @ref UART_RxEvent_Type_Values :
     * HAL_UART_RXEVENT_TC = 0x00U,
     * HAL_UART_RXEVENT_HT = 0x01U,
     * HAL_UART_RXEVENT_IDLE = 0x02U,
     */
    typedef uint32_t HAL_UART_RxEventTypeTypeDef;

    Super User
    June 6, 2025

    Yes, my typo, not HAL's bug. Thanks for catching.