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


相关推荐

  • 详谈利用系统漏洞及mysql提权

    详谈利用系统漏洞及mysql提权提权,顾名思义就是提升权限,当我们getshell⼀个⽹站之后,⼤部分情况下我们的权限是⾮常低的,这时就需要利⽤提权,让原本的低权限(如只允许列⽬录)→⾼权限(拥有修改⽂件的能⼒),权限提升后,对接下来的渗透有很⼤帮助

  • 浅谈CICD持续集成、持续部署的流程

    浅谈CICD持续集成、持续部署的流程Jenkins是一个比较流行的持续集成工具GitLab是存储镜像的镜像仓库由客户端将代码push推送到git仓库,gitlab上配置了一个webHook的东西可以触发Jenkins的构建。进入到Jenkins虚线范围内,它所做的事情非常多,从mvn构建代码,对代码进行静态分析,做单元测试,测试通过之后就可以build镜像,镜像构建成功后就把镜像push推送到Harbor镜像仓库中,镜像push…

  • js 推断 当页面无法回退时(history.go(-1)),关闭网页[通俗易懂]

    js 推断 当页面无法回退时(history.go(-1)),关闭网页

  • AngularJS自己定义标签加入回调函数eval()

    AngularJS自己定义标签加入回调函数eval()

  • 14种DLL注入技术

    14种DLL注入技术本文只是介绍各个注入的核心思想,详细的可以参照文末链接里的源码,一看就明白。本文只是介绍各个注入的核心思想,详细的可以参照文末链接里的源码,一看就明白。本文只是介绍各个注入的核心思想,详细的可以参照文末链接里的源码,一看就明白。第一种CreateRemoteThread远程线程调用DLL注入是指向某一个特定的进程空间强制插入一个特定的DLL文件映像,值得注意的是这种插入是强制性的插…

  • JDBC连接数据库的步骤

    JDBC连接数据库的步骤JDBC连接数据库一共有7步。1、首先加载驱动2、提供JDBC连接的URL3、创建数据库的连接4、创建一个statement执行者5、执行SQL语句6、处理返回结果7、关闭JDBC对象

发表回复

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

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