UCOS II多任务切换例程(二)

转载 2011年01月19日 11:55:00

原链接:http://www.gd-emb.org/detail/id-48642.html


五. 任务状态:
uCOS II
主要有五种任务状态,睡眠态就是挂起态,阻塞态和延时态这里统一为等待状态。增加了一个被中断状态。UC/OS-Ⅱ总是建立一个空闲任务,这个任务在没有其它任务进入就绪态时投入运行。这个空闲任务[OSTaskIdle()]永远设为最低优先级空闲任务OSTaskIdle()什么也不做,只是在不停地给一个32位的名叫OSIdleCtr的计数器加1,统计任务使用这个计数器以确定现行应用软件实际消耗的CPU时间。空闲任务不可能被应用软件删除。
睡眠态(DORMANT)指任务驻留在程序空间之中,还没有交给μC/OS-Ⅱ管理,把任务交给μC/OS-Ⅱ是通过调用下述两个函数之一:OSTaskCreate()OSTaskCreateExt()。当任务一旦建立,这个任务就进入就绪态准备运行。任务的建立可以是在多任务运行开始之前,也可以是动态地被一个运行着的任务建立。如果一个任务是被另一个任务建立的,而这个任务的优先级高于建立它的那个任务,则这个刚刚建立的任务将立即得到CPU的控制权。一个任务可以通过调用OSTaskDel()返回到睡眠态,或通过调用该函数让另一个任务进入睡眠态。
调用OSStart()可以启动多任务。OSStart()函数运行进入就绪态的优先级最高的任务。就绪的任务只有当所有优先级高于这个任务的任务转为等待状态,或者是被删除了,才能进入运行态。
正在运行的任务可以通过调用两个函数之一将自身延迟一段时间,这两个函数是OSTimeDly()OSTimeDlyHMSM()。这个任务于是进入等待状态,等待这段时间过去,下一个优先级最高的、并进入了就绪态的任务立刻被赋予了CPU的控制权。等待的时间过去以后,系统服务函数 OSTimeTick()使延迟了的任务进入就绪态(见3.10节,时钟节拍)。
正在运行的任务期待某一事件的发生时也要等待,手段是调用以下 3个函数之一:OSSemPend()OSMboxPend(),或OSQPend()。调用后任务进入了等待状态(WAITING)。当任务因等待事件被挂起(Pend),下一个优先级最高的任务立即得到了CPU的控制权。当事件发生了,被挂起的任务进入就绪态。事件发生的报告可能来自另一个任务,也可能来自中断服务子程序。
正在运行的任务是可以被中断的,除非该任务将中断关了,或者μC/OS-Ⅱ将中断关了。被中断了的任务就进入了中断服务态(ISR)。响应中断时,正在执行的任务被挂起,中断服务子程序控制了CPU的使用权。中断服务子程序可能会报告一个或多个事件的发生,而使一个或多个任务进入就绪态。在这种情况下,从中断服务子程序返回之前,μC/OS-Ⅱ要判定,被中断的任务是否还是就绪态任务中优先级最高的。如果中断服务子程序使一个优先级更高的任务进入了就绪态,则新进入就绪态的这个优先级更高的任务将得以运行,否则原来被中断了的任务才能继续运行。
当所有的任务都在等待事件发生或等待延迟时间结束,μC/OS-Ⅱ执行空闲任务(idle task),执行OSTaskIdle()函数。
六. 任务切换:
Context Switch 
在有的书中翻译成上下文切换,实际含义是任务切换,或CPU寄存器内容切换。当多任务内核决定运行另外的任务时,它保存正在运行任务的当前状态(Context),即CPU寄存器中的全部内容。这些内容保存在任务的当前状况保存区(Task’s Context Storage area),也就是任务自己的栈区之中。(见图2.2)。入栈工作完成以后,就是把下一个将要运行的任务的当前状况从该任务的栈中重新装入CPU的寄存器,并开始下一个任务的运行。这个过程叫做任务切换。任务切换过程增加了应用程序的额外负荷。CPU的内部寄存器越多,额外负荷就越重。做任务切换所需要的时间取决于 CPU有多少寄存器要入栈。实时内核的性能不应该以每秒钟能做多少次任务切换来评价。

 

