带有 STM32 HAL 驱动程序的 FreeRTOS 中的 UART 中断

UART Interrupts in FreeRTOS with STM32 HAL driver

我正在研究 STM32L152VB-A 控制器。我正在使用 FreeRTOS。
我使用 CubeMX 生成代码,并为 USART1 配置了全局中断。
非中断 RX 和 TX(HAL_UART_Receive 和 HAL_UART_Transmit)正在工作。
但我正试图让它与中断一起工作。

只有在我调用 HAL_UART_Receive_IT 之后,我才收到中断。
因为不知道接收数据的大小,所以打算一个一个地接收字符。

因为我用的是RTOS,所以我很迷茫写哪里HAL_UART_Receive_IT,消息随时都可能来。有人可以指导我吗??

PS: 我尝试在 ISR 中调用 HAL_UART_Receive_IT,但它也不起作用。

我认为您将 HAL_UART_Receive_IT 与实际接收任何内容的函数混淆了。不是这种情况。此函数仅启用 UART 外设及其接收中断。

如果您想坚持使用 HAL 库,您需要将类型为 UART_HandleTypeDef 的结构作为参数传递给 HAL_UART_Receive_IT,其中包含

  • a uint8_t* 指向接收缓冲区的指针
  • 您希望接收的元素数量的传输计数器

据我所知,使用此框架无法无限期地接收元素,因为一旦传输计数器达到零,接收中断就会自动禁用。因此,如果您需要这个,您最好自己编写 ISR,方法是覆盖 ST 定义的弱函数(很可能称为 "UARTx_IRQHandler")。

要最终在 FreeRTOS 中集成接收中断,您有两个选择:

  1. 像 HAL 一样将 ISR 中的数据接收到原始 (uint8_t*) 缓冲区中,并使用在访问时临时禁用接收中断的临界区。
  2. 使用中断安全 API 将 ISR 内的数据接收到 FreeRTOS 队列中。 official FreeRTOS book 第 6 章很好地解释了这一点。

我创建了以下任务(考虑高优先级):

void UARTReceiveTask(void const * argument)
{
  /* USER CODE BEGIN UARTReceiveTask */
  /* Infinite loop */
  for(;;)
  {
    osSemaphoreWait(BinarySemaphoreUARTHandle, osWaitForever);
    HAL_UART_Receive_IT(&huart3, message_received, 2);
  }
  /* USER CODE END UARTReceiveTask */
}

那么,如果你用的是HAL,你肯定知道HAL_UART_RxCpltCallback()是在UART ISR上执行的,所以我写了:

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart){
    if (huart->Instance == USART3){
        osSemaphoreRelease(BinarySemaphoreUARTHandle);
    }
}

我只是按照“精通 FreeRTOS”文档(第 6 章)中的提示推迟对任务的中断。

我没有深入研究,但我知道如果您使用 FreeRTOS 和 Arm Cortex 系统,这 info 很重要。

希望我有所帮助!