uCOSII中的任务

任务和任务控制块:

在处理大而复杂的问题时,一个惯用而有效的方法就是“分而治之”,把一个大问题分解成多个相对简单、比较容易解决的小问题,小问题逐个解决了,大任务也就随之解决了。在uCOSII中,与上述小问题对应的程序实体就叫做“任务”。从代码上来看,uCOSII的任务就是一个C函数。作为任务,必须要接受操作系统的管理,即有一个控制块,这就是所谓的任务控制块。
任务控制块不仅与程序控制块有区别,而且区别还很大。因为任务是一个独立运行单位,在uCOSII中类似普通平台上的main函数,需要自己来保护其因调用或中断而产生的断点,所以它有一个私有的堆栈——任务堆栈。
uCOSII最多含有64个任务(包括用户任务和系统任务),用户任务:应用程序设计这编写的用于实现业务逻辑的任务。系统任务:由系统提供并为系统管理服务的任务叫做系统任务。
为了对系统中的多个任务进行管理,必须将任务的任务控制块登记造表,uCOSII用链表把系统中的所有任务控制块链接了起来,这个链表也叫做任务登记表。

TCB
{
    前一个任务控制块指针
    后一个任务控制块指针
    指向任务的指针
    指向任务堆栈的指针
    任务的优先级别
    .
    .
    .
}

uCOSII中的任务属于线程。(进程:具有独立内存运行空间的程序。线程:多个程序实体共用一个内存空间,单个实体就是线程。)

uCOSII的任务拥有5中状态:
睡眠状态: 任务只是以代码的形式驻留在程序空间,没有任务控制块或被系统剥夺了任务控制块。
就绪状态: 系统为任务配备了任务控制块且在任务就绪表中进行了就绪登记表。
运行状态: 处于就绪态的任务经过调度器判断取得了CPU的使用权。任何时刻只有一个任务处于运行状态,就绪的任务只有当所有优先级高于本任务的任务都转为等待状态时,才能进入运行态。
等待状态: 运行态任务,需要等待一段时间或者等待一个事件发生在运行时,该任务把CPU使用权交给其他任务,并进入等待态。
中断服务态: 运行态的任务被中断打断。

用户应用程序的一般结构:
main负责任务创建后交给系统,任务只被系统的调度器所调用。
例:

void MyTask1(void * pdata)
{
for(;;)
{
……
}
}
void MyTask2(void * pdata)
{
for(;;)
{
……
}
}
void main()
{
……
OSInit();
……
OSTaskCreate(MyTask1,……);
OSTaskCreate(MyTask1,……);
……
OSStart();
……
}

系统任务:uCOSII预定义了两个系统任务:空闲任务和统计任务。
空闲任务是每个应用程序都必须使用的,而统计任务则是应用程序根据实际选用的。

1.空闲任务
void OSTaskIdle(void * pdata)
{
#if OS_CRITICAL_METHOD==3
    OS_CPU_SR cpu_sr
#endif
    pdata=pdata
    for(;;)
    {
        OS_ENTER_CRITICAL();
        OSdleCtr++
        OS_EXIT_CRITICAL();
    }
}

uCOSII规定,一个用户应用程序必须使用这个空闲任务,而且这个任务不能通过程序来删除。

而且如果在这个空闲任务中实现了一个用户可以输入命令并且系统可以按照命令执行相应操作的界面,那么这个uCOSII就有点类似一个通用操作系统的样子了。

2.统计任务OSTaskStat()

这个任务每秒计算CPU在单位时间内被使用的时间,并且计算结果以百分比的形式存放在变量OSCPUsage中以便其他程序来了解CPU的利用率。
如果使用统计任务,则必须把定义在系统头文件OS_CFG.H中的系统配置常数OS_TASK_STAT_EN设置为1,并且在程序中要调用函数OSStatInit()对统计任务进行初始化。

任务的优先权及优先级别

由于最多可以在uCOSII中创建64个任务,所以任务的优先级别最多有64级,每个级别都有一个整数表示0-63,数字越小优先级越高。

大多数应用程序的任务数小于64,所以为了使用户可以设置所需要的任务的实际数目,uCOSII在系统配置文件OS_CFG.H中定义了一个用来表示最低优先级别的常数OS_LOWEST_PRIO,如果用户为其赋值,那么就意味着系统中可供使用的优先级别为0-OS_LOWEST_PRIO,对应了OS_LOWEST_PRIO+1个优先级别。
并且为了方便,系统总把最低优先级别OS_LOWEST_PRIO自动赋给空闲任务,如果使用了统计任务,系统还会自动把OS_LOWEST_PRIO-1赋给统计任务。因此用户任务的优先级别为0-OS_LOWEST_PRIO-2共OS_LOWEST_PRIO-1个,任务优先级别需要用户创建任务时显式的定义。

每个任务具有唯一优先级。优先级也是任务在系统中的标识。

任务堆栈:为了方便定义任务堆栈,在文件OS_CPU.H中专门定义了一个数据类型OS_STK;

typedef unsigned intOS_STK;

这样定义一个任务堆栈的堆栈区是,只要定义一个OS_STK的数组即可

#define TASK_STK_SIZE512
OS_STK TaskStk[TASK_STK_SIZE]

当调用任务创建函数OSTaskCreate( )来创建一个任务时,把数组的指针传递给函数OSTaskCreate()中的堆栈栈顶参数ptos,就可以把该数组与任务关联起来而成为该任务的任务堆栈。

INT8U OSTaskCreate( ){
    void (* task)(void  * pd); //指向任务的指针
    void                  *pdata; //传递给任务的参数
    OS_STK                *ptos;  //任务堆栈的栈顶指针
    INT8U                  prio   //指定任务优先级别的参数
}

注意:堆栈的增长方向跟处理器有关,有些向上有些向下。在创建任务时,如果堆栈增长向上则栈顶为高地址,向下则为低地址。

为了提高程序可移植性,可把两种代码都写出来,利用OS_CFG.H中的常数OS_STK_GROWTH作为选择开关,使用户可通过定义该常数的值来选择相应的代码段,以适应不同的堆栈增长方式。

任务堆栈的初始化:CPU启动一个任务时,CPU的各寄存器总要预先装入一些数据,例如指向任务的指针、程序状态字等。它们都是任务的私有数据,所有都保存在任务堆栈中。把任务初始数据存放到任务堆栈的工作就叫做任务堆栈的初始化。

uCOSII提供了任务堆栈初始化函数:OSTaskStkInit();

OS_STK *OSTaskStkInit(
        void(* task)(void * pd),
        void                * pdato,
        OS_STK              * ptos,
        INT16U                opt
);

这个函数由任务创建函数调用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值