七. 任务调度分析:
uCOS II
提供最简单的实时内核任务调度,算法简单,因此也只支持优先级抢占任务调度,不支持时间片轮训调度算法,不支持优先级逆转。
uCOS II
总是运行进入就绪态任务中优先级最高的那一个。确定哪个任务优先级最高,下面该哪个任务运行了的工作是由调度器(Scheduler)完成的。任务级的调度是由函数OSSched()完成的。中断级的调度是由另一个函数OSIntExt()完成的,这个函数将在以后描述。
uCOS II
任务调度所花的时间是常数,与应用程序中建立的任务数无关。
uCOS中曾经是先得到OSTCBHighRdy然后和OSTCBCur做比较。因为这个比较是两个指针型变量的比较,在8位和一些16位微处理器中这种比较相对较慢。而在μC/OS-Ⅱ中是两个整数的比较。并且,除非用户实际需要做任务切换,在查任务控制块优先级表OSTCBPrioTbl[]时,不需要用指针变量来查OSTCBHighRdy。综合这两项改进,即用整数比较代替指针的比较和当需要任务切换时再查表,使得uCOS IIuCOS8位和一些 16位微处理器上要更快一些。
为实现任务切换,OSTCBHighRdy必须指向优先级最高的那个任务控制块OS_TCB,这是通过将以 OSPrioHighRdy为下标的OSTCBPrioTbl[]数组中的那个元素赋给OSTCBHighRdy来实现的[L3.8(4)]。最后宏调用 OS_TASK_SW()来完成实际上的任务切换[L3.8(6)]
任务切换很简单,由以下两步完成,将被挂起任务的微处理器寄存器推入堆栈,然后将较高优先级的任务的寄存器值从栈中恢复到寄存器中。在uCOS II中,就绪任务的栈结构总是看起来跟刚刚发生过中断一样,所有微处理器的寄存器都保存在栈中。换句话说,μC/OS-Ⅱ运行就绪态的任务所要做的一切,只是恢复所有的CPU寄存器并运行中断返回指令。为了做任务切换,运行 OS_TASK_SW(),人为模仿了一次中断。多数微处理器有软中断指令或者陷阱指令TRAP来实现上述操作。中断服务子程序或陷阱处理(Trap hardler),也称作事故处理(exception handler),必须提供中断向量给汇编语言函数OSCtxSw() OSCtxSw()除了需要OS_TCBHighRdy指向即将被挂起的任务,还需要让当前任务控制块OSTCBCur指向即将被挂起的任务。
OSSched ()
的所有代码都属临界段代码。在寻找进入就绪态的优先级最高的任务过程中,为防止中断服务子程序把一个或几个任务的就绪位置位,中断是被关掉的。为缩短切换时间,OSSched()全部代码都可以用汇编语言写。为增加可读性,可移植性和将汇编语言代码最少化,OSSched()是用C写的。

 

任务切换的相关函数:CPU体系相关,汇编完成。
1. OSStartHighRdy()
执行优先级最高的任务
2. OSCtxSw()    
完成任务的上下文切换
3. OSIntCtxSw() 
中断后的上下文切换
4. OSTickISR()  
中断服务程序启动

 

八. uCOS II的初始化:
OSInit()
建立空闲任务idle task,这个任务总是处于就绪态的。空闲任务OSTaskIdle()的优先级总是设成最低。
这两个任务的任务控制块(OS_TCBs)是用双向链表链接在一起的。OSTCBList指向这个链表的起始处。当建立一个任务时,这个任务总是被放在这个链表的起始处。换句话说,OSTCBList总是指向最后建立的那个任务。链的终点指向空字符NULL(也就是零)
因为这两个任务都处在就绪态,在就绪任务表OSRdyTbl[]中的相应位是设为1的。还有,因为这两个任务的相应位是在OSRdyTbl[]的同一行上,即属同一组,故OSRdyGrp中只有1位是设为1的。 
uCOS II
还初始化了4个空数据结构缓冲区,如图F3.8所示。每个缓冲区都是单向链表,允许uCOS II从缓冲区中迅速得到或释放一个缓冲区中的元素。控制块OS_TCB的数目也就自动确定了。当然,包括足够的任务控制块分配给统计任务和空闲任务。

 

uCOS II内核调度分析

 

 

 vxWorks内核调度分析

 

 

