ucos-II 任务调度源码分析(二)

在ucos-II中最主要的函数是:

INT8U OSTaskCreate (void (*task)(void *p_arg),void *p_arg,OS_STK *ptos, INT8U prio)

*task:任务函数的钩子;*p_arg:任务的参数;ptos:指向任务的堆栈;prio:任务的优先级。

在OSTaskCreate中主要完成了以下工作:

  1. OSTCBPrioTbl[prio] = OS_TCB_RESERVED;设置OSTCKPrioTbl为有效;
  2. OSTaskStkInit;初始化任务堆栈;将下列信息存入ptos指向的堆栈区,如任务函数、任务函数参数、特殊寄存器、工作寄存器
  3. OS_TCBInit;初始化TCB,在初始化TCB函数中:
    1. 初始化OS_TCB;
    2. 根据优先级,更新OSTCBPrioTbl、OSTCBList、OSRdyGrp、OSRdyTbl;
  4. 如果初始化OS_TCB正常,则调用OS_Sched:
    1. 通过OSRdyGrp、OSUnMapTbl查找当前最高优先级的就绪任务(详见ucos-II任务调度(一)),并赋值给全局变量OSPrioHighRdy;
    2. 调用OS_TASK_SW,该函数在OS_CPU_A.ASM中实现,与具体的CPU强相关。

 注:以STC单片机为例,CPU通过执行PC寄存器指向的地址实现跳转,在51系列的MCU中PC寄存器是不可寻址的,因此ucos采用这样的方法。在OSTaskStkInit时任务地址被压栈:

 

void *OSTaskStkInit (void (*task)(void *pd), void *ppdata, OS_STK *ptos, INT16U opt)
{
    OS_STK *stk;
    ppdata     = ppdata;
    opt     = opt;
    stk     = ptos;

    *stk++ = 15;
    *stk++ = (INT16U)task & 0xFF; //任务地址低8位
    *stk++ = (INT16U)task >> 8;      //任务地址高8位
    *stk++ = 0x0A;                //ACC
    *stk++ = 0x0B;                //B
    *stk++ = 0x00;                //DPH

 

然后当需要跳转时首先执行POPA,将所有的寄存器出栈,此时SP的指针指向ACC保存的地址。然后调用RETI,通过RETI指令对PC寄存器赋值。RETI指令定义如下:

PC高8位 = (SP);(SP)<-(SP-1);PC低8位=(SP);(SP)<-(SP-1)

ucos的任务管理中还实现了其他一些函数如任务优先级的修改、任务的挂起、任务的恢复等。从原理上都大同小异,通过修改全局变量实现。

 

 

 

 

posted @ 2013-01-23 22:06  Fredric_2013  阅读(1321)  评论(0编辑  收藏  举报