1、为什么不推荐使用systick作为HAL时钟源?
在FreeRTOS中默认使用systick作为时钟源,并将systick的中断优先级强制设置为最低;如果HAL时钟使用的是systick,那么在某个中断优先级较高的中断中调用了HAL_Delay,系统就会死掉!
一般的解决方案就是:使用TIM6或者TIM7作为HAL时钟,并将其优先级设置较高(至少要比调用了HAL_Delay的中断的优先级高),也可以简单的将其优先级设置为最高即可。
2、OS的tick设置多少合适?
一般的OS默认tick为1ms,这个需要根据具体应用场景来权衡,一般需要考虑的因素有:
1、 是否存在较多的任务都必须及时处理,且及时性都小于tick时间;
2、 tick设置太小,任务切换频繁,导致大量时间花在调度器上;
3、 tick设置太大,任务切换较慢,导致实时性要求较高的任务没能及时执行;
3、configMAX_PRIORITIES设置多少合适?
在部分OS中会对configMAX_PRIORITIES的上限做限制,而FreeRTOS通常情况下没有限制,但在打开configUSE_PORT_OPTIMISED_TASK_SELECTION配置以后,会限制其最大不超过32;但该数量宜少不宜多,多了会导致内核需要更多的RAM空间;一般15以内是够用的,最好在7个以内。FreeRTOS在cmsis_os.h中仅分配了7个优先级:
/// Priority used for thread control.
/// \note MUST REMAIN UNCHANGED: \b osPriority shall be consistent in every CMSIS-RTOS.
typedef enum {
osPriorityIdle = -3, ///< priority: idle (lowest)
osPriorityLow = -2, ///< priority: low
osPriorityBelowNormal = -1, ///< priority: below normal
osPriorityNormal = 0, ///< priority: normal (default)
osPriorityAboveNormal = +1, ///< priority: above normal
osPriorityHigh = +2, ///< priority: high
osPriorityRealtime = +3, ///< priority: realtime (highest)
osPriorityError = 0x84 ///< system cannot determine priority or thread has illegal priority
} osPriority;
4、为什么必须要有idle任务?
我们的OS要想持续运行下去,就必须要至少有一个任务,且该任务的优先级必须最低。原因分析如下:
1、如果OS当前没有可以运行的任务,调度器将没任务可调度,不同的OS将会有不同的死法:要么OS崩溃,因为TCB列表是空的;要么程序退出void vTaskStartScheduler( void );
2、如果idle任务发生阻塞,就导致调度器无任务可调度,OS可能会发生故障。
5、为什么任务退出前必须显示将该任务删除?
void taskFunction(void *param)
{
for(;;)
{
……
}
vTaskDelete(NULL);
}
可以试想:如果该任务退出时没有将该任务从TCB列表中删除,会发生什么?
这种情况下,上面代码就相当于只是一个普通函数,函数执行结束后会执行出栈、跳转等系列操作。由于当前栈空间是该任务的栈空间,出栈结束时候基本就是栈底击穿时间,下一步就是噩耗发生时候:不知道会给PC指针赋值多少!
6、如何判断任务栈空间分配是否合适?
一般,如果出现任务执行一段时间后莫名其妙就进hardfault,找不出代码上的逻辑问题、指针越界问题、字节对齐问题、非法访问问题……其实早就可以优先排除是不是栈顶击穿,排查方法也很简单:看栈顶附近是不是都被填充了非预期数据。
没有哪一种方法可以简单的确定任务到底需要多大空间,一般的经验都是先搞一个大点的栈空间,跑几下子看用了多少,然后在开发前期、后期、结束等过程中,查询栈使用情况,根据经验给一定余量的空间;
7、调度算法简介
1、基于优先级:每个任务都有一个优先级;
2、基于状态:运行状态Running、阻塞状态Blocked、挂起状态Susoended、就绪状态Ready;
3、同一时间有且只有一个任务处于运行状态
4、总是选择优先级最高的就绪态任务进入运行状态。