1.只支持基于优先级的抢占式调度算法,不支持时间片轮训;

 

 

采用工作队列 workQword的方式调度;

 

 

264个优先级,只能创建64个任务,用户只能创建56个任务;

 

 

根据用户指定,动态分配堆栈,可以创建任意多个任务;

 

 

3.每个任务优先级都不相同。

 

 

 

 

 4.不支持优先级逆转;

 

 

支持优先级逆转,TCB保存两个优先级;

 

 

5READY队列通过内存映射表实现快速查询。效率非常高;

 

 

支持抢占与时间片轮训的任务调度方式;

 

 

6.支持时钟节拍;

 

 

通过编译开关实现对多cpu体系结构的支持。

 

 

7.支持信号量,消息队列,事件控制块,事件标志组,消息邮箱任务通讯机制;

 

 

队列采用FIFO或者优先级的双向链表实现;

 

 

8.支持中断嵌套,中断嵌套层数可达255层,中断使用当前任务的堆栈保存上下文;

 

 

支持中断嵌套,中断使用专用的堆栈保存上下文;

 

 

9.每个任务有自己的堆栈,堆栈大小用户自己设定;

 

 

任务是基于类,对象的管理方式;

 

 

10.支持动态修改任务优先级;

 

 

支持动态修改任务优先级;

 

 

11.任务TCB为静态数组,建立任务只是从中获得一个TCB,不用动态分配,释放内存;

 

 

任务的TCB保存在任务的堆栈里;

 

 

12.任务堆栈为用户静态或者动态创建,在任务创建外完成,任务创建本身不进行动态内存分配;

 

 

每个任务有自己的堆栈,堆栈大小用户自己设定;

 

 

13.任务的总个数(OS_MAX_TASKS)由用户决定;

 

 

 

 

140优先级最高, 63优先级最低;

 

 

任务的优先级从0—2550优先级最高,允许多个任务相同优先级;

 

 

15.有一个优先级最低的空闲任务,在没有用户任务运行的时候运行.

 

 

系统没有空闲任务执行;

 

 

 

 

相关文章推荐

uCOS-II移植 (B OSStartHang)问题 和 多任务不能切换问题

关于STM32F107VC _OSStartHang解决方案 问题:移植UCOS-II后,程序总是在  B         OSStartHang ,//根据提示,应当永远不会到这步的。 ...
  • sunymen
  • sunymen
  • 2017年03月07日 12:11
  • 194

uCOS-II多任务编程设计

  • 2013年06月05日 10:49
  • 368KB
  • 下载

关于uCOS-II创建多任务的模板参考

作为一个刚接触uCOS-II的新手,在看了一些代码之后,萌生出写一个创建uCOS-II多任务的参考模版,虽然不是万能,但相信可以节省一点时间,也可以和大家一起交流。 其中如有错误之处,还望各位高手多...

ucos ii是怎么实现多任务运行的?很通俗易懂的描述

作者:不繆 链接:https://www.zhihu.com/question/55265639/answer/143727267 来源:知乎 著作权归作者所有。商业转载请联系作者获得授权,非商业转载...

uCOS-II中的任务切换机制

【@.1 函数周期与死循环】   一般函数的生命周期很简单,从开始调用函数起,直到函数返回,即结束。这样一来就完成了这个函数的使命,它也就不再需要了。对于一般的函数就是这样,但是回过头想想...

uCOS-II中的任务切换机制(转)

ucosII
  • yeanet
  • yeanet
  • 2017年03月10日 09:49
  • 38

uCOS-II中的任务切换-图解多种任务调度时机与问题

【@.1 任务调度时机】 之前的一篇文章分析了具体的uCOS-II中的任务切换机制,是从函数调用的角度上分析的。这次我具体从整个程序运行的时间上来看,分析多种任务调度发生的时机。以下所有图片均可...

uCOS-II中的任务切换-图解多种任务调度时机与问题

uCOS-II中的任务切换-图解多种任务调度时机与问题 【@.1 任务调度时机】 之前的一篇文章分析了具体的uCOS-II中的任务切换机制,是从函数调用的角度上分析的。这次我具体从整个程序...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:UCOS II多任务切换例程(二)
举报原因:
原因补充:

(最多只允许输入30个字)