μC/OS-Ⅱ中的任务

μC/OS-Ⅱ中的任务

 μC/OS-Ⅱ操作系统内核的主要工作就是对任务的调度和管理


1 任务的基本概念

任务及其内存结构

将大任务分解为多个小任务,可以使系统并发地运行多个任务,提高处理器的利用率,加快程序的执行速度,现代操作系统大多是多任务操作系统

μC/OS-Ⅱ中,小任务对应的程序实体为“任务”,μC/OS-Ⅱ是能对小任务进行管理和调度的多任务操作系统

从代码上来看,μC/OS-Ⅱ的任务是一个函数

从存储结构上看,μC/OS-Ⅱ由三部分组成:

任务程序代码(函数): 任务的执行部分

任务堆栈:保存任务的工作变量

任务控制块:记录任务的各个操作

 

进程:具有私有空间的任务

线程:没有私有空间的任务

μC/OS-Ⅱ中的任务属于线程

 

μC/OS-Ⅱ中的任务(最多64):用户任务和系统任务

 用户任务:由应用程序设计者编写

 系统任务:由系统提供

 

2 任务的状态

μC/OS-Ⅱ任务的5钟状态:睡眠、就绪、运行、等待和中断服务

睡眠:以代码的形式留在ROMRAM中,没有被配置任务控制块或被剥夺了任务控制块。

就绪:配备了任务控制块并在任务就绪表中就绪登记,具备运行的充分条件。

运行:处于就绪状态,经调制器判断获得了CPU的使用权。

等待:正在运行的任务,等待一段时间或等待一个事件发生后再运行。

中断服务:正在运行的任务响应中断申请中止去执行中断服务程序。

 

3 用户任务代码的一般结构

 用户应用程序的一般结构

用户任务不是由主函数调用的函数,在系统中它与主函数处于平等地位,主函数负责创建任务并将它们交给系统,由系统决定何时被运行和被中止。

OS_TASKCreate()是创建任务的函数,OSStart()是启动μC/OS-Ⅱ的函数。


4 系统任务

系统任务:空闲任务和统计任务

空闲任务(每个应用程序必须使用):

统计任务(根据要求选择使用):

每秒计算一次CPU在单位时间内被使用的时间,计算结果以百分比的形式存放在变量OSCPUsage中。

若要使用统计任务,须在系统头文件OS_CFG中的系统配置常数OS_TASK_STAT_EN置为1,在程序中要调用函数OSStartInit()进行初始化。

 

5 任务的优先权及优先级别

系统总是把最低优先级别OS_LOWEST_PRIO自动赋值给空闲任务。

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


6 任务堆栈

堆栈:在存储器中按数据“后进先出(LIFO)”的原则组织的连续存储空间,每个任务都有自己的堆栈,在任务控制块中都有一个指向任务堆栈的指针。

1 任务堆栈的创建

typedef unsigned int OS_STK;

#define TASK_STK_SIZE 512

OS_STK TaskStk[TASK_STK_SIZE];

OSTaskcreate(void (

 *task)(void *pd), //指向任务的指针

void *pdata, //传递给任务的参数

OS_STK *ptos,//任务堆栈栈顶指针

INTBU prio//指定任务优先级的参数

);
堆栈的增长方向是由系统所使用的处理器决定的。

头文件OS_CFG.H中的OS_STK_GROWTH作为选择开关

#if OS_STK_GROWTH == 1//向下增长

    OSTaskcreate(MyTask, &MyTaskAgu, &MyTaskStk[MyTaskStkN - 1], 20);

#else//向上增长

    OSTaskcreate(MyTask, &MyTaskAgu, &MyTaskStk[0], 20);

#endif

2 任务堆栈的初始化à将任务初始数据存放到任务堆栈

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

该函数由OSTaskcreate()函数来调用。

7  任务控制块及其链表

μC/OS-Ⅱ把系统所有任务的额控制块链接为两条链表

任务控制块链表

一条空任务链表,一条任务块链表。

空任务块链表:系统调用OSInit()μC/OS-Ⅱ进行初始化时,在RAM中建立一个OS_TCB结构的数组OSTCBTbl[]各个元素链接成一个链表。

空任务链表的元素数目:

  OS_CFG.HOS_MAX_TASKS用户任务的最大数目

  UCOSII.HOS_N_SYS_TASKS系统任务的数目(空闲任务+统计任务(1 or 2))

 

任务控制块链表创建为双向链表,可加快任务控制块的访问速度。

当前任务控制块:正在占有CPU且处于运行状态的任务所属的控制块,是μC/OS-Ⅱ访问频度最高的控制块。

任务控制块的初始化

INTBU OSTCBInit(INTBU prio, OS_STK *ptos, OS_STK *pbos, INT16U id, INT16U stk_size, void *pext, INT16U opt);

Ø 为被创建任务从空任务控制块链表获取一个任务控制块

Ø 用任务的属性对任务控制块各个成员进行赋值

Ø 把这个任务控制块链入到任务控制块链表


8 任务就绪表及任务调度

为系统中处于就绪状态的任务分配CPU是多任务操作系统的核心工作。

判断哪些任务处于就绪状态;进行任务调度。

 

 对任务就绪表的操作

登记、注销和从就绪表的就绪任务中得知具有最高优先级任务的标识。

1. 登记

当某个任务处于就绪状态时,系统将该任务登记在就绪表中,在就绪表对应位置置1.

OSRdyGrp |= OSMapTbl[prio >> 3];

OSRdyTbl[prio >> 3] |= OSMapTbl[prio & 0x07];

 

利用该数组可以加快运算速度。

2. 注销

当某个任务脱离就绪任务时,系统在就绪表中将该任务对应位置置0.

