最近做项目时使用到了FreeRTOS,之前是通过手动移植源码的方式完成的,这次习惯性的使用Keil自带的包管理器创建工程,结果踩了巨多的坑,浪费了大量的时间在调试上,特此记录一下。
首先说明一下我创建工程的过程:

1.使用CudeMX生成工程文件。注意这里没有将FreeRTOS这些组件包括进去,仅仅生成HAL库相关代码。
2.使用Keil创建FreeRTOS工程,包管理器的选择如下:
屏幕截图 2024-10-18 195912.png
3.将CubeMX生成代码的有用部分重组,变为我习惯的代码编写形式。
4.开始编写工程。

这里遇到了第一个问题:

haltick设置

在CubeMX生成代码时,如果你选中了FreeRTOS的组件,那么它大概率会提醒你:
1cb0a4bc843340723b9fda91e31e3cb1.png
说是不建议OS和HAL同时使用SysTick作为系统节拍。
使用了FreeRTOS会强制使用systick作为自己的心跳,这个os_tick的优先级是最低的,它主要的作用就是OS任务调度,时间片查询等工作。如果HAL也设置成systick,优先级最低,那么在高优先级(优先级高于systick) 中断服务函数中调用HAL_Delay()就会导致错误。
于是我把HAL时钟设为了TIM11。

紧接着就遇到了第二个问题

中断优先级分组和配置最低中断优先级

我之前一直不知道FreeRTOS是如何配置中断分组的,只是看野火资料说分组为4,就一直这么用的。这次就出问题了:只要一添加第二个任务系统马上就进入HardFault_Handler(),这个问题困扰了我好几天。发现将OS的Tickless功能关闭后问题就消失了,刚以为解决了问题,移植LVGL中发现会随机进入HardFault_Handler(),于是不得不仔细检查。
FreeRTOS只能处理抢占优先级,因此将中断组设为4以外的会使得子优先级失去意义,因此,在FreeRTOS工程中的中断只有0~15的抢占优先级。
FreeRTOSConfig.h文件中涉及到了中断配置,其注意问题在注释中已写出:

/* Cortex-M specific definitions. */
#ifdef __NVIC_PRIO_BITS
  /* __NVIC_PRIO_BITS will be specified when CMSIS is being used. */
  #define configPRIO_BITS                     __NVIC_PRIO_BITS   //这里要注意,需要手动包含stm32fxxx.h文件,不然configPRIO_BITS的值就会为3,导致配置错误
#else
  /* 7 priority levels */
  #define configPRIO_BITS                     3
#endif

/* The lowest interrupt priority that can be used in a call to a "set priority" function. */
#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY       7  //这里是最最坑的地方,他把最低优先级设为了7!!!导致一旦引入优先级为15的HAL_Tick中断,就会出现不可预料的问题!应该为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))

任务堆栈大小

创建LVGL任务后,发现有一个任务进入一次后就再也不会进入了。
这也是一个比较有意思的地方:FreeRTOS+LVGL中某个任务运行异常可能是其他任务的堆栈不足导致的!
将其他任务的堆栈调大后问题便解决。