启动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);
}

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

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

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • pycharm2021年 激活码(最新序列号破解)

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

  • 国产的FPGA_能不能长点心

    国产的FPGA_能不能长点心关注、星标公众号,直达精彩内容FPGA作为嵌入式必备的一个硬件,国产的产品也正在逐渐渗透工程师的生活之中。不过tzgok认为,目前国产FPGA还有几个问题非常令人困扰,并发出评论表示“国产…

  • vue 生成二维码 插件

    vue 生成二维码 插件1.下载qr插件npmivue-qr–save2.引入//引入插件importVueQrfrom’vue-qr’//放入componentscomponents:{VueQr}3.使用//页面使用<vue-qrtext=”这是你的二维码内容”size=”200″:margin=”0″/>4.效果

  • AllinOne安装OpenStack

    AllinOne安装OpenStack1.虚拟机的配置准备内存:8G+CPU:2|2网络设置:NAT硬盘设置:100G+2.启动虚拟机3.网络配置vi/etc/sysconfig/network添加内容:NETWORKING=yes

    2022年10月25日
  • 记一次CTF的USB流量分析

    记一次CTF的USB流量分析最近在研究鼠标流量,找到如下的文章:https://www.cnblogs.com/hackxf/p/10670844.html根据这个师傅的说法,不同的鼠标抓到的流量不一样,一般的鼠标流量是四个字节,第一个字节表示按键指示左键右键,第二个字节表示水平位移,为正(小于127)是向右移动,为负(补码负数,大于127小于255)是向左移动。第三个字节表示垂直位移,为正(小于127)是向上移动,为负…

  • 浅析Apache中RewriteRule和RewriteCond规则参数的详细介绍[通俗易懂]

    浅析Apache中RewriteRule和RewriteCond规则参数的详细介绍[通俗易懂]参考: http://www.jb51.net/article/39298.htm  http://www.cnblogs.com/scgw/archive/2011/05/01/2033730.html正则的链接: http://baike.baidu.com/item/%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8F

发表回复

您的电子邮箱地址不会被公开。

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