Electronic – In STM32, How to check the UART Serial Buffer If They Are Available using HAL Library

hal-libraryserialstm32uart

I am using STM32F429 in my project which connects to an ATmega2560 thru UART. In arduino, there is a function Serial.Available() to check if the serial buffer is empty or not.

Is there a function in STM32 that is similar to Serial.Available() in Arduino?

BTW, I am using HAL libraries in STM32CubeIDE and HAL_UART_Receive(huart, pData, Size, Timeout) to read the contents of UART buffer.

Please help. Thanks!

PS. I've read the documentation in HAL library but I'm not sure if there is one. I've looked into HAL_UART_GetState but Im not sure.

Best Answer

AFAIK there is no similar function in HAL. The common way to do it is:

// index of first unread byte in the RX buffer
static uint32_t rxpos = 0;
// find end of data position in the RX buffer
uint32_t pos = rxsize - puart->hdmarx->Instance->CNDTR;
// pass accumulated bytes to listener
if (pos != rxpos) {
    if (pos > rxpos) {
        // Process data directly by subtracting indexes
            processData(rxbuffer + rxpos, pos - rxpos);
        } else {
        // First process data to the end of the buffer
            processData(rxbuffer + rxpos, rxsize - rxpos);
        // Continue with beginning of the buffer
            processData(rxbuffer, pos);
        }
}
// update starting index
rxpos = (pos == rxsize)? 0 : pos;

You can call the above code from HAL_UART_RxHalfCpltCallback, HAL_UART_RxCpltCallback and, if you have code for processing either IDLE or RTO events, from corresponding handlers as well.

Note that current HAL implementation treats RTO as an error, eliminating the possibility to handle it properly. You'd have to bypass that if you want to get circular DMA transfers handled without added latency.

UPDATE

To answer your question in comments, please note that checking for available bytes in a buffer and using blocking HAL_UART_Receive call are two different approaches. You did not specify baud rate or whether or not you have variable message length. These two really define correct method of doing things in STM32.

But in general, you either need low latency communication, or you don't care how long it takes and your code has nothing to do meanwhile.

In the former case you have to use either interrupt or circular DMA versions of Receive function. With DMA you can check for available data length as described above.

In the latter you can do a loop calling blocking Receive which will either give you expected data or will time out. At low speeds you may even be better handling incoming data byte by byte in UART interrupt handler.

The methods available to you are quite different from Arduino approach. I would suggest to follow the examples available for HAL instead of trying to fit HAL functions into Arduino perspective.