资料来源于硬件家园:资料汇总 - FreeRTOS实时操作系统课程(多任务管理)
一、调度器
1、合作式调度
单片机资源越来越丰富,加上合作式调度器的系统实时性不够好,合作式调度已经很少用了,FreeRTOS在新的版本中已不再更新
2、抢占式调度
抢占式调度器提供了一种多任务的的系统结构,高优先级任务可以抢占低优先级任务的CPU使用权,使得系统实时性非常好。使用抢占式调度器时,根据任务重要程度合理分配优先级,CPU会优先执行就绪列表中优先级最高的任务。
3、时间片轮转调度
时间片调度针对同优先级的任务,调度算法给同优先级的任务分配一个专门的列表,用于记录当前就绪的任务,并为每个任务分配一个时间片。
FreeRTOS不支持设置单任务CPU时间,每个任务CPU占用时间都是一样的
二、抢占式调度编程测试
1、测试方法
创建3个任务,情况如下:
任务1: 优先级低,阻塞,打印信息
任务2: 优先级中,运行时不阻塞,不挂起,闪灯
任务3: 优先级高,阻塞,打印信息
2、测试分析
因为任务2一直运行,不释放CPU,使得低优先级的任务1无法获得CPU使用权,而任务3优先高,可以抢占CPU获得运行。
三、时间片调度编程测试
1、测试方法
创建3个相同优先级的任务,打印信息,延时10ms,灯闪烁。 另外,方便测试,FreeRTOS的Tick设置为20,也就是每50ms进行一次系统调度。
2、测试分析
3个任务优先级相同,按时间片调度,调度时间为50ms,因此每个任务可以连续执行5次。
四、任务栈大小确认
1、粗略栈大小计算
在FreeRTOS的应用设计中,每个任务都需要独立的栈空间,而且每个任务需要的栈大小也是不同的。将如下的几个选项简单的累加就可以得到一个粗略的栈大小:
1、函数
① 局部变量 ② 函数形参 (针对函数嵌套) ③ 函数返回地址 (针对函数嵌套) ④ 函数内部的状态保存
2、任务切换
3、发生中断
2、栈大小确认
可以事先给任务分配一个大的栈空间,然后通过第二讲介绍的调试方法打印任务栈的使用情况,运行一段时间就会有个大概的范围了,再乘以安全系数(一般1.5-2.0),即可得到需要使用的栈空间。
五、任务栈溢出与检测
1、FreeRTOS栈溢出检测机制
方法一:使用方法一需要用户在 FreeRTOSConfig.h 文件中配置如下宏定义
#define configCHECK_FOR_STACK_OVERFLOW 1
在任务切换时检测任务栈指针是否过界了,如果过界了,在任务切换的时候会触发栈溢出钩子函数(钩子函数的主要作用就是对原有函数的功能进行扩展,用户可以根据自己的需要往里面添加相关的测试代码) void vApplicationStackOverflowHook( TaskHandle_t xTask, signed char *pcTaskName );
方法二:使用方法二需要用户在 FreeRTOSConfig.h 文件中配置如下宏定义:
#define configCHECK_FOR_STACK_OVERFLOW 2
任务创建的时候将任务栈所有数据初始化为 0xa5,任务切换时进行任务栈检测的时候会检测末尾的 16 个字节是否都是 0xa5,通过这种方式来检测任务栈是否溢出了。相比方法一,这种方法的速 度稍慢些,但是这样就有效地避免了方法一里面的部分情况。不过依然不能保证所有的栈溢出都能检测到,比如任务栈末尾的 16 个字节没有用到,即没有被修改,但是任务栈已经溢出了,这种情况是检测不到的。另外任务栈溢出后,任务栈末尾的 16 个字节没有修改,但是溢出部分的栈区数据被修改了,这部分栈区的数据不重要或者暂时没有用到还好,但如果是重要数据被修改将直接导致系统进入硬件异常,这种情况下,栈溢出检测功能也是检测不到的。
2、栈溢出编程测试
实验方法:在任务KEY_Task中申请过大的数组,模拟栈溢出的情况,检测到按键1按下时,对数组赋值,模拟产生系统硬件错误。 检测溢出后触发钩子函数,将发生栈溢出的任务打印出来。
①钩子函数配置,选择检测方法二
②在按键任务中作溢出操作
③当发生溢出并写入数据时会发生硬件错误