您当前的位置:五五电子网电子知识单片机-工控设备嵌入式系统-技术setjmp构建简单协作式多任务系统 正文
setjmp构建简单协作式多任务系统

setjmp构建简单协作式多任务系统

点击数:7680 次   录入时间:03-04 11:48:07   整理:http://www.55dianzi.com   嵌入式系统-技术
}

else tcb[tskid].entry(tcb[tskid].argc,tcb[tskid].argv);

return 0;

}

3 代码说明

任务代码通过执行setjmp设置本任务下次查询时的返回点,然后在等待条件放弃掉CPU跳转到下一任务的返回点处执行。如此周而复始,让各任务都获得轮转运行的机会,也要求各任务都需要主动通过等待条件的方式放弃掉CPU。系统中除了中断服务程序之外,所有任务都是平等的,都应该遵循同样的规则和其它任务一起协作运行。基本系统中没有设计杀死任务的调用,这要求各任务都应当设计成某种形式的无限循环。

任务中等待的条件可以是任务复杂的表达式或都函数调用,也可以是中断服务程序设置的全局变量(注意加volatile定义)。一般在任务执行时会让下次等待的条件不再满足,避免某个任务一直霸占CPU将系统饿死。在嵌入式软件中还经常会遇到任务定时启动和超时等待在I/O操作上,在我们的系统中可以维护一个时间计数器,只需在适当的地方记录时刻,然后在任务查询条件中判断当前计数器和记录时刻之间的差值就可以了。

内核实现的代码则相当简法。由于主要的保护和恢复任务现场的工作都由C语言标准库setjmp实现了,我们就只需要操纵一下堆栈指针防止不同的任务使用了重叠的局部环境,这个工作在初始化和创建任务的时候通过预定义的两个宏来实现。在init_coos函数中,记录了主任务(main函数)保留mainstk字节堆栈后的新栈顶位置(stktop),然后在每次creat_task时都根据要求为每个任务保留stksize字节的堆栈并重新计算下一个stktop。在creat_task函数中利用了setjmp函数的返回值(直接返回时为0,longjmp跳转返回时非0),使得一方面creat_task能正常回到调用者,又让下次轮转到新任务时能够找到创建时的入口。

co-os.h中定义的WAITFOR使用了一个do{…while(0)实现多语句宏的C语言小技巧,这样能保证在任何情况下WAITFOR都可以如单条语句一样在源程序中使用,需要担心多了或者少了大括弧破坏if/else匹配之类的问题,并且,所有的编译器都会优化掉这个假循环。

为了尽量使程序简单并说明问题,以上代码中没有考虑中断相关的数据保护问题。实际运行的系统中,如果首先写堆栈指针不能一步完成(如AVR这样的8位机),那么,在写操作正在进行的时候绝对不能允许中断;另外,在任务中查询的条件如果和中断有关,那么也必须考虑数据的完整性。

4 性能分析

所有的协作式多任务系统中任务切换时间都和用户代码(是否长期占用CPU)、就绪时刻有关,比标准系统略差的是,我们的简单系统中不支持任务优先级,并且完成一轮查询调度的时间还和任务数目有关。这也是为了达到简单和可移植性目标而不得已作出的牺牲。在各任务间切换查询条件通过C语言标准库函数longjmp实现,一般来讲longjmp函数要从内存中恢复大部分CPU寄存器,执行它也需要若干条指令的时间。

为了面向嵌入式系统应用,任务控制块(TCB)采用静态数组来实现,这样要求预先确定系统的最大任务数(co-os.h中的MAX_TSK)。如果需要,也可以通过环波链表来动态管理任务控制块(TCB),这时可以简单实现任务的动态创建和删除,并且通过指针来访问TCB也要比通过下标(tskid)略快一点。

在某些情况下,如果在中断返回后需要执行某关键任务,可以考虑通过设置“高级中断”的方法来实现。具体地讲,就是在中断返回前改变返回地址到某函数入口(“高级中断服务程序”),同时保留原返回地址到堆栈中,这样在“高级中断服务程序”完成后执行return就又回到了正常的多任务查询流程。使用“高级中断”时要注意现场保护的衔接,并且这种技巧显然和CPU和体系结构有关。

5 结论

setjmp是标准C语言中用于远程跳转的库函数,利用它可方便实现一个简单易移植的协作式多任务系统。该系统功能完备、编程简单、易于学习,适合一些中小规模的嵌入式软件使用;并且,以此为基础,还可以用一些与平台相关的编程技巧提高其实时性和灵活性。



上一页  [1] [2] 


本文关键字:暂无联系方式嵌入式系统-技术单片机-工控设备 - 嵌入式系统-技术

《setjmp构建简单协作式多任务系统》相关文章>>>