serial-portstm32usartstm32f1

Can bytes be lost when using HAL_UART_Receive_IT() and HAL_UART_RxCpltCallback()?


I have some (mostly CubeMX-generated) code:

volatile uint8_t buf[4];

int main(void)
{
    ...
    HAL_UART_Receive_IT(&huart3, buf, sizeof(buf));
    while (1)
    {
        /* USER CODE END WHILE */

        /* USER CODE BEGIN 3 */
    }
    /* USER CODE END 3 */
}

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) {
    if (huart->Instance == USART3) {
        HAL_UART_Transmit(&huart3, buf, sizeof(buf), 0xFFFF);
        HAL_UART_Receive_IT(&huart3, buf, sizeof(buf));
    }
}

This successfully echos everything which is received on USART3. (This code is just a throw-away example to learn about the serial port.)

I am concerned about the time between HAL_UART_RxCpltCallback() being called and HAL_UART_Receive_IT() setting up the next receive.

Is there any feature of the STM32F103 which guarantees that data won't be lost in this interval? I haven't found any evidence of more than a two byte receive buffer on the USART.

I am particularly concerned that some higher-priority USB-device activity might delay the calling of HAL_UART_RxCpltCallback(), and so one or more characters might be lost.


Solution

  • Quick answer:

    HAL_UART_Transmit is a blocking function, so, until it completes HAL_UART_Receive_IT is not called and the uart will surely go overflow. If you are worried of any other interrupt can preemt your execution, use dma or disable the troublesome interrupts while you issue the command. You could also rise UART interrupt priority but....

    Hints:

    ....you should not call HAL_UART_Transmit and HAL_UART_Receive_IT within HAL_UART_RxCpltCallback as here you are in ISR mode. This cause some side issues on certain versions of the HAL framework. Better to set a flag and check for it from the main code.

    Also you should really avoid the use of volatile, better if you use a compiler barrier like gcc __asm volatile("" ::: "memory")