if((OSRdyTbl[prio >> 3] & -OSMapTbl[prio & 0x07]) == 0)

    OSRdyGrp &= -OSMapTbl[prio >> 3];

3. 最高优先级就绪任务的查找

y = OSUnMapTal[OSRdyGrp];//获取优先级别的D5D4D3位

x = OSUnMapTal[OSRdyTbl[y]];//获取优先级别的D2D1D0位

prio = (y << 3) + x;//获取就绪任务的优先级别

y = OSUnMapTbl[OSRdyGrp];

prio = (INTBU) ((y << 3) + OSUnMapTbl[OSRdyTbl[y]]);

 

4. 任务调度à每时每刻让优先级最高的就绪任务处于运行状态

任务切换:令CPU中止当前正在运行的任务转而去运行另一个任务

任务的调度:按某种规则进行任务切换

1. 调度器的主要共作

任务调度器:在就绪表中查找优先级别最高的就绪任务;

实现任务的切换:获取待运行任务的TCB指针、进行断点数据切换

任务级调度器:OSSched()

中断级调度器:OSIntExt()

2. 获得待运行就绪任务控制块的指针

操作系统通过任务控制块TCB来管理任务,被中止任务的任务控制块指针存放在全局变量OSTCBCur中,所以调度器主要获取待运行就绪任务控制块的指针。

通过OSSchedLock()OSSchedUnlock()函数给调度器上锁和解锁,上锁一次,变量OSLockNexting1;解锁一次,变量OSLockNexting1

3. 任务切换宏OS_TASK_SW()

断点:任务被中止运行时的位置

断点数据:当时存放在CPUPCPSW和通用寄存器等各寄存器中的数据

一个被中止的任务能否正确地在断点处恢复运行,关键在于能否正确地在CPU各寄存器中恢复断点数据;能否正确恢复断点数据的关键在于CPU的堆栈指针SP是否有正确的指向。

任务的切换就是断点数据的切换,断点数据的切换也就是CPU堆栈指针的切换。

 

OSCtxSW()的工作:

Ø 断点指针保存到任务堆栈

Ø CPU通用寄存器的内容保存到任务堆栈

Ø 被中止任务的任务堆栈指针当前值保存到该任务的任务控制块的OSTCBStkPtr

Ø 获得待运行任务的任务控制块

Ø CPU获得待运行任务的任务堆栈指针

Ø 将待运行任务堆栈中通用寄存器的内容恢复到CPU通用寄存器中

Ø 使CPU获得待运行任务的断点指针

对于被中止任务:把任务的断点指针压入任务堆栈

对于待运行任务:把任务堆栈里上次任务被中止时存放在堆栈中的中断指针推入PC寄存器。

通过改变PC值的指令实现出栈和入栈。


9 任务的创建

1 用函数OSTaskCreate()创建任务


2 用函数OSTaskcreateExt()创建任务

    

3 创建任务的一般方法

在调用OSStart()之前,必须已经创建了至少一个任务,不允许在中断服务程序中创建任务。

PC功能函数提供了三类服务:字符显示、运行时间测量和其他服务


10. 任务的挂起和恢复

 

1 挂起任务

挂起任务à停止这个任务的运行

OSTaskSuspend()挂起ßàOSTaskResume()恢复

挂起任务:

INTBU OSTaskSuspend(INTBU prio);

挂起自身时,参数为OS_PRIO_SELF

 

 

2 恢复任务

恢复任务

INTBU OSTaskResume(INTBU prio);

 

 

11.其他任务管理函数

1 任务优先级别的修改

可通过函数OSTaskChangePrio()来改变任务的优先级别

 

2 任务的删除à将任务置于睡眠状态

#if OS_TASK_DEL_EN

INTBU OSTaskDel(INTBU prio);

删除自身时,参数为OS_PRIO_SELF

μC/OS-Ⅱ利用被删除任务的任务控制块成员OSTCBDelReq作为请求删除方的被删除方的联络信号,同时提供了一个函数OSTaskDelReq()双方都能访问OSTCBDelReq信号,从而根据信号的状态决定各自的行为。

INTBU OSTaskDelReq(INTBU prio);

被删除任务调用这个函数时,参数为OS_PRIO_SELF

 

3 查询任务的信息

    OSTaskQuery(INTBU prio, OS_TCB *pdata);

12 μC/OS-Ⅱ的初始化和任务的启动

1 μC/OS-Ⅱ的初始化

使用OSInit()初始化μC/OS-Ⅱ自身的运行环境,将对所有全局变量数据结构进行初始化,并创建空闲任务OSTaskIdle,并赋之以最低的优先级别和永远的就绪状态。

主要是创建包括空任务控制块链表在内的5个空数据缓冲区,还要创建一个数组OSTCBPrioTbl[OS_LOWEST_PRIO + 1]按任务的优先级别的顺序把任务控制块的指针存放在对应的元素中

2 μC/OS-Ⅱ的启动

    μC/OS-Ⅱ进行任务的管理从调用启动函数OSStart()开始,调用函数前至少创建了一个用户任务


小结

n 任务由任务控制块、任务堆栈和任务代码三部分组成。

Ø 任务控制块:感知和控制任务

Ø 任务堆栈:保护和恢复断点

Ø 任务代码:超循环结构,描述任务的执行过程

创建任务时,OSTaskcreate()OSTaskcreateExt()用来给任务分配任务控制块和任务堆栈。

n 系统是按任务就绪表和任务的优先级别来调度任务的。

n 任务切换的核心工作是任务堆栈指针的切换

n 任务的优先级别也是任务的标识

应用程序首先调用OSInit()函数对全局变量和数据结构进行初始化,以及建立μC/OS-Ⅱ的运行环境。

应用程序通过调用OSSart() 函数进入多任务管理,在调用之前至少创建一个任务。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值