2025-06-04 5:42 AM - edited 2025-06-04 7:22 AM
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 ?
2025-06-04 5:47 AM
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.
2025-06-04 6:01 AM
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.
2025-06-04 6:51 AM
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.
2025-06-04 7:31 AM
By TC, I mean HAL_UART_RXEVENT_TC, as I wrote in my first message. TC stands for “Transfer Complete,” not “Transmit Complete.” But that's not the point.
You are right that it is better to write your own driver. That is exactly what I did. But I still have one question. How can we tell that we have received a data packet if its size matches the buffer size? Yes, this situation is unlikely, but it is still possible, and I would like to be able to distinguish between these two events somehow.
2025-06-04 7:34 AM
Ahh, nonblocking mode. I misread.
If DMA is in non-circular mode, it will complete immediately when the buffer is filled. No IDLE event is processed as the transfer is already done.
In circular mode, there could be an issue. It will definitely trigger TC, but may or may not trigger IDLE later on. There used to be a bug where it did not do this, but there has been some work on it and it may have been fixed.
2025-06-04 8:07 AM - edited 2025-06-04 8:10 AM
Hmm... I don't have the code in front of me now, but in general - just like you resolve most of race conditions. The most important - check the events in correct order. In this case: when the timeout event occurs before the TC, you want to check if the transfer is in fact fully completed, if so - ignore the timeout and handle the data. With DMA, there are more than one interrupt vectors, so priorities must match to avoid one of them preempt another. If you suspect that the race condition in the HAL library is handled incorrectly (leads to data loss or crash) please say so.
2025-06-04 8:33 AM
Thank you! If I understand correctly, only a TC event is generated when the buffer is filled (unless we are in cyclic DMA mode). And if packet reception has ended at the moment the buffer is filled, the IDLE event will no longer be generated. So we need to find some other way to determine the end of packet reception if the packet length is equal to the buffer length? If so, do you know of any other methods for determining the end of packet reception besides the IDLE event?
2025-06-04 8:43 AM - edited 2025-06-04 8:44 AM
> And if packet reception has ended at the moment the buffer is filled, the IDLE event will no longer be generated.
Have you verified that? Is that what happens on the latest library version?
2025-06-05 4:34 PM
You can test for the RxEventType
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{
if(huart == &huart2)
{
if(huart->RxEventType == HAL_UART_RXEVENT_TC)
{
}
else if(huart->RxEventType == HAL_UART_RXEVENT_IDLE)
{
}
else if(huart->RxEventType == HAL_UART_RXEVENT_HT)
{
}
}
}