uC/OS-II的任务

uC/OS-II的任务

      在小型应用中,通常一个嵌入式系统中的所有程序模块同属于一个统一的任务——对宿主对象进行控制。因此,通常认为在嵌入式系统中只有一个进程,而把这个进程进行分解之后的那些小程序模块,由于他们没有自己的内存空间,所以他们实质上就是所谓的线程。在uC/OS-II中,习惯把这样的线程叫做任务,或者叫做实时任务。

      实时系统中的任务的执行大多数都是由外部事件触发的。也就是说,实时操作系统的主要工作就是响应并处理各种外部事件

uC/OS-II任务的存储结构

      从应用程序设计的角度来看,uC/OS-II的任务就是一个线程,是一个用来解决用户问题的C函数和与之相关联的一些数据结构而构成的一个实体。

      从任务的存储结构来看,任务有3个组成部分:任务程序代码,任务堆栈和任务控制块。其中,任务控制块用来保存任务属性;任务堆栈用来保存任务工作环境;任务程序代码是任务的执行部分。

uC/OS-II任务的优先级别

      uC/OS-II把任务的优先权分为64个优先级别,每个级别都用一个数字来表示。数字0表示任务的优先级别最高,数字越大则表示任务的优先级别越低。

      uC/OS-II规定,一个应用程序的任务数最多可以有64个。但在实际应用中,为了节省内存,用户可根据需要,在配置文件OS_CFG.H中通过对常数OS_LOWEST_PRIO赋值的方法来说明应用程序中任务优先级别的数目。通常,常数OS_LOWEST_PRIO还有另外一个意义,它还用来表示系统中任务的最低级别。该常数一旦被定义,就意味着系统可供使用的优先级别一共有OS_LOWEST_PRIO+1个,它们分别是:012,……OS_LOWEST_PRIO

任务控制块

      uC/OS-II用来记录任务的堆栈指针,任务的当前状态,任务的优先级别等一些与任务管理有关的表就叫做任务控制块。即进程控制块

      为了管理系统中的多个任务,uC/OS-II把系统所有任务的控制块链接为两条链表。

      uC/OS-II中,当用户应用程序调用系统函数OSTaskCreate()创建一个用户任务时,这个函数会把该任务的所有相关数据赋予任务控制块中的对应成员,并驻留在RAM中。

      任务控制块结构的定义为如下:(在uC/OS-II.H中定义)

typedef struct os_tcb {

    OS_STK        *OSTCBStkPtr;        /* Pointer to current top of stack                              */

 

#if OS_TASK_CREATE_EXT_EN   

    void          *OSTCBExtPtr;        /* Pointer to user definable data for TCB extension             */

    OS_STK        *OSTCBStkBottom;     /* Pointer to bottom of stack                                   */

    INT32U         OSTCBStkSize;       /* Size of task stack (in bytes)                                */

    INT16U         OSTCBOpt;           /* Task options as passed by OSTaskCreateExt()                  */

    INT16U         OSTCBId;            /* Task ID (0..65535)                                           */

#endif

 

    struct os_tcb *OSTCBNext;          /* Pointer to next     TCB in the TCB list                      */

    struct os_tcb *OSTCBPrev;          /* Pointer to previous TCB in the TCB list                      */

 

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

    OS_EVENT      *OSTCBEventPtr;      /* Pointer to event control block                               */

#endif

 

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

    void          *OSTCBMsg;           /* Message received from OSMboxPost() or OSQPost()              */

#endif   

 

    INT16U         OSTCBDly;           /* Nbr ticks to delay task or, timeout waiting for event        */

    INT8U          OSTCBStat;          /* Task status                                                  */

    INT8U          OSTCBPrio;          /* Task priority (0 == highest, 63 == lowest)                   */

 

    INT8U          OSTCBX;             /* Bit position in group  corresponding to task priority (0..7) */

    INT8U          OSTCBY;             /* Index into ready table corresponding to task priority        */

    INT8U          OSTCBBitX;          /* Bit mask to access bit position in ready table               */

    INT8U          OSTCBBitY;          /* Bit mask to access bit position in ready group               */

   

#if OS_TASK_DEL_EN   

    BOOLEAN        OSTCBDelReq;        /* Indicates whether a task needs to delete itself              */

#endif

} OS_TCB;

 

