精华内容
下载资源
问答
  • 程序清单 L6.5是函数OSEventWaitListInit()的源代码。当建立一个信号量、邮箱或者消息队列时,相应的建立...该函数初始化一个空的等待任务列表,其中没有任何任务。该函数的调用参数只有一个,就是指向需要初始化的事件
    程序清单 L6.5是函数OSEventWaitListInit()的源代码。当建立一个信号量、邮箱或者消息队列时,相应的建立函数OSSemInit(),OSMboxCreate(),或者OSQCreate()通过调用OSEventWaitListInit()对事件控制块中的等待任务列表进行初始化。该函数初始化一个空的等待任务列表,其中没有任何任务。该函数的调用参数只有一个,就是指向需要初始化的事件控制块的指针pevent。
    
    程序清单 L6.5 初始化ECB块的等待任务列表
    void OSEventWaitListInit (OS_EVENT *pevent)
    {
        INT8U i;
        pevent->OSEventGrp = 0x00;
        for (i = 0; i < OS_EVENT_TBL_SIZE; i++) {
            pevent->OSEventTbl[i] = 0x00;
        }
    }

    展开全文
  • UC/OS-II基础知识之事件控制块及事件处理函数1.等待任务列表 作为功能完善的事件,应该对那些处于等待任务具有两方面的管理功能,一是要对等待事件的所有任务进行记录并排序,而是允许等待任务有一个等待时限,即当...

    UC/OS-II基础知识之事件控制块及事件处理函数

    1.等待任务列表
    作为功能完善的事件,应该对那些处于等待任务具有两方面的管理功能,一是要对等待事件的所有任务进行记录并排序,而是允许等待任务有一个等待时限,即当等待任务认为等不及时可以退出对事件的请求。对于等待事件任务的记录,系统使用了与任务就绪表类似的位图,即定义了一个INT8U类型的数组OSEventTbl【】作为等待事件任务的记录表,即等待任务表。
    等待任务表仍然以任务的优先级别为顺序为每个任务分配一个二进制位,并用该为为1来表示这一位对应的任务为事件的等待任务,否则不是等待任务。同样为了加快对该表的访问,也定义了一个INT8U类型的变量OSEventGrp来表示等待任务表中的任务组,示意图如下所示:

    至于等待任务的时限则记录在等待任务的任务控制块TCB的成员OSTCBDly中。每当有任务的等待时限到达时,便将该任务从等待任务表中删除,并使他进入就绪状态。
    2.事件控制块的结构
    为了将描述事件的数据结构统一起来,UC/OS-II使用事件控制块ECB的数据结构来描述如信号量,信号队列和邮箱这些事件。事件控制块的数据结构如下所示:

    typedef struct os_event {
        INT8U    OSEventType;                    /* Type of event control block (see OS_EVENT_TYPE_xxxx)    */
        void    *OSEventPtr;                     /* Pointer to message or queue structure                   */
        INT16U   OSEventCnt;                     /* Semaphore Count (not used if other EVENT type)          */
    #if OS_LOWEST_PRIO <= 63
        INT8U    OSEventGrp;                     /* Group corresponding to tasks waiting for event to occur */
        INT8U    OSEventTbl[OS_EVENT_TBL_SIZE];  /* List of tasks waiting for event to occur                */
    #else
        INT16U   OSEventGrp;                     /* Group corresponding to tasks waiting for event to occur */
        INT16U   OSEventTbl[OS_EVENT_TBL_SIZE];  /* List of tasks waiting for event to occur                */
    #endif
    
    #if OS_EVENT_NAME_SIZE > 1
        INT8U    OSEventName[OS_EVENT_NAME_SIZE];
    #endif
    } OS_EVENT;
    #endif

    应用程序中的任务通过指针pevent来访问事件控制块,事件控制块结构示意图如下图所示

    成员OSEventType为事件的类型如下表所示

    成员OSEventPtr主要用来存放消息邮箱或者消息队列的指针。
    成员OSEventCnt为信号量的计数器。
    成员OSEventTbl[OS_EVENT_TBL_SIZE]表示等待任务表。
    3.对事件控制块的操作
    UC/OS-II有四个对事件控制块进行基本操作的函数(定义在OS_CORE.C)
    3.1事件控制块的初始化
    调用函数OS_EventWaitListInit()可以对事件控制块进行初始化。函数原型如下

    #if OS_EVENT_EN
    void  OS_EventWaitListInit (OS_EVENT *pevent)
    {
    #if OS_LOWEST_PRIO <= 63
        INT8U  *ptbl;
    #else
        INT16U *ptbl;
    #endif
        INT8U   i;
        pevent->OSEventGrp = 0;                      /* No task waiting on event                           */
        ptbl               = &pevent->OSEventTbl[0];
    
        for (i = 0; i < OS_EVENT_TBL_SIZE; i++) {
            *ptbl++ = 0;
        }
    }

    这个函数的作用就是把OSEventGrp及任务等待表中每一位都请0,即令事件的任务等待表中不含任何等待任务
    事件控制块被初始化后的情况如下所示

    3.2使一个任务进入等待状态的函数
    把一个任务至于等待状态要调用函数OS_EventTaskWait()函数原型如下

    void  OS_EventTaskWait (OS_EVENT *pevent)
    {
        INT8U  y;
    
        OSTCBCur->OSTCBEventPtr = pevent;             /* Store pointer to event control block in TCB       */
        y                       = OSTCBCur->OSTCBY;   /* Task no longer ready                              */
        OSRdyTbl[y]            &= ~OSTCBCur->OSTCBBitX;
        if (OSRdyTbl[y] == 0) {
            OSRdyGrp &= ~OSTCBCur->OSTCBBitY;         /* Clear event grp bit if this was only task pending */
        }
        pevent->OSEventTbl[OSTCBCur->OSTCBY] |= OSTCBCur->OSTCBBitX;          /* Put task in waiting list  */
        pevent->OSEventGrp                   |= OSTCBCur->OSTCBBitY;
    }

    3.3使一个任务进入就绪状态的函数
    把一个任务至于等待状态要调用函数OS_EventTaskRdy()函数原型如下

    INT8U  OS_EventTaskRdy (OS_EVENT *pevent, void *msg, INT8U msk)
    {
        OS_TCB  *ptcb;
        INT8U    x;
        INT8U    y;
        INT8U    prio;
    #if OS_LOWEST_PRIO <= 63
        INT8U    bitx;
        INT8U    bity;
    #else
        INT16U   bitx;
        INT16U   bity;
        INT16U  *ptbl;
    #endif
    
    
    #if OS_LOWEST_PRIO <= 63
        y     = OSUnMapTbl[pevent->OSEventGrp];             /* Find HPT waiting for message                */
        bity  = (INT8U)(1 << y);
        x     = OSUnMapTbl[pevent->OSEventTbl[y]];
        bitx  = (INT8U)(1 << x);
        prio  = (INT8U)((y << 3) + x);                      /* Find priority of task getting the msg       */
    #else
        if ((pevent->OSEventGrp & 0xFF) != 0) {             /* Find HPT waiting for message                */
            y = OSUnMapTbl[pevent->OSEventGrp & 0xFF];
        } else {
            y = OSUnMapTbl[(pevent->OSEventGrp >> 8) & 0xFF] + 8;
        }
        bity = (INT16U)(1 << y);
        ptbl = &pevent->OSEventTbl[y];
        if ((*ptbl & 0xFF) != 0) {
            x = OSUnMapTbl[*ptbl & 0xFF];
        } else {
            x = OSUnMapTbl[(*ptbl >> 8) & 0xFF] + 8;
        }
        bitx = (INT16U)(1 << x);
        prio = (INT8U)((y << 4) + x);                       /* Find priority of task getting the msg       */
    #endif
    
        pevent->OSEventTbl[y] &= ~bitx;                     /* Remove this task from the waiting list      */
        if (pevent->OSEventTbl[y] == 0) {
            pevent->OSEventGrp &= ~bity;                    /* Clr group bit if this was only task pending */
        }
        ptcb                 =  OSTCBPrioTbl[prio];         /* Point to this task's OS_TCB                 */
        ptcb->OSTCBDly       =  0;                          /* Prevent OSTimeTick() from readying task     */
        ptcb->OSTCBEventPtr  = (OS_EVENT *)0;               /* Unlink ECB from this task                   */
    #if ((OS_Q_EN > 0) && (OS_MAX_QS > 0)) || (OS_MBOX_EN > 0)
        ptcb->OSTCBMsg       = msg;                         /* Send message directly to waiting task       */
    #else
        msg                  = msg;                         /* Prevent compiler warning if not used        */
    #endif
        ptcb->OSTCBPendTO    = OS_FALSE;                    /* Cancel 'any' timeout because of post        */
        ptcb->OSTCBStat     &= ~msk;                        /* Clear bit associated with event type        */
        if (ptcb->OSTCBStat == OS_STAT_RDY) {               /* See if task is ready (could be susp'd)      */
            OSRdyGrp        |=  bity;                       /* Put task in the ready to run list           */
            OSRdyTbl[y]     |=  bitx;
        }
        return (prio);
    }
    #endif

    该函数的作用就是把调用这个函数的任务在任务等待列表中的位置清0,再把任务就绪表中对应的位置1,然后引发一次中断。
    3.4使一个等待超时的任务进入就绪状态的函数
    如果一个正在等待事件的任务已经超过了等待事件,却任然没有获得事件等原因而未具备运行的条件,却又要使他进入就绪状态,这时需要调用OS_EventTO()函数

    void  OS_EventTO (OS_EVENT *pevent)
    {
        INT8U  y;
    
    
        y                      = OSTCBCur->OSTCBY;
        pevent->OSEventTbl[y] &= ~OSTCBCur->OSTCBBitX;     /* Remove task from wait list                   */
        if (pevent->OSEventTbl[y] == 0x00) {
            pevent->OSEventGrp &= ~OSTCBCur->OSTCBBitY;
        }
        OSTCBCur->OSTCBPendTO   = OS_FALSE;                /* Clear the Pend Timeout flag                  */
        OSTCBCur->OSTCBStat     = OS_STAT_RDY;             /* Set status to ready                          */
        OSTCBCur->OSTCBEventPtr = (OS_EVENT *)0;           /* No longer waiting for event                  */
    }

    3.5空事件控制块链表
    UC/OS-II在初始化时,系统会在初始化函数OSInit()中按应用程序使用事件OS_MAX_EVENT(在OS_CFG.H定义)创建OS_MAX_EVENT个空事件控制块。每当创建一个事件时,系统会从时间控制块链表中取出一个空事件控制块,并对他进行初始化以描述该事件,当应用程序删除一个事件时,系统会将该事件的控制块归还给空事件控制块链表。空事件控制块链表如下所示

    展开全文
  • 继续上一节的讲解,uCOS-II通过OSTaskCreate()和OSTaskCreateExt()来创建任务,后者相当于前者的一些扩展。 下面对OSTaskCreate()的源码进行讲解:   INT8U OSTaskCreate( void (*task)(void *pd),...

    继续上一节的讲解,uCOS-II通过OSTaskCreate()和OSTaskCreateExt()来创建任务,后者相当于前者的一些扩展。

    下面对OSTaskCreate()的源码进行讲解:

     

    INT8U OSTaskCreate(  void (*task)(void *pd), //指向任务的指针
                          void * pdata,                //传递给任务的参数
                          OS_STK * ptos,              //指向任务堆栈栈顶指针
                          INT8U  prio                //任务的优先级
                       )
    {
        #if OS_CRITCAL_METHOD == 3
        OS_CPU_SR cpu_sr;
        #endif
      
        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
                           );                       //获得并初始化任务控制块
            if(err == OS_NO_ERR)
            {
                 OS_ENTER_CRITICAL();
                 OSTaskCtr++;             //任务计数器+1
                 OS_EXIT_CRITICAL();
                 if(OSRunning)
                 {
                     OSSChed();
                 }
            }
            else
            {
                OS_ENTER_CRITICAL();
                OSTCBPrioTbl[prio] = (void *)0;      //放弃任务
                OS_EXIT_CRITICAL();
            } 
            return (err);
        }
        else
        {
             OS_EXIT_CRITICAL();
        }
    }
    

    从上述源码我们可以看到,函数对创建任务的优先级先进行判断,确定合法后,调用OSTaskStkInit()  和 OSTCBInit()对任务堆栈和任务控制块进行初始化,初始化完成后,除了把任务计数器+1外,还要对CPU是否处于运行状态,为1则调用函数OSSched()任务调度。

    创建任务的一般方法:

    一般来说,任务可在调用OSStart()启动调度任务之前创建,也可在任务中创建,但是在uCOS-II中,在调用OSStart()之前,系统必须已经创建了一个任务。因此习惯上在OSStart()之前创建一个任务,并赋予这个任务最高优先级,使其成为起始任务,在起始任务中再创建其他任务。

    注意:如果要使用系统提供的统计任务,则必须在起始任务中的初始化函数中调用统计任务的初始化函数。

    下面是创建任务的示意性代码:

    void main()
    {
         .....   
         OSInit();       //对uCOS进行初始化
         .....
         OSTaskCreate(TaskStart,......);     //创建起始任务TaskStart
         OSStart();                //开始多任务调度
    }
    
    
    
    void main()
    {
    
       .....  //在这个位置安装并启动uCOS的时钟
       OSStatInit();      //初始化统计任务
       ....... //在这个位置创建其他任务
       for(;;)
       {
            //起始任务TaskStart的代码
       }  
    }
    
    //特别注意:uCOS-II不允许在中断服务中创建任务

    挂起任务:

    挂起任务函数OSTaskSuspend(INT8U prio)如果任务挂起自身参数为常数OS_PRIO_SELF,从下面的流程图可以看出,首先判断将要挂起的任务是否是自身,若是,则必须删除该任务在任务就绪表中的就绪标志,并在任务控制块成员OSTCBStat中做挂起记录,引发一次任务调度,以使CPU去运行就绪的其他任务。若果不是任务自身,那么只要删除任务就绪表中被挂起任务的就绪状态,并在任务控制块成员OSTCBStat中做挂起记录。

     

    恢复任务:

    恢复任务函数INT8U    OSTaskResume(INT8U prio).  从下面的流程图可以看出函数在判断任务确实是一个已存在的挂起任务,同时它又不是一个等待任务(任务控制块成员OSTCBDly =0)时,就会清除任务控制块成员OSTCBStat中的挂起记录并使任务就绪,最后调用调度器OSSched()进行任务调度,并返回函数调用成功的信息OS_NO_ERR。

    任务优先级的修改:

    没啥要说的,知道去调用这个函数就可以了

    INT8U OSTaskChangePrio(
    
                            INT8U oldprio; //任务现在的优先级别  
                            INT8U newprio;  //要改为的优先级别
                           );

    任务的删除;

    所谓删除,不是真的删除,是将该任务置于睡眠状态。具体操作就是把删除任务的任务控制块从任务控制块链表中删除,并归还给空白控制块链表,然后在任务就绪表中把该任务的就绪状态置为0,这样就不会被调度器调用。

    通过调用OSTaskDel(INT8U prio)来删除任务自身或者除了空闲任务之外的其他任务,有的人说了,我看你之前写的代码也没看到你你创建空闲任务,这个是系统在你调用函数OSInit()自动完成的。删除自身参数为OS_PRIO_SELF。

    我们知道任务有时候会占用一些动态分配的内存或者信号量之类的资源。这就涉及到内存管理了,最严重直接后果就是系统死机。所以uCOS-II提出,删除任务请求的任务只负责提出删除请求,具体删除内容由被删除任务自己完成。

    显然想要使删除任务请求的任务和被删除任务之前能够像上述方式执行,双方必须存在通信。uCOS-II利用被删除任务的任务控制块成员OSTCBDelReq作为请求删除方的被删除方的联络信号,同时提供一个双方都能调用的函数--请求删除任务函数OSTCBDelReq(INT8U prio),这样双方就都能使用这个函数来访问OSTCNDelReq这个信号,从而可以根据这个信号的状态来决定各自的行为。

    提出删除任务请求的任务在调用这个函数是,参数为被删除任务的优先级别,被删除任务在调用这个函数是,参数是OS_PRIO_SELF。

    查询任务的信息:

    没啥好说的,调用这个函数成功返回OS_NO_ERR,查询的信息存放在OS_TCB结构类型的变量中

    INT8U OSTaskQuery(
                         INT8U prio;   //待查询任务的优先级别
                         OS_TCB *pdata;  //存储任务信息的结构
                      );

    uCOS-II的初始化和任务的启动

    在使用uCOS-II的所有服务之前,必须调用uCOS-II的初始化函数OSInit(),对自身环境进行初始化。

    函数OSInit()将对uCOS-II的所以噗全局变量和数据结构进行初始化,同时创建空闲任务OSTaskidle,并辅之以最低优先级和永远就绪的状态,如要使用统计任务(常数OS_TASK_STAT_EN = 1),则OSInit()还要以优先级别为OS_LOWEST_PRIO-1来创建统计任务。

    初始化OSInit()在对数据结构进行初始化时,主要创建包括空任务控制块链表在内的5个空数据缓冲区。同时为了可以快速查询任务控制块链表中的各个元素,OSInit()还要创建一个数组OSTCBPrioTbl[OS_LOWEST+1],在这个数据中,按任务的优先级别顺序把任务控制块的指针存放在对应的元素中。

    uCOS-II启动:

    uCOS-II进行任务的管理是从调用启动任务函数OSStart()开始的,当然前提条件是系统至少创建了一个任务。源代码如下:

    void OSStart (void)
    {
         INT8U y;
         INT8U x;
     
         if(OSRunning == FALSE)
         {
            y = OSUnMapTbl[OSRdyGrp];
            x = OSUnMapTbl[OSRdyTbl[y]];
            OSPrioHighRdy = (INT8U) ((y<<3)+x);
            OSPrioCur = OSPrioHighRdy;
            OSTCBHighRdy = OSTCBPrioTbl[OSPrioHighRdy];
            OSTCBCur = OSTCBHighRdy;
            OSStartHighRdy(); 
         }
    }

    OSStartHighRdy()在多任务系统启动函数OSStart()中调用。完成的功能是:设置系统运行标志OSRunning = TRUE,将就绪表中最高优先级任务的栈指针Load到SP中,并强制中断返回。这样就绪的最高优先级任务就如同从中断返回到运行状态一样,使整个系统得以运转。

    最近比较忙,我还是个实习生,就负责一个项目的开发,很多东西都要去协调,最近硬件出了问题,硬件部门非说我们软件部这边有问题,检查了半个月,最终将硬件打回去了,重新设计。更新的就比较慢了。

     

     

     

     

     

    展开全文
  • 任务控制块

    千次阅读 2017-02-26 22:24:55
    一旦任务建立了,任务控制块OS _TCBs将赋值(程序清单3.3)。任务控制块是一个数据结构,当任务的CPU使用权剥夺时,μC/OS-Ⅱ用它来保存该任务的状态。当任务重新得到CPU使用权时,任务控制块能确保任务从当时...

    一旦任务建立了,任务控制块OS_TCBs将被赋值(程序清单3.3)。任务控制块是一个数据结构,当任务的CPU使用权被剥夺时,μC/OS-Ⅱ用它来保存该任务的状态。当任务重新得到CPU使用权时,任务控制块能确保任务从当时被中断的那一点丝毫不差地继续执行。OS_TCBs全部驻留在RAM中。读者将会注意到笔者在组织这个数据结构时,考虑到了各成员的逻辑分组。任务建立的时候,OS_TCBs就被初始化了(见第四章 任务管理)。

     

    程序清单 L 3.3  µC/OS-II任务控制块.

    typedef struct os_tcb {

        OS_STK        *OSTCBStkPtr;

     

    #if OS_TASK_CREATE_EXT_EN

        void          *OSTCBExtPtr;

        OS_STK        *OSTCBStkBottom;

        INT32U         OSTCBStkSize;

        INT16U         OSTCBOpt;

        INT16U         OSTCBId;

    #endif

     

        struct os_tcb *OSTCBNext;

        struct os_tcb *OSTCBPrev;

     

    #if (OS_Q_EN && (OS_MAX_QS >= 2)) || OS_MBOX_EN || OS_SEM_EN

        OS_EVENT      *OSTCBEventPtr;

    #endif

     

    #if (OS_Q_EN && (OS_MAX_QS >= 2)) || OS_MBOX_EN

        void          *OSTCBMsg;

    #endif

        INT16U         OSTCBDly;

        INT8U          OSTCBStat;

        INT8U          OSTCBPrio;

     

        INT8U          OSTCBX;

        INT8U          OSTCBY;

        INT8U          OSTCBBitX;

        INT8U          OSTCBBitY;

     

    #if OS_TASK_DEL_EN

        BOOLEAN        OSTCBDelReq;

    #endif

    } OS_TCB;

     

    .OSTCBStkPtr是指向当前任务栈顶的指针μC/OS-Ⅱ允许每个任务有自己的栈,尤为重要的是,每个任务的栈的容量可以是任意的。有些商业内核要求所有任务栈的容量都一样,除非用户写一个复杂的接口函数来改变之。这种限制浪费了RAM,当各任务需要的栈空间不同时,也得按任务中预期栈容量需求最多的来分配栈空间。OSTCBStkPtr是OS_TCB数据结构中唯一的一个能用汇编语言来处置的变量(在任务切换段的代码Context-switching code之中,)把OSTCBStkPtr放在数据结构的最前面,使得从汇编语言中处理这个变量时较为容易。

    .OSTCBExtPtr 指向用户定义的任务控制块扩展。用户可以扩展任务控制块而不必修改μC/OS-Ⅱ的源代码。.OSTCBExtPtr只在函数OstaskCreateExt()中使用,故使用时要将OS_TASK_CREAT_EN设为1,以允许建立任务函数的扩展。例如用户可以建立一个数据结构,这个数据结构包含每个任务的名字,或跟踪某个任务的执行时间,或者跟踪切换到某个任务的次数(见例3)。注意,笔者将这个扩展指针变量放在紧跟着堆栈指针的位置,为的是当用户需要在汇编语言中处理这个变量时,从数据结构的头上算偏移量比较方便。

    .OSTCBStkBottom是指向任务栈底的指针。如果微处理器的栈指针是递减的,即栈存储器从高地址向低地址方向分配,则OSTCBStkBottom指向任务使用的栈空间的最低地址。类似地,如果微处理器的栈是从低地址向高地址递增型的,则OSTCBStkBottom指向任务可以使用的栈空间的最高地址。函数OSTaskStkChk()要用到变量OSTCBStkBottom,在运行中检验栈空间的使用情况。用户可以用它来确定任务实际需要的栈空间。这个功能只有当用户在任务建立时允许使用OSTaskCreateExt()函数时才能实现。这就要求用户将OS_TASK_CREATE_EXT_EN设为1,以便允许该功能。

    .OSTCBStkSize存有栈中可容纳的指针元数目而不是用字节(Byte)表示的栈容量总数。也就是说,如果栈中可以保存1,000个入口地址,每个地址宽度是32位的,则实际栈容量是4,000字节。同样是1,000个入口地址,如果每个地址宽度是16位的,则总栈容量只有2,000字节。在函数OSStakChk()中要调用OSTCBStkSize。同理,若使用该函数的话,要将OS_TASK_CREAT_EXT_EN设为1。

    .OSTCBOpt“选择项”传给OSTaskCreateExt(),只有在用户将OS_TASK_CREATE_EXT_EN设为1时,这个变量才有效。μC/OS-Ⅱ目前只支持3个选择项(见uCOS_II.H):OS_TASK_OTP_STK_CHK, OS_TASK_OPT_STK_CLR和OS_TASK_OPT_SAVE_FP。 OS_TASK_OTP_STK_CHK  用于告知TaskCreateExt(),在任务建立的时候任务栈检验功能得

    到了允许。OS_TASK_OPT_STK_CLR表示任务建立的时候任务栈要清零。只有在用户需要有栈检验功能时,才需要将栈清零。如果不定义OS_TASK_OPT_STK_CLR,而后又建立、删除了任务,栈检验功能报告的栈使用情况将是错误的。如果任务一旦建立就决不会被删除,而用户初始化时,已将RAM清过零,则OS_TASK_OPT_STK_CLR不需要再定义,这可以节约程序执行时间。传递了OS_TASK_OPT_STK_CLR将增加TaskCreateExt()函数的执行时间,因为要将栈空间清零。栈容量越大,清零花的时间越长。最后一个选择项OS_TASK_OPT_SAVE_FP通知TaskCreateExt(),任务要做浮点运算。如果微处理器有硬件的浮点协处理器,则所建立的任务在做任务调度切换时,浮点寄存器的内容要保存。

    .OSTCBId用于存储任务的识别码。这个变量现在没有使用,留给将来扩展用。

    .OSTCBNext.OSTCBPrev用于任务控制块OS_TCBs的双重链接,该链表在时钟节拍函数OSTimeTick()中使用,用于刷新各个任务的任务延迟变量.OSTCBDly,每个任务的任务控制块OS_TCB在任务建立的时候被链接到链表中,在任务删除的时候从链表中被删除。双重连接的链表使得任一成员都能被快速插入或删除。

    .OSTCBEventPtr是指向事件控制块的指针,后面的章节中会有所描述(见第6章 任务间通讯与同步)。

    .OSTCBMsg是指向传给任务的消息的指针。用法将在后面的章节中提到(见第6章任务间通讯与同步)。

    .OSTCBDly当需要把任务延时若干时钟节拍时要用到这个变量,或者需要把任务挂起一段时间以等待某事件的发生,这种等待是有超时限制的。在这种情况下,这个变量保存的是任务允许等待事件发生的最多时钟节拍数。如果这个变量为0,表示任务不延时,或者表示等待事件发生的时间没有限制。

    .OSTCBStat是任务的状态字.OSTCBStat为0,任务进入就绪态。可以给.OSTCBStat赋其它的值,在文件uCOS_II.H中有关于这个值的描述。

    .OSTCBPrio是任务优先级。高优先级任务的.OSTCBPrio值小。也就是说,这个值越小,任务的优先级越高。

    .OSTCBX, .OSTCBY, .OSTCBBitX和 .OSTCBBitY用于加速任务进入就绪态的过程或进入等待事件发生状态的过程(避免在运行中去计算这些值)。这些值是在任务建立时算好的,或者是在改变任务优先级时算出的。这些值的算法见程序清单L3.4。

     

    程序清单 L 3.4 任务控制块OS_TCB中几个成员的算法

    OSTCBY

    = priority >> 3;

    OSTCBBitY

    = OSMapTbl[priority >> 3];

    OSTCBX

    = priority & 0x07;

    OSTCBBitX

    = OSMapTbl[priority & 0x07];

     

     

    .OSTCBDelReq是一个布尔量,用于表示该任务是否需要删除,用法将在后面的章节中描述(见第4章 任务管理)

     

    应用程序中可以有的最多任务数(OS_MAX_TASKS)是在文件OS_CFG.H中定义的。这个最多任务数也是μC/OS-Ⅱ分配给用户程序的最多任务控制块OS_TCBs的数目。将OS_MAX_TASKS的数目设置为用户应用程序实际需要的任务数可以减小RAM的需求量。所有的任务控制块OS_TCBs都是放在任务控制块列表数组OSTCBTbl[]中的。请注意,μC/OS-Ⅱ分配给系统任务OS_N_SYS_TASKS若干个任务控制块,见文件μC/OS-Ⅱ.H,供其内部使用。

    目前,一个用于空闲任务,另一个用于任务统计如果OS_TASK_STAT_EN是设为1的)。在μC/OS-Ⅱ初始化的时候,如图3.2所示,所有任务控制块OS_TCBs被链接成单向空任务链表。当任务一旦建立,空任务控制块指针OSTCBFreeList指向的任务控制块便赋给了该任务,然后OSTCBFreeList的值调整为指向下链表中下一个空的任务控制块。一旦任务被删除,任务控制块就还给空任务链表。

     

                  3.2 空任务列表


    展开全文
  • ucosii任务三要素---执行代码 堆栈 任务控制块

    千次阅读 多人点赞 2018-02-27 21:07:49
    RTOS中一个任务的三要素:程序代码、堆栈、任务控制块。程序代码就是任务的执行函数。这没啥好说的每个任务都有自己的堆栈,来保存自身的信息。这是每个任务自己的资源。是每个人自己的一亩三分地。...
  • OSInit()调用来初始化空闲TCB(任务控制块)。这个初始化函数包含的信息是比较难的,也是系统比较重要的(后面会对TCB进行讲述)。 所谓任务控制块,就是控制任务相关变量数据信息各类的结构体的归类,其结构体里面...
  • 1、在多任务系统中,令CPU中止当前运行的任务转而去运行另一个任务的工作叫做任务切换,而按照某种规则进行任务切换...4、任务级的调度器由函数OSSched()实现,中断级的调度器由函数OSIntExt()实现 5、调度器做任
  • OSTaskStkInit():任务堆栈结构的初始化 OSTaskCreate()和OSTaskCreateExt()通过调用OSTaskStkInit(),初始化任务的栈结构。因此,堆栈看起来就像中断刚发生过一样,所有寄存器都保存在堆栈中。OSTaskStkInit()的...
  • UCOS-II任务堆栈初始化函数移植

    千次阅读 2013-08-03 18:41:53
    http://blog.sina.com.cn/s/blog_6d589a300100nc3n.html### (2010-10-20 16:34:40) 转载▼ ...UCOS-II的在建立任务函数中要对新建任务的堆栈进行初始化。堆栈初始化函数原型是: OS_STK *OSTaskStkInit (vo
  • 【UCOSIII】UCOSIII的初始化和启动

    千次阅读 2018-06-22 18:32:26
    在使用UCOSIII之前我们必须先初始化UCOSIII,函数OSInit()用来完成UCOSIII的初始化,而且OSInit()必须先于其他UCOSIII函数调用,包括OSStart()。 一般UCOSIII的main函数遵循以下的格式编写: int main(void) { ...
  • UC/OS基础知识之任务控制块

    千次阅读 2016-01-05 11:49:54
    用来记录任务的堆栈指针,任务的当前状态,任务的优先级别等一些与任务管理有关的属性的表就叫做任务控制块,没有任务控制块的任务不能系统承认和管理 任务控制块是一个结构类型数据,当调用OSTaskCreate()创建...
  • Ⅰ、写在前面 学习本文之前可以参看我前面的...上一篇文章讲述了关于OSInit函数体中几个关于系统内核重要的函数,本文将针对上一篇文章中OS_InitTCBList(初始化任务控制块函数重点讲述一下TCB(Task Control Bloc
  • ucos任务状态及任务控制块

    千次阅读 2017-01-09 14:30:48
    一个任务被创建后,可以处于以下五种状态之一 这五种状态分别是: 1.睡眠状态 2.就绪状态 3.等待状态 4中断服务状态 5执行状态 下面简单介绍各状态的含义即各状态的切换方法  睡眠状态:睡眠态指任务驻留在...
  • 为了满足任务切换和响应中断时保存CPU寄存器中的内容及任务调用其它函数时的需要,每个任务都应该有自己的堆栈。 如何创建? #define START_STK_SIZE 512 //堆栈大小 CPU_STK START_TASK_STK[STAR...
  • 初始化函数OSInit()的理解

    千次阅读 2015-10-21 19:09:52
    我们在学习uCOSII的时候每一个main()函数总有一个初始化函数OSInit(),说明初始化是非常重要的,那么初始化到底做了那些工作呢,说简单点就是把系统恢复到默认值,让我们来详细看一下代码: 要看代码首先要从...
  • ucos 任务控制块及任务链表

    千次阅读 2013-11-11 16:52:08
    1:任务控制块 首先看看ucos中任务控制块的数据结构为: typedef struct os_tcb {  OS_STK *OSTCBStkPtr; /* Pointer to current top of stack */ #if OS_TASK_CREATE_EXT_EN > 0  v
  • 系统任务4.1 显示任务4.1.1 display和write任务4.1.2 strobe监控4.1.3 连续监控4.2 文件I/O任务函数4.2.1 打开文件和关闭文件4.2.2 文件输出4.2.3 数据转换为字符串4.2.4 读取文件内容4.2.5 文件I/O错误状态4.2.6 ...
  • 可以这样理解,前面学习我们已经知道,创建一个任务需要给这个任务分配一个任务控制块,这个任务控制块存储着关于这个任务的重要信息。那么,事件控制块就好比任务里的任务控制块。它存储着这个事件的重要信息,我们...
  • 事件控制块ECB

    千次阅读 2017-03-21 09:21:05
    µC/OS-II通过uCOS_II.H 中定义的OS_EVENT数据结构来维护一个事件控制块的所有信息[程序清单L6.1],也就是本章开篇讲到的事件控制块ECB。该结构中除了包含了事件本身的定义,如用于信号量的计数器,用于指向邮箱的...
  • UCOSIII中的任务由三部分组成:任务堆栈、任务控制块和任务函数。 任务堆栈:上下文切换的时候用来保存任务的工作环境,就是STM32的内部寄存器值; 任务控制块任务控制块用来记录任务的各个属性; 任务函数:由...
  • 从零开始学习UCOSII操作系统6--事件控制块1、任务任务任务和中断子程序是如何进行通信的?--事件控制块事件控制块使用的几点须知:(1)任务或者中断服务子程序可以给事件控住块ECB发送信号。(2)中断服务子程序不...
  • uC/OS-III任务创建函数OSTaskCreate()

    千次阅读 2017-05-17 19:16:37
    1.OSTaskCreate()函数原型void TaskCreate(OS_TCB *p_tcb, // 任务控制OS_TCB的地址 CPU_CHAR *p_name, // 任务的名字 OS_TASK_PTR p_task, // 任务代码的起始地址 void *p_arg, // 任务第一次运行时接收到
  • 5、UCOSIII系统初始化和启动

    千次阅读 2018-08-04 09:25:47
    在使用UCOSIII之前我们必须先初始化UCOSIII,即函数OSInit()就是用来完成UCOSIII的初始化,而且OSInit()必须先于其他UCOSIII函数调用,包括OSStart()。 int main(void) { OS_ERR err; CPU_SR_ALLOC(); /*外设...
  • 串口通信初始化

    千次阅读 2019-10-29 10:37:18
    串口初始化工作需要做以下工作: 设置波特率 设置数据流控制 设置帧的格式(即数据位个数,停止位,校验位) 串口初始化 代码: [cpp] view plain copy int set_opt(int fd,int nSpeed,...
  • uCOS-II系统中的任务

    千次阅读 2017-08-28 00:01:35
    uCOS-II系统内核的主要工作是对任务的管理和调度。在进行接下来的源码分析前,先来把任务这东西理一理。1. 任务的引入  在公司的大型的软件研发项目中,通常项目经理会将该项目分解成多个功能模块,项目组内程序员...
  • 又到了来废话的时候了,今天这一节,我们把第三章结束,所讲述的内容如标题所示,废话不多讲,切...所有uCOS-II任务的任务控制块都有一个指向该任务堆栈的指针。 任务堆栈的创建: 为了方便定义堆栈,在系统文件...
  • FreeRTOS任务API函数的使用

    千次阅读 2017-08-27 18:01:41
    FreeRTOS 任务函数API
  • 3、uc/os:任务控制块OS_TCB

    千次阅读 2015-07-04 21:12:53
    操作系统的调度都围绕这一个数据结构体OS_TCB,我们叫它任务控制块任务控制块贯穿了整个uCOS2操作系统,如果不了解这个结构体在操作系统当中的用法,那就不可能对uCOS2深入的理解。 在Ucos_ii.

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 109,310
精华内容 43,724
关键字:

任务控制块被哪个函数初始化