启动ucosii之四OSTaskCreate()[通俗易懂]

启动ucosii之四OSTaskCreate()[通俗易懂]函数原型来自OS_TASK.C/***********************************************************************************************************                                           CREATEATASK**************

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

函数原型来自OS_TASK.C
/**********************************************************************************************************
*                                            CREATE A TASK
**********************************************************************************************************/
//uC/OS-II是通过任务控制块来管理任务的,因此创建任务的工作实质上是给任务的代码分配一个任务控制块,并通过任务控制块把任务代码和任务堆栈关联起来形成一个完整的任务.当然还要使刚创建的任务进入就绪状态,并接着引发一次任务调度.
//uC/OS-II有两个用来创建任务的函数:OSTaskCreate()和OSTaskCreateExt().
//其中函数OSTaskCreateExt()是OSTaskCreate()的扩展,并提供一些附加功能.
//用户可根据需要使用这两个函数之一来完成任务的创建工作.
//OSTaskCreate ()函数主要完成3项工作:任务堆栈的初始化,任务控制块的初始化和任务调度.任务代码的指针并不是存放在任务控制块中的,而是存放在任务堆栈里面.
//一般来说,任务可在调用函数OSStart()启动任务调度之前来创建,也可在任务中来创建.但是,uC/OS-II有一个规定:在调用启动任务函数OSStart()之前,必须已经创建了最少一个任务.因此,习惯上在调用函数OSStart()之前先创建一个任务,并赋予它最高的优先级别,从而使它成为起始任务,然后在这个起始任务中,再创建其他各任务.

#if OS_TASK_CREATE_EN > 0 //OS_CFG配置文件.配置一些常数,编译时根据这些常数决定某代码段是否编译
//task是任务代码指针,pdata是传递给任务的参数的指针,ptos是分配给任务的堆栈栈顶指针,prio是分配给任务的优先级
INT8U  OSTaskCreate (void (*task)(void *pd), void *pdata, OS_STK *ptos, INT8U prio)
{

#if OS_CRITICAL_METHOD == 3                  /* Allocate storage for CPU status register               */
    OS_CPU_SR  cpu_sr;
#endif
    OS_STK    *psp;
    INT8U      err;

#if OS_ARG_CHK_EN > 0 //OS_CFG配置文件.配置一些常数,编译时根据这些常数决定某代码段是否编译
//检测分配给任务的优先级是否有效,任务的优先级必须在0到OS_LOWEST_PRIO之间
    if (prio > OS_LOWEST_PRIO) {             /* Make sure priority is within allowable range           */
        return (OS_PRIO_INVALID);//uCOS_II.h→ERROR CODES
    }
#endif
    OS_ENTER_CRITICAL();//代码临界段,不允许中断

    //确保在规定的优先级上还没有建立任务-uCOS_II.h→GLOBAL VARIABLES→OS_TCB *OSTCBPrioTbl[OS_LOWEST_PRIO + 1]
    if (OSTCBPrioTbl[prio] == (OS_TCB *)0) { /* Make sure task doesn’t already exist at this priority  */
 //通过放置一个非空指针在OSTCBPrioTbl[]中来保留该优先级
 //如果规定的优先级为空,即还没有被用于任务,那么就可以用该优先级,设为(OS_TCB *)1
        OSTCBPrioTbl[prio] = (OS_TCB *)1;    /* Reserve the priority to prevent others from doing …  */
                                             /* … the same thing until task is created.              */

        OS_EXIT_CRITICAL();//设置任务数据结构的其他部分时重新允许中断

 //建立任务的堆栈,OSTaskStkInit()函数返回新的堆栈栈顶(psp),并保存在任务的0S_TCB中
 //任务堆栈初始化就是对栈顶指针和寄存器进行初始化,OSTaskStkInit()函数的定义在OS_CPU_C.C文件中.
        psp = (OS_STK *)OSTaskStkInit(task, pdata, ptos, 0);    /* Initialize the task’s stack         */

 //调用OS_CORE.c→OSTCBInit(),从空闲的OS_TCB池中获得并初始化一个OS_TCB
        err = OS_TCBInit(prio, psp, (OS_STK *)0, 0, 0, (void *)0, 0);
 //返回一个代码表明OS_TCB已经被分配和初始化

        if (err == OS_NO_ERR) {//uCOS_II.h→ERROR CODES
            OS_ENTER_CRITICAL();//代码临界段,不允许中断

     //如果OSTCBInit()返回成功,就增加OSTaskCtr(用于保存产生的任务数目)
            OSTaskCtr++;/* Increment the #tasks counter        */
     //OSTaskCreateHook(OSTCBPrioTbl[prio]);//用户自己定义的函数,用来扩展OSTaskCreate()的功能
            OS_EXIT_CRITICAL();//退出临界段 (开中断)

     //如果OSTaskCreate()函数是在某个任务的执行过程中被调用(即OSRunning置为True)
            if (OSRunning == TRUE) {         /* Find highest priority task if multitasking has started */
                OS_Sched();//调用任务调度函数以判断是否新建立的任务比原来的任务有更高的优先级
            }
        }
 else {

            OS_ENTER_CRITICAL();//代码临界段,不允许中断
     //如果OSTCBInit()返回失败,就置OSTCBPrioTbl[prio]的入口为0,以放弃该任务的优先级
            OSTCBPrioTbl[prio] = (OS_TCB *)0;/* Make this priority available to others                 */
            OS_EXIT_CRITICAL();//退出临界段 (开中断)
        }
        return (err);
    }
    OS_EXIT_CRITICAL();//退出临界段 (开中断)
    return (OS_PRIO_EXIST);//uCOS_II.h→ERROR CODES
}
#endif

