带有 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 中集成接收中断,您有两个选择:
- 像 HAL 一样将 ISR 中的数据接收到原始 (uint8_t*) 缓冲区中,并使用在访问时临时禁用接收中断的临界区。
- 使用中断安全 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 很重要。
希望我有所帮助!
我正在研究 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 中集成接收中断,您有两个选择:
- 像 HAL 一样将 ISR 中的数据接收到原始 (uint8_t*) 缓冲区中,并使用在访问时临时禁用接收中断的临界区。
- 使用中断安全 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 很重要。
希望我有所帮助!