之前做项目时,使用GD32F303并移植了freertos。移植过程网上有很多教程,根据这些教程移植就可以。移植完后注意FreeRTOSConfig.h中关于RTOS中断管理的设置。 我移植时在官网下的是当时最新的RTOS版本为:FreeRTOS V202112.00。 移植完后,建立了4个任务,测试没有问题。进行了后续代码编写。在做CAN中断时,使和了二值信号量,测试了下没有问题。但在长时间运行测试时,出现的CAN任务死机(假死)现象。这个坑让我好苦恼,由于项目急没有办法CAN中断最后没有使用二值信号量。
后来有时间仔细研究了下FreeRTOSConfig.h文件,发现之前的中断管理设置不对。
在官网下的 FreeRTOS V202112.00版FreeRTOSConfig.h文件关于中断管理内容如下:
/* This is the raw value as per the Cortex-M3 NVIC. Values can be 255
(lowest) to 0 (1?) (highest). */
#define configKERNEL_INTERRUPT_PRIORITY 255
/* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!!
See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */
#define configMAX_SYSCALL_INTERRUPT_PRIORITY 191 /* equivalent to 0xb0, or priority 11. */
/* This is the value being used as per the ST library which permits 16
priority values, 0 to 15. This must correspond to the
configKERNEL_INTERRUPT_PRIORITY setting. Here 15 corresponds to the lowest
NVIC value of 255. */
#define configLIBRARY_KERNEL_INTERRUPT_PRIORITY 15
这段代码设置的中断管理范围为:11~15
在我的项目中CAN中断的优先级为0。
nvic_irq_enable(USBD_LP_CAN0_RX0_IRQn,0,0);/* configure CAN0 NVIC */
经过查阅资料与使用STM32cubeMX生成代码测试,基本确定问题所在。
引用《FreeRTOS源码详解与应用---基于STM32》这本书中关于【FreeRTOS中断配置宏】中的一段话和图片。
低于configMAX_SYSCALL_INTERRUPT_PRIORITY 191(equivalent to 0xb0, or priority 11)这个优先级的中断可以安全的调用 FreeRTOS API函数,高于此优先级的中断FreeRTOS是不能禁止的,中断服务函数不能调用 FreeRTOSR 的API函数。
之后又参考了下STM32cubeMX生成的带有FreeRTOS的代码FreeRTOSConfig.h中关于中断管理设置,代码如下:
/* Cortex-M specific definitions. */
#ifdef __NVIC_PRIO_BITS
/* __BVIC_PRIO_BITS will be specified when CMSIS is being used. */
#define configPRIO_BITS __NVIC_PRIO_BITS
#else
#define configPRIO_BITS 4
#endif
/* The lowest interrupt priority that can be used in a call to a "set priority"
function. */
#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY 15
/* The highest interrupt priority that can be used by any interrupt service
routine that makes calls to interrupt safe FreeRTOS API functions. DO NOT CALL
INTERRUPT SAFE FREERTOS API FUNCTIONS FROM ANY INTERRUPT THAT HAS A HIGHER
PRIORITY THAN THIS! (higher priorities are lower numeric values. */
#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 5
/* Interrupt priorities used by the kernel port layer itself. These are generic
to all Cortex-M ports, and do not rely on any particular library functions. */
#define configKERNEL_INTERRUPT_PRIORITY ( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
/* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!!
See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */
#define configMAX_SYSCALL_INTERRUPT_PRIORITY ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
我们可以看到这里将中断管理范围设置为:5~15
再查看STM32cubeMX创建的CAN外设的初始化关于中断的设置,
/* CAN1 interrupt Init */
HAL_NVIC_SetPriority(USB_LP_CAN1_RX0_IRQn, 5, 0);
HAL_NVIC_EnableIRQ(USB_LP_CAN1_RX0_IRQn);
STM32cubeMX创建的UART5外设的初始化关于中断的设置,
/* UART5 interrupt Init */
HAL_NVIC_SetPriority(UART5_IRQn, 5, 0);
HAL_NVIC_EnableIRQ(UART5_IRQn);
中断优先级都为5,这样在中断中使用FreeRTOS的API经过测试没有出现 假死 现象。
综上所述。移植FreeRTOS后要注意中断管理设置,否则会出现想不到的结果,给我们的测试、调试带来不可预测的 。。。坑~!
这里仅仅表达我对FreeRTOS中断管理的理解,有不足之处请多指教~!希望我的写的东西能对您有所帮助~!