函数原型来自OS_CORE.C
//任务控制块初始化函数
INT8U  OS_TCBInit (INT8U prio, OS_STK *ptos, OS_STK *pbos, INT16U id, INT32U stk_size, void *pext, INT16U opt)
{

#if OS_CRITICAL_METHOD == 3                                /* Allocate storage for CPU status register */
    OS_CPU_SR  cpu_sr;
#endif   
    OS_TCB    *ptcb;

    OS_ENTER_CRITICAL();

//OSInit()→OS_InitTCBList();/* 初始化任务控制块 */→OSTCBFreeList
//获得空闲任务控制块列表头指针
    ptcb = OSTCBFreeList;                                  /* Get a free TCB from the free TCB list    */

//如果缓冲池有空余TCB,这个TCB被初始化
    if (ptcb != (OS_TCB *)0) {

//将控制块列表头交给新建任务,OSTCBFreeList指向该任务的下一个控制块
//OSTCBFreeList指向TCB的双向链接的后链接
        OSTCBFreeList        = ptcb->OSTCBNext;            /* Update pointer to free TCB list          */
        OS_EXIT_CRITICAL();

//初始化控制块各个参数
//指向当前TCB的栈顶指针
        ptcb->OSTCBStkPtr    = ptos;                       /* Load Stack pointer in TCB                */
//保存当前TCB的优先级别
        ptcb->OSTCBPrio      = (INT8U)prio;                /* Load task priority into TCB              */
//设定当前TCB的状态字
        ptcb->OSTCBStat      = OS_STAT_RDY;                /* Task is ready to run                     */
//设定当前TCB的延时时间-允许任务等待的最大字节节拍为0
        ptcb->OSTCBDly       = 0;                          /* Task is not delayed                      */

#if OS_TASK_CREATE_EXT_EN > 0
//指向用户定义的任务控制块(扩展指针)
        ptcb->OSTCBExtPtr    = pext;                       /* Store pointer to TCB extension           */
//设定堆栈的容量
        ptcb->OSTCBStkSize   = stk_size;                   /* Store stack size                         */
//指向堆栈栈底的指针
        ptcb->OSTCBStkBottom = pbos;                       /* Store pointer to bottom of stack         */
//保存OS_TCB的选择项
        ptcb->OSTCBOpt       = opt;                        /* Store task options                       */
//保存任务标志符
        ptcb->OSTCBId        = id;                         /* Store task ID                            */
#else
//扩展指针
        pext                 = pext;                       /* Prevent compiler warning if not used     */
//堆栈的容量
        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;                  /* Pre-compute X, Y, BitX and BitY          */
        ptcb->OSTCBBitY      = OSMapTbl[ptcb->OSTCBY];
//优先级所在列
        ptcb->OSTCBX         = prio & 0x07;
        ptcb->OSTCBBitX      = OSMapTbl[ptcb->OSTCBX];

#if OS_EVENT_EN > 0
        ptcb->OSTCBEventPtr  = (OS_EVENT *)0;              /* Task is not pending on an event          */
#endif

//针对的事件为信号量,互斥型信号量,消息邮箱,消息队列,当满足版本大于2.51且事件标志允许且有最大事件标志及允许删除任务
#if (OS_VERSION >= 251) && (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) && (OS_TASK_DEL_EN > 0)
//指向事件标志节点的指针被初始化为空指针
        ptcb->OSTCBFlagNode  = (OS_FLAG_NODE *)0;          /* Task is not pending on an event flag     */
#endif

#if (OS_MBOX_EN > 0) || ((OS_Q_EN > 0) && (OS_MAX_QS > 0))
//满足以上条件,指向传递给任务的消息指针初始化为0空指针
        ptcb->OSTCBMsg       = (void *)0;                  /* No message received                      */
#endif

#if OS_VERSION >= 204
        OSTCBInitHook(ptcb);
#endif

        OSTaskCreateHook(ptcb);                            /* Call user defined hook                   */
       
        OS_ENTER_CRITICAL();

//prio优先级匹配对应的任务控制块指针
        OSTCBPrioTbl[prio] = ptcb;
//链接到任务控制块链接串
        ptcb->OSTCBNext    = OSTCBList;                    /* Link into TCB chain                      */
        ptcb->OSTCBPrev    = (OS_TCB *)0;
//由此看出,任务总是不停的向前添加
        if (OSTCBList != (OS_TCB *)0) {

            OSTCBList->OSTCBPrev = ptcb;//当前新创建的任务控制块指针
        }
        OSTCBList               = ptcb;//OSTCBList指针更新

//这里用了’|’或运算.
//因为任务可能不止一个,但是基于任务的数量,行号只会在0-7之间
//eg:prio=12,那么该任务处在行号1,对应OSMapTab[1]=0000 0010
//eg:prio=23,那么该任务处在行号2,对应OSMapTab[2]=0000 0100
//那么OSRdyGrp=0000 0010|0000 0100=0000 0110
        OSRdyGrp               |= ptcb->OSTCBBitY;         /* Make task ready to run                   */
//同理
//eg:prio=12,那么该任务处在列号4,对应OSMapTab[1]=0001 0000
//eg:prio=23,那么该任务处在列号7,对应OSMapTab[2]=1000 0000
//因为不同的行拥有同样的列号0-7,所以采用OSRdyTbl[OSRdyGrp],进行或运算的必然属于同行
        OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX;
        OS_EXIT_CRITICAL();

//调用成功,最后让此函数返回到调用函数[OSTaskCreate()或OSTaskCreateExt()函数]
//返回值表示分配到任务控块,并初始化了
        return (OS_NO_ERR);
    }
    OS_EXIT_CRITICAL();
//没有更多的任务控制块被分配,将无法创建新的任务
    return (OS_NO_MORE_TCB);
}

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/196738.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • QQ自动强制加好友代码

    强行聊天的代码:tencent://Message/?Uin=919433667&websiteName=www.oicqzone.com&Menu=yes强行加好友的代码:tencent://AddContact/fromId=45&fromSubId=1&subcmd=all&uin=574201314&fuin=919433667&w…

    2022年4月6日
    4.7K
  • subline text 激活码(最新序列号破解)[通俗易懂]

    subline text 激活码(最新序列号破解),https://javaforall.net/100143.html。详细ieda激活码不妨到全栈程序员必看教程网一起来了解一下吧!

    2022年3月19日
    58
  • cisco光纤交换机配置「建议收藏」

    cisco光纤交换机配置「建议收藏」1.初始化信息首次设置,必须通过console进行连接(需要U口转DB9针的接口线,专门卖接口线的有卖大约30元),然后进行初始化设计,以后设定IP后可通过LAN进行登陆具体步骤:(红色字体部分着重注意,需要进行设置,大部分按照默认设置即可,而且设置的部分进入管理工具软件可以更改)—-SystemAdminAccountSetup—-Enterthep…

    2022年5月21日
    108
  • Mac下homebrew安装

    Mac下homebrew安装需要替换国内镜像 usr bin ruby e curl fsSLhttps cdn jsdelivr net gh ineo6 homebrew install install 该脚本用了中科大镜像加速访问 仅修改仓库地址部分 不会产生安全隐患 关于中科大所提供的 Homebrew 镜像服务 https lug ustc edu cn wiki mirrors help brew git 以下是中科大的 Homebrew 安装帮助 Homebrew

    2025年8月5日
    5
  • 关于pdb文件

    关于pdb文件关于pdb文件当程序在VS上编译时,程序所依赖的所有动态链接库(dll文件)也会被编译,编译过程中每个dll都会产生一个pdb文件,又称为“符号文件”,是一个存储数据的信息文件,其包含dll库在编译过程的某些调试信息,例如程序中所用到的全局变量、局部变量、函数名以及他们的入口地址等。当使用VS调试程序时,会默认加载你的程序以及程序依赖的dll库产生的所有pdb文件,但是结…

    2022年6月2日
    60
  • JavaScript清空数组的三种方法

    JavaScript清空数组的三种方法1、length用length方法可以很轻松地清空数组,代码示例:vararr=[1,2,3];console.log(arr);arr.length=0;console.log(arr);结果如下:2、splisesplice()方法向/从数组中添加/删除项目,然后返回被删除的项目vararr=[1,2,3]…

    2022年6月9日
    46

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号