μC/OS-II的多任务系统实时性分析与优先级分配 02
![Rank: 8](images/default/star_level3.gif) ![Rank: 8](images/default/star_level3.gif)
- UID
- 872238
|
![](http://images.eccn.com/silabs/silicon_chip_980x60_202203.jpg)
μC/OS-II的多任务系统实时性分析与优先级分配 02
删除任务的办法不仅可获得共享的任务栈资源,而且也是一个方便中止某些应用程序的手段,前面提及的任何测试阶段按Exit键退出所有测试的动作,就可以依靠删除任务来实现。
把任务看作有大小的,这里的“大小”指需要“重入”到任务堆栈的变量的数量。如果每一个任务都使用相同大小的任务栈,对小任务而言显然是在浪费宝贵的RAM,大小可变的任务栈才是经济合理的。
首先,在os_cfg.h头文件中增加大、小两个宏参数,如果需要更多不同的栈大小,还可以继续增加参数。
#define MaxStkSize128//大任务栈
#define MinStkSize80//小任务栈
然后定义任务栈时使用它们:
OS_STK TaskDelStk1[MinStkSize];
OS_STK TaskDelStk2[MaxStkSize];
TaskDelStk1和TaskDelStk2是两个可删除任务所使用的任务栈,一个80字节,另一个128字节。
接下来是关键,要在任务堆栈初始化函数OSTaskStkInit中进行处理:定义一个全局整型变量STK_SIZE,创建任务前给它赋值,任务创建时执行的OSTaskStkInit函数用它来初始化模拟栈的长度。
修改前,OSTaskStkInit中的?C_XBP仿真堆栈指针(即模拟栈指针)的初始化语句如下:
*stk++ = (INT16U) (ptos + MaxStkSize) >> 8;//MaxStkSize是固定的栈长度
*stk++ = (INT16U) (ptos + MaxStkSize) & 0xFF;
注意:ptos是任务栈栈底,模拟栈从任务堆栈的另一头开始。
修改后变为:
*stk++ = (INT16U) (ptos + STK_SIZE) >> 8;//指针高8位
*stk++ = (INT16U) (ptos + STK_SIZE) & 0xFF;//指针低8位
创建任务前要给STK_SIZE赋予堆栈定义匹配的栈长度值,否则,会因为堆栈不能正确初始化导致任务崩溃。不同大小的任务栈结构如图2所示,可以看出区别在于模拟栈不同。
![](http://embed.chinaitlab.com/UploadFiles_4615/201306/20130624065124197.jpg)
图2 可变大小任务栈结构 利用可变大小任务栈创建一个小堆栈任务,示例如下:
STK_SIZE=MinStkSize;//提供堆栈大小值
/*创建带TimeLimit参数的,分配有任务栈TaskDelStk1,优先级为10的任务OverTime*/
OSTaskCreate(OverTime,(void*)&TimeLimit, &TaskDelStk1[0],10);
3.2 系统任务划分
用户任务分为两类: 一类任务是常驻任务,即创建后不用删除的任务;另一类是可删除任务,运行时建立,运行完删除,该任务资源又可用来创建新的任务。
4 任务优先级分配
优先级的合理分配围绕实时性要求进行,因为可用优先级较多,所以任务优先级之间可取较大间隔。这样当有更多的任务加入时,能安排在这些间隔中,不用改变已有任务的优先级。本系统中优先级关系可以按由高到低顺序依次排列: 键盘扫描任务,超时检测任务, A/D扫描转换任务,主任务,各通道测试任务,数据打印和传送任务,温度检测任务,日期时间显示任务,如图3所示。
![](http://embed.chinaitlab.com/UploadFiles_4615/201306/20130624065132389.jpg)
图3 任务关系示意图 常驻任务一般是固定优先级,而可删除任务每一次创建时却能够对应不同的任务函数和优先级,且使用同一个任务栈。
一个任务函数可用于多个任务,这种“重用”的特性在获得任务并行性的同时,最大限度地节约了代码。本系统只有一个测试函数,却构成了4个并行的通道任务。这些任务都是进入测试菜单后随着各自通道键被按下后在主任务中创建的,复用的4个测试函数接受任务创建时主任务传递过来的参数,为本通道的计算、显示、数据存储等一系列工作服务。
5 资源共享的处理
ADC0、LCD、打印机和串口等资源被4个测试任务所共享。资源共享有一些经典的方法(如信号量、全局变量等),需要根据实际需求灵活运用。
本系统的处理如下:
① 对于ADC0,在A/D扫描转换任务中每0.1 s轮流扫描4个通道一次,产生4个邮箱消息发往各自通道任务,以读取对应的转换结果。0.1 s的精确定时由定时器中断获得,中断服务发出信号量启动AD任务。一次扫描完成后A/D扫描转换任务挂起,直至下一次信号量到来。
② 对于LCD,情况要复杂一些,每个测试任务都要在LCD的各自区域显示,但是LCD不能实现2个以上位置同时进行显示处理,所以当涉及显示过程时需要禁止任务切换,否则会造成显示混乱。例如,当一个低优先级任务的显示工作还没有完成时,若发生了任务切换,则高优先级任务去进行另一个显示。当重新切换回低优先级任务后就没有办法继续未完的显示,因为显示位置已经被高优先级任务所改变。
③ 对于打印机和串口,也有类似的问题,不允许一个结果尚未打印完成又去打印另一个结果。禁止任务切换的办法不适合这里,因为打印和传送耗时比LCD显示长很多,禁止任务切换会影响到测试的实时性,它们单独建立后台任务的原因也在于此。
数据打印和传送任务循环扫描各个通道的请求服务标志,当标志有效时即为该通道服务,服务完毕清除该标志,因数据打印和传送任务的优先级较低而不会对其他测试任务造成任何影响。被服务的通道测试任务循环检测请求服务标志,检测到标志被清除后才可以继续下次测试,表示此次数据已经输出。其他高优先级测试任务不会影响打印过程,因为先检测到标志的通道独占资源,直至传送和打印完成后,打印任务才去检测下一个标志;高优先级任务的输出请求要等低优先级输出完毕才能得到响应,优先级反转在这里是正确的。
6 结论
本文从嵌入式系统的并行程序出发,结合实时性的要求,讨论了μC/OS-II操作系统环境下的任务划分和优先级确定的相关问题,提出了一些在μC/OS-II中用于减少资源耗用和同时运行的任务数量的改进措施。实践证明,这些措施可以充分发挥μC/OS-II小巧精悍的特点,提高程序代码的重用性,节约宝贵的RAM资源。
本系统与采用双通道测试、没有RTOS、采用前后台方式解决并行问题的方法比较[5],后者占用了54 KB代码,在人机界面和并行度上均不及前者。前者在加入了μC/OS-II和GUI,并能进行四通道测试的情况下,仅有59 KB代码;排除更大的汉字库容量后,实际代码大小几乎与原来相同,性能却有了很大的提高。 |
|
|
|
|
|