ucos-II(三)

来源:互联网 发布:上海大众售后数据 编辑:程序博客网 时间:2024/04/30 06:30
一、 任务控制块的初始化
初始化任务控制块函数OSTCBInit() :
INT8U OSTCBInit(
           INT8U prio,      //任务的优先级别,保存在OSTCBPrio中
           OS_STK * ptos,   //任务堆栈栈顶指针,保存在OSTCBStkPtr中
           OS_STK * pbos,  //任务堆栈栈底指针,保存在OSTCBStkBottom中
           INT16U id,      //任务的标识符,保存在OSTCBId中
           INT16U stk_size, //任务堆栈的长度,保存在OSTCBStkSize中
           void * pext,    //任务控制块的拓展指针,保存在OSTCBExtPtr中
           INT16U opt    //任务控制块的选择项,保存在OSTCBOpt中
              );
该函数的主要任务:
1.为被创建任务从空任务控制块链表获取一个任务控制块;
2.用任务的属性对任务控制块各个成员进行赋值;
3.把这个任务控制块链入到任务控制块链表。


二、任务就绪表及任务调度
为系统中处于就绪状态的任务分配CPU是多任务操作系统的核心工作。
   判断哪些任务处于就绪状态

  进行任务调度


三、 对任务就绪表的操作
1.登记
 将优先级别为prio的任务设置为就绪状态
OSRdyGrp  |= OSMapTbl[prio >> 3];
OSRdyTbl[prio >> 3]  |= OSMapTbl[prio & 0x07];
 其中OSMapTbl[]是uC/OS-II为加快运算速度定义的一个数组,其元素值为:
OSMapTbl[0] = 00000001B
OSMapTbl[1] = 00000010B
OSMapTbl[2] = 00000100B
OSMapTbl[3] = 00001000B
OSMapTbl[4] = 00010000B
OSMapTbl[5] = 00100000B
OSMapTbl[6] = 01000000B
OSMapTbl[7] = 10000000B
2.注销
 使优先级别为prio的任务脱离就绪状态:
if((OSRdyTbl[prio >> 3] &= -OSMapTbl[prio & 0x07]) == 0)
    OSRdyGrp &= - OSMapTbl[prio >> 3];
3.最高优先就绪任务的查找
uC/OS-II调度器用于获取优先级别最高的就绪任务:
y = OSUnMapTal[OSRdyGrp];         //获得优先级别的D5、D4、D3位
x = OSUnMapTal[OSRdyTbl[y]];       //获得优先级别的D2、D1、D0位
prio = (y << 3) + x;                 //获得就绪任务的优先级别
或:
y = OSUnMapTal[OSRdyGrp];
prio = (INT8U)((y << 3) + OSUnMapTal[OSRdyTbl[y]);


四、任务调度
1.调度器的主要工作
(1)在任务就绪表中查找具有最高优先级别的就绪任务
(2)实现任务的切换
2.获得待运行就绪任务控制块的指针
 任务级调度器OSSched()的源代码如下:
void OSSched(void)
{
#if OS_CRITICAL_METHOD == 3
      OS_CPU_SR_ cpu_sr;
#endif
 
       INT8U y;
 
       OS_ENTER_CRITICAL();
       if((OSLockNesting | OSIntNesting) == 0)
       {
            y = OSUnMapTbl[OSRdyGrp];
            OSPrioHighRdy             //得到最高级优先任务
                       = (INT8U)((y << 3) + UnMapTbl[OSRdyTbl[y]]);
           if(OSPrioHighRdy != OSPrioCur)
           {
               OSTCBHighRdy    //得到任务块指针
                         = OSTCBPrioTbl[OSPrioHighRdy];
               OSCtxSwCtr++;     //统计任务切换次数的计数器加1
               OS_TASK_SW();
           }
       }
       OS_EXIT_CRITUCAL();
}


五、OSCtxSw()要依次做下述7项工作:
(1)把被中止任务的断点指针保存到任务堆栈中;
(2)把CPU通用寄存器的内容保存到任务堆栈中;
(3)把被中止任务的任务堆栈指针当前值保存到该任务的任务控制块的OSTCBStkPtr中;
(4)获得待运行任务的任务控制块;
(5)使CPU通过任务控制块获得待运行任务的任务堆栈指针;
(6)把待运行任务堆栈中通用寄存器的内容恢复到CPU的通用寄存器中;
(7)使CPU获得待运行任务的断点指针(该指针是待运行任务在上次被调度器中止运行时保留在任务堆栈中的)
代码示例:
void OSCtxSw(void)
{
用压栈指令把CPU通用寄存器R1、R2、…压入堆栈;
OSTCBCur -> OSTCBStkPtr = SP;       //在中止任务控制块中保存SP
OSTCBCur = OSTCBHighRdy;          //任务控制块的切换
OSPrioCur = OSPrioHighRdy;         
SP = OSTCBHighRdy -> OSTCBStkPtr;     //使SP指向待运行任务堆栈
用出栈指令把R1、R2、…弹入CPU的通用寄存器;
IRET;                            //中断返回,使PC指向待运行任务
}


六、 其他任务管理函数
1 任务优先级别的修改
OSTaskChangePrio()函数原型:
#if OS_TASK_DEL_EN
INT8U  OSTaskDel(
                INT8U prio     //要删除任务的优先级别
               );
2 任务的删除
OSTaskDel()函数原型:
INT8U OSTaskChangePrio(
                     INT8U  oldprio,      //任务现在的优先级别
                     INT8U  newprio     //要修改的优先级别
                    );


OSTaskDelReq()函数原型:
INT8U  OSTaskDelReq(
                   INY8U  prio         //待删除任务的优先级别
                  );


3 查询任务的信息
OSTaskQuery()函数原型:
INT8U  OSTaskQuery(
                  INT8U prio,           //待查询任务的优先级别
                  OS_TCB  * pdata      //存储任务信息的结构
                 );


小结:
(1)任务由任务控制块、任务堆栈和任务代码组成;
(2)系统按任务就绪表和任务的优先级别来调度任务的;
(3)任务切换的核心工作是任务堆栈指针的切换;
(4)任务调度器代码的设计,使得它的运行时间与系统中的任务数无关,从而使它满足了实时系统的要求;
(5)任务的优先级别也是任务的标识;
(6)应用程序首先应该调用OSInit()函数对全局变量和数据结构进行初始化,以建立uC/OS-II的运行环境;
(7)应用程序是通过调用函数OSStart()开始进入多任务管理的,但在调用函数OSStart()之前必须至少创建一个任务。
0 0