注册 登录
电子工程世界-论坛 返回首页 EEWORLD首页 频道 EE大学堂 下载中心 Datasheet 专题
416561760的个人空间 https://home.eeworld.com.cn/space-uid-116357.html [收藏] [复制] [分享] [RSS]
日志

uC/OS II学习《二》—uC/OS II内核完全解析之空闲任务的建立

已有 2575 次阅读2010-5-30 18:50 |个人分类:uC/OS II|

上次说到空闲任务的建立:

OSTaskCreate(OSTaskIdle, (void *)0, &OSTaskIdleStk[0], OS_IDLE_PRIO);//建立空闲任务

空闲任务的建立是调用OS_TASK.C中的OSTaskCreate 任务创建函数完成的,OSTaskCreate函数接收4个变量:task是任务代码的指针,pdata是当任务开始执行时传递给任务的参数的指针,ptos是分配给任务的堆栈的栈顶指针,prio是分配给任务的优先级。

 

INT8U OSTaskCreate (void (*task)(void *pd), void *ppdata, OS_STK *ptos, INT8U prio)

{

    void   *psp;

    INT8U   err;

 

if (prio > OS_LOWEST_PRIO)// 判断分配给任务的优先级是否有效。任务的优先级//必须在064之间

 {       

      return (OS_PRIO_INVALID); //优先级无效,返回42

     }

OS_ENTER_CRITICAL();  //关中断,EA=0

if (OSTCBPrioTbl[prio] == (OS_TCB *)0) //确保在规定的优先级上还没有建立任务,//果此优先级prio上有任务建立则OSTCBPrioTbl[prio] = (OS_TCB *)1

 {

   OSTCBPrioTbl[prio] = (OS_TCB *)1; //占用该优先级,其他任务就不能再应用//该优先级           

      OS_EXIT_CRITICAL();     //开中断 EA=1

psp = (void *)OSTaskStkInit(task, ppdata, ptos, 0);//堆栈初始化,返回栈顶指针

err = OSTCBInit(prio, psp, (void *)0, 0, 0, (void *)0, 0); //初始化任务控制块       

        if (err == OS_NO_ERR) //如果初始化成功

  {

            OS_ENTER_CRITICAL(); //关中断EA=0

            OSTaskCtr++;     //任务计数器加一                   

            OS_EXIT_CRITICAL(); //开中断 EA=1

            if (OSRunning)  //如果任务运行标志为1

 {     

                OSSched();  //调用任务调用任务调度函数

              }

           }

else {

           OS_ENTER_CRITICAL(); //关中断EA=0

OSTCBPrioTbl[prio] = (OS_TCB *)0;  //初始化不成功,讲此优先级//还给优先级表,让其他任务建立时可用

          OS_EXIT_CRITICAL(); //开中断 EA=1

            }

        return (err); //返回错误

}

else {

        OS_EXIT_CRITICAL();//开中断 EA=1

        return (OS_PRIO_EXIST); //返回此任务优先级已经存在

       }

}

 

 到这空闲任务就算建立起来了,从上面的函数来看,空闲任务的建立主要做的事情就是:

psp = (void *)OSTaskStkInit(task, ppdata, ptos, 0);//堆栈初始化,返回栈顶指针

err = OSTCBInit(prio, psp, (void *)0, 0, 0, (void *)0, 0); //初始化任务控制块

其余的语句都是为了做这两件事情服务的。

下面我们在来看堆栈初始化函数OSTaskStkInit(),堆栈的初始化是要自己根据处处理器的特点编写的,51单片机在任务切换和中断来临时需要入栈的寄存器有12个:R0-R7ACCBPSWDPTRDPHDPL)共13个字节,在加上任务的地址(2字节),共15字节。

   从上面看出OSTaskStkInit()函数接收4个参数:

task          指向任务代码的指针

pdata         当任务第一次执行时将要传入任务的用户数据结构指针

         ptos         栈顶指针。ptos指针被默认为用户堆栈入口指针。OS_STK_GROWTH被置1,那么,ptos指向用户堆栈的最高有效地址。同样地,如果OS_STK_GROWTH0ptos将指向用户堆栈的最低有效地址。

         opt           指定可以改变OSTaskStkInit()行为的选项。

void *OSTaskStkInit (void (*task)(void *pd), void *ppdata, void *ptos, INT16U opt)

{   

    OS_STK *stk;   // typedef unsigned char  OS_STK栈单元宽度为8比特

 

    ppdata = ppdata;

    opt    = opt;                           //opt没被用到,保留此语句防止告警产生    

    stk    = (OS_STK *)ptos;                    //用户堆栈最低有效地址

    *stk++ = 15;                                //用户堆栈长度

    *stk++ = (INT16U)task & 0xFF;               //任务地址低8

    *stk++ = (INT16U)task >> 8;                 //任务地址高8   

    *stk++ = 0x00;                              //PSW

    *stk++ = 0x0A;                              //ACC

    *stk++ = 0x0B;                              //B

    *stk++ = 0x00;                              //DPL

    *stk++ = 0x00;                              //DPH

    *stk++ = 0x00;                              //R0

    *stk++ = 0x01;                              //R1

    *stk++ = 0x02;                              //R2

    *stk++ = 0x03;                              //R3

    *stk++ = 0x04;                              //R4

    *stk++ = 0x05;                              //R5

    *stk++ = 0x06;                              //R6

    *stk++ = 0x07;                              //R7

                   

    return ((void *)ptos);                       //返回用户堆栈最低有效地址

}

上面这四个参数是由OSTaskCreate(OSTaskIdle, (void *)0, &OSTaskIdleStk[0], OS_IDLE_PRIO);任务创建函数传递进来的。初始化完任务堆栈后,函数返回用户堆栈的栈顶指针,即最低地址。将这个地址传递给任务控制块初始化函数OSTCBInit()

即:err = OSTCBInit(prio, psp, (void *)0, 0, 0, (void *)0, 0); //初始化任务控制块

该上班了,有空再说任务控制块的初始化……

发表评论 评论 (1 个评论)
回复 litianchenghao 2013-9-22 09:49
非常感谢,对初学者的我很有用处。

facelist doodle 涂鸦板

您需要登录后才可以评论 登录 | 注册

热门文章