zoukankan      html  css  js  c++  java
  • uc/os任务管理

    //ucos的初始化
    void OSInit(void)
    {
    #if OS_VERSION>=204
    OSInitHookBegin();
    #endif
    OS_InitMisc(); //初始化系统需要的一些变量
    OS_InitRdyList(); //初始化就绪列表
    OS_InitTCBList(); //初始化TCB列表
    OS_InitEventList(); //初始化事件列表
    #if (OS_VERSION>=251)&&(OS_FLAG_EN>0)&&(OS_MAX_FLAGS>0)
    OS_FlagInit(); //初始化事件标志
    #endif
    #if (OS_MEM_EN>0)&&(OS_MAX_MEM_PART>0)
    OS_MemInit(); //初始化内存管理
    #endif
    #if (OS_Q_EN>0)&&(OS_MAX_QS>0)
    QS_Init(); //初始化消息队列
    #endif
    OS_InitTaskIdle(); //建立空闲任务
    #if OS_TASK_STAT_EN>0
    OS_InitTaskStat(); //建立统计任务
    #endif
    #if OS_VERSION>=204
    OSInitHookEnd();
    #endif
    }



    /*uc/os-II的任务控制块的数据结构的定义*/
    typedef struct os_tcb{
    OS_STK *OSTCBStKPtr; /*指向任务独立堆栈的栈顶指针*/
    #if OS_TASK_CREATE_EXT_EN
    void *OSTCBExtPtr; /*指向用户定义的任务控制块拓展*/
    OS_STK *OSTCBStkBottom; /*指向任务栈区栈底的指针*/
    INT32U OSTCBStkSize; /*栈区中可容纳的存储单元个数*/
    INT16U OSTCBopt; /*创建TCB的类型选择*/
    INT16U OSTCBId; /*任务识别号*/
    #endif
    struct os_tcb *OSTCBNEXT; /*指向OS_TCB联表中下一个元素*/
    struct os_tcb *OSTCBPre; /*指向OS_TCB联表中前面一个元素*/
    #if(OS_Q_EN&&(OS_MAX_QS>=2))||OS_MBOX_EN||OS_SEM_EN
    OS_EVENT *OSTCBEvent; /*指向事件控制块的的指针*/
    #endif
    #if(os_Q_EN&&(OS_MAX_QS>=2))||OS_MBOX_EN
    void *OSTCBMsg; /*指向传给任务的消息指针*/
    #endif
    INT16U OSTCBDly; /*任务允许等待事件发生的最多时钟节拍数*/
    INT8U OSTCBStat; /*任务的状态字*/
    INT8U OSTCBPrio; /*任务的优先级*/
    INT8U OSTCBX; /*任务就绪表位图矩阵的X坐标*/
    INT8U OSTCBY; /*任务就绪表位图矩阵的Y坐标*/
    INT8U OSTCBBitX; /*任务就绪表位图矩阵的X坐标操作掩码*/
    INT8U OSTCBbitY; /*任务就绪表位图矩阵的Y坐标操作掩码*/
    #if OS_TASK_DEL_EN
    BOOLEAN OSTCBDelReg; /*表示该任务是否删除*/
    #endif
    }OS_TCB;



    /*基本型任务创建函数的原型声明*/
    INT8U OSTaskCreate(void(*task)(void *pd),void *pdata,OS_STK *ptos,INT8U prio)
    /*拓展型任务创建函数声明*/
    INT8U OSTaskCreateExt(
    void (*task)(void *pd), //指向任务的执行函数的指针
    void *pdata, //指向任务执行的参数指针
    OS_STK *ptos, //指向任务自用栈栈顶的指针
    INT8U prio; //任务的优先级
    INT16U id, //任务的标识符
    OS_STK *pbos, //指向任务自用栈栈底的指针
    INT32U stk_size, //任务自用栈的空间大小
    void *pext, //指向任务扩展指针
    INT16U opt) //任务的选项



    //任务的建立
    INT8U OSTaskCreate(void (*task)(void *pd),void *pdata,OS_STK *ptos,INT8U prio)_
    {
    void *psp;
    INT8U err;

    if(prio>OS_LOWEST_PRIO) //确定用户输入的优先级是否在有效的范围内
    {
    return (OS_PRIO_INVALID);
    }

    OS_ENTER_CRITICAL(); //进入临界区
    if(OSTCBPrioTbl[prio]==(OS_TCB*)0) //确定优先级没有被其他任务占用
    {
    OSTCBPrioTbl[prio]==(OS_TCB*)1; //如果分配的优先级空闲,保留该优先级
    OS_EXIT_CRITICAL(); //退出临界区


    psp=(void *)OSTaskStkInit(task,pdata,ptos,0); //初始化任务堆栈
    err=OSTCBInit(prio,psp,(void*)0,0,0,(void*)0,0); //从空闲的OS_TCB池获得并初始化一个任务控制块OS_TCB

    if(err==OS_NO_ERR)
    {//从OS_TCBInit()返回后,会检测返回的代码,如果成功,给OSTaskCtr加1
    OS_ENTER_CRITICAL();
    OSTaskCtr++;
    OSTaskCreateHook(OSTCBPrioTbl[prio]); //是用户自己定义的函数,用来拓展OSTaskCreate()的功能
    OS_EXIT_CRITICAL();

    if(OSRunning) //如果多任务环境已经启动,立即执行任务调度
    {
    OSSched();
    }
    }
    else
    {//从OS_TCBInit()返回后,会检测返回的代码,如果失败,放弃该优先级
    OS_ENTER_CRITICAL();
    OSTCBPrioTbl[prio]=(OS_TCB*)0;
    OS_EXIT_CRITICAL();
    }
    return (err);
    }
    else
    {
    OS_EXIT_CRITICAL();
    return (OS_PRIO_EXIST);
    }
    }

    //获取一块空闲的TCB
    INT8U OS_TCBInit(INT8U prio,OS_STK *ptos,
    OS_STK *pbos,
    INT16U id,
    INT32U stk_size,
    void *pnext,
    INT16U opt)
    {
    #if OS_CRITICAL_METHOD==3
    OS_CPU_SR cpu_sr;
    #endif
    OS_TCB *ptcb;

    OS_ENTER_CRITICAL();
    ptcb=OSTCBFreeList; //试图从OS_TCB缓冲池中获取一个任务控制块OS_TCB
    if(ptcb!=(OS_TCB *)0)
    {
    OSTCBFreeList=ptcb->OSTCBNext;
    OS_EXIT_CRITICAL();
    ptcb->OSTCBStkPtr=ptos; //如果OS_TCB池中有空闲的OS_TCB,就被初始化
    ptcb->OSTCBPrio=(INT8U)prio;
    ptcb->OSTCBStat=OS_STAT_RDY;
    ptcb->OSTCBDly=0;

    #if OS_TASK_CREATE_EXT_EN>0
    //如果允许OSTaskCreateExt()的代码生成,额外的变OS_TCB
    ptcb->OSTCBExtPtr=pnext;
    ptcb->OSTCBStkSize=stk_size;
    ptcb->OSTCBStkBottom=pbos;
    ptcb->OSTCBOpt=opt;
    ptcb->OSTCBId=id;
    #else
    pext=pext;
    stk_size=stk_size;
    pbos=pbos;
    opt=opt;
    id=id;
    #endif

    #if OS_TASK_DEL_EN>0
    ptcb->OSTCBDelReq=OS_NO_ERR; //如果不打算删除任务,该变元可以省略
    #endif
    ptcb->OSTCBY=prio>>3; //为了节省任务调度时间,对一些参数提前运算
    ptcb->OSTCBBitY=OSMapTbl[ptcb->OSTCBY];
    ptcb->OSTCBX=prio&0x07;
    ptcb->OSTCBBitX=OSMapTbl[ptcb->OSTCBX];

    #if OS_EVENT_EN>0
    ptcb->OSTCBEventPtr=(OS_EVENT *)0;
    #endif
    #if (OS_VERSION>=251)&&(OS_FLAG_EN>0)&&(OS_MAX_FLAGS>0)&&(OS_TASK_DEL_EN>0)
    //如果事件标志的使用得到允许,则指向事件标志节点的指针被初始化为空指针
    ptcb->OSTCBFlagNode=(OS_FLAG_NODE *)0;
    #endif
    #if
    (OS_MBOX_EN>0)||((OS_Q_EN>0)&&(OS_MAX_QS>0))
    ptcb->OSTCBMsg=(void*)0;
    #endif
    #if OS_VERISON>=204
    OSTCBInitHook(ptcb);
    #endif
    OSTaskCreateHook(ptcb);
    OS_ENTER_CRITICAL();
    //需要将OS_TCB插入到已建立任务的OS_TCB的双向联表中
    OSTCBPrioTbl[prio]=ptcb;
    ptcb->OSTCBNext=OSTCBList;
    ptcb->OSTCBPrev=(OS_TCB*)0;
    if(OSTCBList!=(OS_TCB*)0)
    {
    OSTCBList->OSTCBPrev=ptcb;
    }
    OSTCBList=ptcb;
    OSRdyGrp|=ptcb->OSTCBBitY;
    OSRdyTbl[ptcb->OSTCBY]|=ptcb->OSTCBBitX;
    }
    OS_EXIT_CRITICAL();
    return (OS_NO_MORE_TCB);
    }



    //uc/OS-II C 语言任务调度函数
    void OS_Shedul(void)
    {
    #if OS_CRITICIAL_METHOD==3
    OS_CPU_SR cpu_sr; /*为CPU的状态寄存器分配存储器*/
    #endif
    INT8U y;
    OS_ENTER_CRITICAL();
    if((OSIntNesting==0)&&(OSLockNecting==0))
    {
    /*任务调度的要求:所有的ISR执行完毕并且任务调度未加锁*/
    y=OSUnMapTabl[OSRbyGrp];/*得到最高就绪任务所在任务的分组组号*/
    OSPrioHighRby=(INT8U)((y<<3)+OSUnMapTbl[OSRbyTbl[y]];/*得到最高就绪任务的优先级*/
    if(OSPrioHighBy!=OSPrioCur)/*如果当前任务优先级就是最高优先级的任务,则不进行调度*/
    {
    OSTCBHighBy=OSTCBPrioTbl[OSPrioHighRby];/*获得最高优先级就绪的TCB指针*/
    OSCtxSwCtr++;/*任务切换计数器增1*/
    OS_TASk_SW();/*执行任务级任务切换*/
    }
    }
    OS_EXIT_CRITICAL();
    }



    //堆栈的检测,OS_STK_DATA是一个结构,记录已用的堆栈空间和剩余的堆栈空间
    INT8U OSTaskStkChk(INT8U prio,OS_STK_DATA *pdata)
    {
    OS_TCB *ptcb;
    OS_STK *pchk;
    NT32U free;
    INT32U size;
    pdata->OSFree=0;
    pdata->OSUsed=0;
    if(prio>OS_LOWEST_PRIO&&prio!=OS_PRIO_SELF)
    {
    return (OS_PRIO_INVALID);
    }
    OS_ENTER_CRITICAL();
    if(prio==OS_PRIO_SELF) //优先级等于当前的任务优先级
    {
    prio=OSTCBCur->OSTCBPrio;
    }
    ptcb=OSTCBPrioTbl[prio];
    if(ptcb==(OS_TCB)*0) //任务不存在
    {
    OS_EXIT_CRITICAL();
    return (OS_TASK_NOT_EXIST);
    }
    if((ptcb->OSTCBOpt&OS_TASK_OPT_STK_CHK)==0)
    {
    OS_EXIT_CRITICAL();
    return (OS_TASK_OPT_ERR);
    }
    free=0;

    size=ptcb->OSTCBStkSize;
    pchk=ptcb->OSTCBStkBottom;

    OS_EXIT_CRITICAL();
    #if OS_TASK_GROWTH==1 //如果堆栈是增长型,从低地址往高地址放
    while(*pchk++==0)
    {
    free++;
    }
    #else
    while(*pchk--==0)
    {
    free++;
    }
    #endif
    pdata->OSFree=free*sizeof(OS_STK);
    pdata->OSUsed=(size-free)*sizeof(OS_STK);
    return (OS_NO_ERR);
    }



    //改变任务的优先级
    INT8U OSTaskChangePrio(INT8U oldprio,INT8U newprio)
    {
    #if OS_EVENT_EN
    OS_EVENT *prevent;
    #endif
    OS_TCB *ptcb;
    INT8U x;
    INT8U y;
    #if OS_LOWEST_PRIO<=63
    INT8U bitx;
    INT8U bity;
    #else
    INT16U bitx;
    INT16U bity;
    #endif
    INT8U y_old;
    #if OS_CRITICAL_METHOD==3
    OS_CPU_SR cpu_sr=0;
    #endif


    #if OS_ARG_CHK_EN>0
    if(oldprio>=OS_LOWEST_PRIO) //不能改变空闲任务的优先级,但可以改变调用本任务或者其他任务的优先级
    {
    if(oldprio!=OS_PRIO_SELF)
    {
    return (OS_PRIO_INVALID);
    }
    }
    if(newprio>=OS_LOWEST_PRIO)
    {
    return (OS_PRIO_INVALID);
    }
    #endif

    OS_ENTER_CRITICAL();
    if(OSTCBPrioTbl[newprio]!=(OS_TCB *)0)
    {//ucOS-II不允许多个任务具有相同的优先级
    OS_EXIT_CRITICAL();
    return (OS_PRIO_EXIST);
    }
    if(oldprio==OS_PRIO_SELF)
    {
    //检测目前的任务是否想改变它的优先级
    oldprio=OSTCBCur->OSTCBPrio;
    }
    ptcb=OSTCBPrioTbl[oldprio];

    if(ptcb==(OS_TCB*)0)
    {//如果想要改变优先级的任务不存在
    OS_EXIT_CRITICAL();
    return (OS_TASK_NOT_EXIST);
    }

    #if OS_LOWEST_PRIO<=63 //计算新优先级任务的OS_TCB中的某些值
    y=(INT8U)(newprio>>3);
    x=(INT8u)(newprio&ox07);
    bity=(INT8U)(1<<y);
    bitx=(INT8U)(1<<x);

    #else
    y=(INT8U)((newprio>>4)&oxFF);
    x=(INT8U)((newprio&0x0f);
    bity=(INT16U)(1<<y);
    bitx=(INT16U)(1<<x);
    #endif

    OSTCBPrioTbl[oldprio]=(OS_TCB *)0;//插入NULL指针将指向当前OS_TCB的指针从优先级表中删除
    OSTCBPrioTbl[newprio]=ptcb; //将指向任务OS_TCB的指针存到OSTCBPrioTbl[]中·
    y_old=ptcb->OSTCBY;
    if((OSRdyTbl[y_old]&ptcb->OSTCBBitX)!=0) //改变优先级是否就绪
    {
    OSRdyTbl[y_old]&=~ptcb->OSTCBBitX;
    if(OSRdyTbl[y_old]==0)
    {
    OSRdyGrp&=~ptcb->OSTCBBitY;
    }
    //如果该任务处于就绪状态,它必须在当前的优先级下从就绪表总移除,然后在新的优先级下插入到就绪表中
    OSRdyGrp|=bity;
    OSRdyTbl[y]|=bitx;

    #if OS_EVENT_EN
    }else
    {
    pevent=ptcb->OSTCBEventPtr;
    if(prevent!=(OS_EVENT*)0)
    {//如果任务为就绪,任务正在等待信号量,邮件或者是消息队列
    prevent->OSEventTbl[y_old]&=~ptcb->OSTCBBitX;
    if(prevent->OSEventTbl[y_old]==0)
    {
    prevent->OSEventGrp&=~ptcb->OSTCBitY;
    }
    //如果任务在等待某一事件发生,OSTaskChangePrio()必须将任务从事件控制块的等待队列(在以前的优先级下)中移除,
    //并在新的优先级下将事件插入到等待队列中
    pevent->OSEventGrp|=bity;
    prevent->OSEventTbl[y]=bitx;
    }
    #endif
    }
    ptcb->OSTCBPrio=newprio;
    ptcb->OSTCBY=y;
    ptcb->OSTCBX=x;
    ptcb->OSTCBBitY=bity;
    ptcb->OSTCBBitX=bitx;
    OS_EXIT_CRITICAL();
    OS_Sched(); //任务调度程序被调用
    return (OS_NO_ERR);
    }

    //删除任务
    INT8U OSTaskDel(INT8U prio)
    {
    #if OS_CRITICAL_METHOD==3
    OS_CPU_SR cpu_sr;
    #endif

    #if OS_EVENT_EN>0
    OS_EVENT *prevent;
    #endif
    #if (OS_VERSION>=251)&&(OS_FLAG_EN>0)&&(OS_MAX_FLAGS>0)
    OS_FLAG_NODE *pnode;
    #endif
    OS_TCB *ptcb;
    BOOLEAN self;

    if(OSIntNesting>0) // 确保不是在中断服务子程序中调用
    {
    return (OS_TASK_DEL_ISR);
    }
    #if OS_ARG_CHK_EN>0
    if(prio==OS_IDLE_PRIO) //确保删除的不是空闲任务
    {
    return (OS_TASK_DEL_IDLE);
    }
    if(prio>=OS_LOWEST_PRIO&&prio!=OS_PRIO_SELF)
    {
    return (OS_PRIO_INVALID);
    }
    #endif
    OS_ENTER_CRITICAL();
    if(prio==OS_PRIO_SELF) //可以通过OS_PRIO_SELF参数来删除自己
    {
    prio=OSTCBCur->OSTCBPrio;
    }
    ptcb=OSTCBPrioTbl[prio];
    if(ptcb!=(OS_TCB *)0) //应确保任务是存在的
    {
    if((OSRdyTbl[ptcb->OSTCBY]&=~ptcb->OSTCBBitX)==0x00)
    {
    OSRdyGrp&=~ptcb->OSTCBBitY;
    }

    #if OS_EVENT_EN>0
    prevent=ptcb->OSTCBEventPtr;
    if(prevent!=(OS_EVENT *)0) //如果任务处于不兼容信号量,邮箱,消息队列或信号量的等待表中,从所在表中删除
    {
    if((pevent->OSEventTbl[ptcb->OSTCBY]&=~ptcb->OSTCBBitX)==0)
    OSRdyGrp&=~ptcb->OSTCBBitY;
    }
    }
    #endif
    #if (OS_VERSION>=251)&&(OS_FLAG_EN>0)&&(OS_MAX_FLAGS>0) //如果处于事件标志的等待表中,从此表删除
    pnode=ptcb->OSTCBFlagNode;
    if(pnode!=(OS_FLAG_NODE*)0)
    {
    OS_FlagUnlink(pnode);
    }
    #endif
    ptcb->OSTCBDly=0; //任务时钟节拍延迟数清零,
    ptcb->OSTCBStat=OS_STAT_RDY; //置任务的OSTCBStatOSSSTATRDY
    if(OSLockNesting<255)
    {
    OSLockNesting++;
    }
    OS_EXIT_CRITICAL();
    OS_Dummy(); //确保处理器在中断允许的情况下至少执行一个指令
    OS_ENTER_CRITICAL();
    if(OSLockNesting>0)
    {
    OSLockNesting--; //锁定嵌套计数器(OSLockNesting减1以重新允许任务调度
    }
    OSTaskDelHook(ptcb);
    OSTaskCtr--; //任务计数减—
    OSTCBPrioTbl[prio]=(OS_TCB *)0; //将指向被删除的任务的OS_TCB的指针指向NULL
    if(ptcb->OSTCBPrev==(OS_TCB *)0) //将被删除的任务OS_TCB双联表中移除
    {
    ptcb->OSTCBNext->OSTCBPrev=(OS_TCB *)0;
    OSTCBList=ptcb->OSTCBNext;
    }
    else
    {
    ptcb->OSTCBPrev->OSTCBNext=ptcb->OSTCBNext;
    ptcb->OSTCBNext->OSTCBPrev=ptcb->OSTCBPrev;
    }

    ptcb->OSTCBNext=OSTCBFreeList; //OS_TCB返OS_TCB表中,并允许其他任务的建立
    OSTCBFreeList=ptcb;
    OS_EXIT_CRITICAL();
    OS_Sched(); //调用任务调度程序
    return (OS_NO_ERR);
    }
    OS_EXIT_CRITICAL();
    return (OS_TASK_DEL_ERR);
    }


    //请求删除任务
    INT8U OSTaskDelReq(INT8U prio)
    {
    #if OS_CRITICAL_METHOD==3
    OS_CPU_SR cpu_sr;
    #endif
    BOOLEAN stat;
    INT8U err;
    OS_TCB *ptcb;
    #if OS_ARG_CHK_EN>0
    if(prio==OS_IDLE_PRIO) //如果需要被删除的任务是空闲任务,报错
    {
    return (OS_TASK_DEL_IDLE);
    }
    if(prio>=OS_LOWEST_PRIO&&prio!=OS_PRIO_SELF) //必须保证请求删除的优先级有效
    {
    return (OS_PRIO_INVALID);
    }
    #endif
    if(prio==OS_PRIO_SELF) //如果删除自身,存储在OS_TCB中的标志将返回
    {
    OS_ENTER_CRITICAL();
    stat=OSTCBCur->OSTCBDelReq;
    OS_EXIT_CRITICAL();
    return (stat);
    }
    ptcb=OSTCBPrioTbl[prio];
    if(ptcb!=(OS_TCB*)0)
    {
    ptcb->OSTCBDelReq=OS_TASK_DEL_REQ;
    err=OS_NO_ERR;
    }
    else
    {
    err=OS_TASK_NOT_EXIST; //如果任务不存在,返回错误信息
    }
    OS_EXIT_CRITICAL();
    return (err);
    }

    //请求删除其他任务的任务
    void RequestorTask(void *pdata)
    {
    INT8U err;
    pdata=pdata;
    for(;;)
    {
    if(TaskToBeDeleted())//需要被删除
    {
    while(OSTaskDelReq(TASK_TO_DEL_PRIO)!=OS_TASK_NOT_EXIST)
    {
    OSTimeDly(1);
    }
    }
    }
    }

    //需要删除自己的任务
    void TaskToBeDeleted(void *pdata)
    {
    INT8U err;
    pdata=pdata;
    for(;;)
    { //应用程序代码
    if(OSTaskDelReq(OS_PRIO_SELF)==OS_TASK_DEL_REQ)
    {
    //释放所有的占用资源
    //释放所有动态内存
    OSTaskDel(OS_PRIO_SELF);
    }
    else
    {
    //应用程序代码
    }
    }
    }
    Live together,or Die alone!
  • 相关阅读:
    事后诸葛亮
    OVS常用命令
    阿里云部署杂记
    Alpha冲刺总结
    测试随笔
    Alpha冲刺集合
    项目Alpha冲刺Day12
    项目Alpha冲刺Day11
    项目Alpha冲刺Day10
    MySQL修改密码
  • 原文地址:https://www.cnblogs.com/hzhida/p/2395669.html
Copyright © 2011-2022 走看看