启动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)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • Pytest(13)命令行参数–tb的使用

    Pytest(13)命令行参数–tb的使用前言pytest使用命令行执行用例的时候,有些用例执行失败的时候,屏幕上会出现一大堆的报错内容,不方便快速查看是哪些用例失败。–tb=style参数可以设置报错的时候回溯打印内容,可以设置参

    2022年7月31日
    3
  • 用new创建数组

    用new创建数组用new创建数组用new创建数组的优势由于new创建的对象是在运行时确立的,所以有着具体情况具体分析的优点,那么什么叫做具体情况具体分析呢?我觉得c++primerplus的一个例子十分贴切——比如你在度假,已经做好每天的参观计划,可突然有一天天气不好或你心情不好,此时你就不想参观了,如果此时是在编译状态,系统是不允许的,你必须按照计划去参观,但运行时状态,系统是允许的,此时你就可以呆在酒店尽情的玩耍了。用new创建数组也有此优点,即数组长度可以根据情况而定。比如说创建10个元素的数组,可以如下代

    2022年5月15日
    35
  • 多重共线性检验之方差膨胀因子VIF[通俗易懂]

    多重共线性检验之方差膨胀因子VIF[通俗易懂]过程1、构造每一个自变量与其余自变量的线性回归模型,例如,数据集中含有p个自变量,则第一个自变量与其余自变量的线性组合可以表示为2、根据如上线性回归模型得到相应的判决系数R2R^2R2,进而计算第一个自变量的方差膨胀因子VIF:importpandasaspdimportnumpyasnpfromsklearnimportmodel_selectionimportstatsmodels.apiassnfromstatsmodels.stats.outlier

    2022年6月6日
    243
  • 设置css属性clear的值为什么时可清除左右两边浮动_clear both

    设置css属性clear的值为什么时可清除左右两边浮动_clear bothDIV+CSSclearboth清除产生浮动我们知道有时使用了cssfloat浮动会产生css浮动,这个时候就需要清理清除浮动,我们就用clear样式属性即可实现。接下来我们来认识与学习cssclear知识与用法一、clear语法与结构clear:none|left|right|both2、clear参数值说明none: 允

    2022年9月4日
    4
  • sql存储过程简单例题_sql存储过程实例详解

    sql存储过程简单例题_sql存储过程实例详解1、创建存储过程P1,查询每个学生的修课门数,要求列出学生学号、姓名及修课门数。createprocP1asselectStudent.StudentID,StudentName,count(CourseID)选修门数fromStudentjoinGradeonGrade.StudentID=Student.StudentIDgroupbyStudent.StudentID,StudentNamego2、创建存储过程P2,查询学生的学号、姓名、课程名、成绩

    2022年9月1日
    3
  • Pycharm 提示:this license * has been cancelled – Python零基础入门教程

    Pycharm 提示:this license * has been cancelled – Python零基础入门教程目录一.前言一.找到hosts文件二.修改hosts文件三.检查hosts文件是否修改成功四.pycharm安装激活详细教程五.猜你喜欢一.前言零基础Python学习路线推荐:Python学习目录>>Python基础入门Pycharm安装激活过程中,提示thislicense****hasbeencancelled。这个问题并不是你的激活码不对,而是需要修改系统的hosts文件,下面详细讲解下如何修改hosts文件

    2022年8月26日
    2

发表回复

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

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