使用 HAL_UART_Receive_IT() 和 HAL_UART_RxCpltCallback() 时会丢失字节吗?

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

我有一些(主要是 CubeMX 生成的)代码:

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

这成功地回显了 USART3 上接收到的所有内容。 (这段代码只是一个学习串口的一次性例子。)

我担心 HAL_UART_RxCpltCallback() 被调用和 HAL_UART_Receive_IT() 设置下一次接收之间的时间。

STM32F103有没有什么特性可以保证在这个区间内不丢失数据?我没有在 USART 上找到超过两个字节的接收缓冲区的任何证据。

我特别担心某些优先级较高的 USB 设备 activity 可能会延迟 HAL_UART_RxCpltCallback() 的调用,因此可能会丢失一个或多个字符。

Quick answer:

HAL_UART_Transmit 是一个阻塞函数,因此,在它完成之前 HAL_UART_Receive_IT 不会被调用并且 uart 肯定会溢出。如果您担心任何其他中断会抢占您的执行,请在发出命令时使用 dma 或禁用麻烦的中断。您也可以提高 UART 中断优先级但是....

Hints:

...您不应在 HAL_UART_RxCpltCallback 内调用 HAL_UART_Transmit 和 HAL_UART_Receive_IT,因为您处于 ISR 模式。这会导致某些版本的 HAL 框架出现一些附带问题。最好设置一个标志并从主代码中检查它。

另外你真的应该避免使用 volatile,如果你使用像 gcc 这样的编译器障碍会更好__asm volatile("" ::: "memory")