任务基本概念
任务是一个接受操作系统管理的独立运行单元,在uCosII
中类似与普通平台上的main()
函数,需要自己来保护其因调用或中断二产生的断点,所以需要一个自己的私有堆栈,即任务堆栈;
任务有两种,分为:用户任务和系统任务;
uCosII
中并没有给任务分配独立的运行空间,而是所有的任务共同使用一个内存空间,所以这里的任务属于线程;
系统中的任务共有5种状态:
- 睡眠状态:任务只是以代码的形式驻留在程序空间(ROM或RAM),还没有交给操作系统管理时的情况叫睡眠状态;
- 就绪状态:如果系统为任务分配了任务控制块且在任务就绪表中进行了就绪登记,则任务就具备了运行的充分条件,这时任务的状态就是就绪状态;
- 运行状态:处于就绪状态的任务如果经调度器判断获得CPU的使用权,则任务就进入了运行状态,任何时刻只能有一个任务处于运行状态;
- 等待状态:正在运行的任务,需要等待一段时间或需要等待一个事件发生再运行时,该任务就把CPU的使用权让给其他任务而使任务进入了等待状态;
- 中断服务状态:一个正在运行的任务一旦响应中断申请就会中止运行而去执行中断服务程序,这时的任务状态就是中断服务状态;
CosII
预定义了两个系统任务:空闲任务和统计任务,其中空闲任务是每个应用程序必须使用的,而统计任务则是应用程序可以根据实际需要来选择可配置的;
任务控制块及其链表
任务控制块
一条空任务块链表,其中所有任务控制块还未分配给任务;
一条任务块链表,其中所有任务控制块已分配给任务;
一个数据类型为OS_TCB*
的数据OSPrioTbl[]
,按照任务优先级顺序存放了指向各个任务控制块的指针;
任务控制块初始化
OSTaskCreate()
-> OSTCBInit()
;
流程:获取一个空的任务块 -> 创建任务控制块并初始化成员值 -> 将该任务控制块链入任务控制块链表中;
任务就续表及任务调度
任务就续表
任务就续表就是一个位图,系统中每个任务占据一个二进制位,1/0表示任务是否处于就绪状态;
实质是一个类型为INT8U
的数组OSRdyTbl[]
,每个元素(每8个任务)是一个任务组;
位图中按照任务优先级高低为顺序依次分配对应位;
为了便于对就绪表查找,定义了一个数据类型为INT8U
的变量OSRdyGrp
,使该变量的每一个位都对应OSRdyTbl[]
的一个任务组,如果某任务组中有任务就绪,则在变量OSRdyGrp
里把该任务组所对应的位设置1,否则为0,因此也对应最多可以管理64个任务;
任务调度
uCossII
中的任务调度由调度器来完成;
任务调度器主要工作有两项:
- 在就续表中查找具有最高优先级别的就绪任务;
- 实现任务的切换;
任务调度器有两种:
- 任务级的调度器(由函数
OS_Sched()
来实现); - 中断级的调度器(由函数
OS_IntExt()
来实现);
调度器把任务切换工作分为两个步骤:
- 获得待运行任务的
TCB
指针; - 进行断点数据的切换(在宏OS_TASK_SW()中实施任务切换,主要是靠
OSCtxSw()
);
任务的创建
uCosII
是通过任务控制块来管理任务的,所以创建任务的实质就是创建一个任务控制块,并通过任务控制块把任务代码和任务堆栈关联起来形成一个完整的任务,还要使刚创建的任务进入就绪状态,并且接着引发一次任务调度;
创建任务的函数有两个:STaskCreate()
和OSTaskCreateExt()
,后者是前者的扩展,提供了一些附加功能;
uCosII
有一个规定:在调用启动任务函数OSStart()
之前,必须已经创建了至少一个任务;不允许在中断服务程序中创建任务;
任务的挂起和恢复
任务的挂起就是停止这个任务;
用户任务可通过调用系统提供的OSTaskSuspend()
函数来挂起自身或者除空闲任务之外的其他任务,用该函数挂起后的任务只能在其他任务中通过调用恢复函数OSTaskResume()
使其恢复为就绪状态;
其他任务相关函数
任务优先级修改
OSTaskChangePrio()
在程序的运行过程中,可调用该函数来改变任务优先级别;
任务的删除
删除任务就是把该任务置于休眠状态;
可调用函数OSTaskDel()
来删除任务自身或者除了空闲任务之外的其他任务;
删除任务时为防止被删除任务所占用的一些资源没有释放,所以解决办法是:提出删除任务请求的任务只负责删除任务请求,而删除工作则由被删除任务自己来完成,这样被删除任务就可以根据自身的具体情况来决定何时删除自身,同hi也有机会删除自身所占用的资源;
能实现这种删除方式的方法是:利用被删除任务的任务控制块成员OSTCBDelReq
作为请求删除方与被删除方的联络信号,同时提供了一个双方都能调用的函数(请求删除任务函数)OSTaskDelReq()
,这样提出删除任务请求的任务和被删除任务双方就能使用该函数来访问OSTCBDelReq
这个信号,从而可以根据这个信号的状态来决定各自的行为;
查询任务信息
在应用程序运行中需要了解一个任务的指针、堆栈等信息时,可以调用函数OSTaskQuery()
来获取选定的任务信息;