OSTCBStat用来存放任务的当前状态:

                                       /* TASK STATUS (Bit definition for OSTCBStat)                   */

#define  OS_STAT_RDY            0x00   /* Ready to run                                                 */

#define  OS_STAT_SEM            0x01   /* Pending on semaphore                                         */

#define  OS_STAT_MBOX           0x02   /* Pending on mailbox                                           */

#define  OS_STAT_Q              0x04   /* Pending on queue                                             */

#define  OS_STAT_SUSPEND        0x08   /* Task is suspended                                            */

 

任务控制块链表(学习实时性的链表处理方法)

      uC/OS-II两条链表管理任务控制块:一条是空任务控制块链表(其中所有任务控制块还没有分配给任务);另一条是任务控制块链表(其中所有任务控制块已经分配给任务了)。

      众所周知,在这种链表例查找一个元素有时是很费时的,而且查找时间还与目标元素在链表中的位置有关,有某种不确定性,这两种情况都是实时系统所忌讳的。所以,为了加快对任务控制块的访问速度,除了任务控制块链表被创建为双向链表之外,uC/OS-IIuC/OS-II.H中还定义了一个数据类型为0S_TCB* DE 数组OSTCBTbl[],专门用来存放指向各任务控制块的指针,并按任务的优先级别把这些指针存放数组的各元素里。这样,在访问某个任务的任务控制块时,就可以按照任务的优先级别直接从数组OSTCBTbl[]的对应元素中获得该任务控制块的指针,并通过它直接找到该任务控制块了

 

任务堆栈

      在文件OS_CUP.H中专门定义了一个数据类型OS_STK:

typedef unsigned int   OS_STK;                   /* Each stack entry is 16-bit wide                    */

在应用程序中定义一个OS_STK类型的一个数组即可。

#define  TASK_STK_SIZE                 512       /* Size of each task's stacks (# of WORDs)            */

#define  N_TASKS                        10       /* Number of identical tasks                          */

OS_STK           TaskStk[N_TASKS][TASK_STK_SIZE];     /* Tasks stacks                                  */

OS_STK           TaskStartStk[TASK_STK_SIZE];

 

需要注意的是,堆栈的增长方向是随系统使用的处理器的不同而不同的,利用OS_CFG.H文件中的常数OS_STK_GROWTH作为选择开关,选择不同的增长方向。

 

任务堆栈的初始化

      应用程序在创建一个新任务时,就必须把在系统启动这个任务时处理器个寄存器所需的初始化数据(任务指针,任务堆栈指针程序状态字等)事先存放在这个任务的堆栈中。这个工作是在创建任务函数OSTaskCreate()中通过调用任务堆栈初始化函数OSTaskStkInit()来完成的。

      void *OSTaskStkInit (void (*task)(void *pd), void *pdata, void *ptos, INT16U opt)

      该函数需要用户在进行uC/OS-II的移植时按所使用的处理器由用户来编写。

 

系统任务

      uC/OS-II预定义了两个为应用程序服务的系统任务:空闲任务(OSTaskIdle())和统计任务(OSTaskStat())

 

临界区

      uC/OS-II中的临界区,值得就是一个特殊代码段。如果在程序中有一段代码在执行期间不允许中断,那么它就是具有原子性的代码段。这种代码段在uC/OS-II中叫做临界区。

      uC/OS-II用宏OS_ENTER_CRITICAL()关闭中断,而用OS_EXIT_CRITICAL()打开中断。(在OS_CPU.H中)

OS_ENTER_CRITICAL()

……//临界区

OS_EXIT_CRITICAL()

你可能感兴趣的:(uC/OS-II的任务)