全部博文(245)
分类: C/C++
2009-09-16 15:05:33
uc/os的任务管理
uc/os每个任务被赋予不同的优先级等级,从0级到最低优先级OS_LOWEST_PRIO,包括0和OS_LOWEST_PRIO在内, uc/os总是在已经就绪的任务中选择一个任务来运行,为了了解那些任务出于就绪状态,uc/os在系统初始化的时候创建了一个供就绪任务登记的表,即就绪任务表。就绪任务表实际上为一个类型为INT8U的数组OSRdyTbl[],由 于每个任务在此数组中只占一位,所以数组的每一个元素可以表达8个任务的就绪状态。为了便于对就绪表的查找,uc/os又定义了一个数组类型为INT8的 OSRdyGrp,并使该数组的每一位都对应OSRdyTbl[]的一个任务组。在OSRdyGrp中,任务按优先级分组,8个任务为一组。OSRdyGrp中的每一位表示8组任务中每一组中是否有进入就绪态的任务。例如OSRdyGrp=1100101,哪么意味着OSRdyTbl[0],OSRdyTbl[2],OSRdyTbl[6],OSRdyTbl[7]任务组中有任务就绪。
由于优先级是一个单字节的数字,且其最大值不超过63,因此可以把优先级看做是一个6位的二进制数,这样子可以用高三位表示OSRdyGrp的具体数据位,用低三位表示数组元素OSRdyTcl的具体数据位。
对于任务就绪表的操作主要有两项:添加,删除。
在任务就绪表中登记就绪任务的代码为:
OSRdyGrp |= OSMapTbl[prio >> 3];
OSRdyTbl[prio >> 3] |= OSMapTbl[prio & 0x07];
从任务就绪表中删除任务的代码为:
if ((OSRdyTbl[prio >> 3] &= ~OSMapTbl[prio & 0x07]) == 0)
OSRdyGrp &= ~OSMapTbl[prio >> 3];
表 T3.1 OSMapTbl[]的值 |
|
Index |
Bit Mask (Binary) |
0 |
00000001 |
1 |
00000010 |
2 |
00000100 |
3 |
00001000 |
4 |
00010000 |
5 |
00100000 |
6 |
01000000 |
7 |
10000000 |
从就绪表中获得任务优先级最高的任务的方法为:
y = OSUnMapTbl[OSRdyGrp];
x = OSUnMapTbl[OSRdyTbl[y]];
prio = (y << 3) + x;
具 体使用时需要查找一个16*16的OSUnMapTbl[]数组,OSUnMapTbl的设计思想为:表示人物的OSRdyGrp为一个8位的二进制数, 从这个数的最低位到最高位查找,碰到第一个为1的位所对应的任务就绪组一定是最高优先级任务所在的组,所以它的组号一定是优先级最高的就绪任务的级别。
2.任务的创建:
1. OSTaskCreate()
建立一个新任务。任务的建立可以在多任务环境启动之前,也可以在正在运行的任务中建立。中断处理程序中不能建立任务。一个任务可以为无限循环的结构。
函数原型:INT8U OSTaskCreate(void (*task)(void *pd), void *pdata, OS_STK *ptos, INT8U prio);
参数说明:task 是指向任务代码首地址的指针。
pdata 指向一个数据结构,该结构用来在建立任务时向任务传递参数。
ptos 指向堆栈顶端的指针
Prio 任务的优先级
返回值:
OSTaskCreate() 的返回值为下述之一:
* OS_NO_ERR:函数调用成功。
* OS_PRIO_EXIST:具有该优先级的任务已经存在。
* OS_PRIO_INVALID:参数指定的优先级大于OS_LOWEST_PRIO。
* OS_NO_MORE_TCB:系统中没有OS_TCB可以分配给任务了。
2. OSTaskSuspend()
无条件挂起一个任务。调用此函数的任务也可以传递参数 OS_PRIO_SELF,挂起调用任务本身。当前任务挂起后,只有其他任务才能唤醒被挂起的任务。任务挂起后,系统会重新进行任务调度,运行下一个优先级最高的就绪任务。唤醒挂起任务需要调用函数OSTaskResume()。
任务的挂起是可以叠加到其他操作上的。例如,任务被挂起时正在进行延时操作,那么任务的唤醒就需要两个条件:延时的结束以及其他任务的唤醒操作。又如,任务被挂起时正在等待信号量,当任务从信号量的等待对列中清除后也不能立即运行,而必须等到被唤醒后。
函数原型:INT8U OSTaskSuspend(INT8U prio);
参数说明:prio为指定要获取挂起的任务优先级,也可以指定参数 OS_PRIO_SELF,挂起任务本身。此时,下一个优先级最高的就绪任务将运行。
返回值:
OSTaskSuspend() 的返回值为下述之一:
* OS_NO_ERR:函数调用成功。
* OS_TASK_SUSPEND_IDLE:试图挂起μC/OS-II中的空闲任务(Idle task)。
* OS_PRIO_INVALID:参数指定的优先级大于 OS_LOWEST_PRIO 或没有设定 OS_PRIO_SELF 的值。
* OS_TASK_SUSPEND_PRIO:要挂起的任务不存在。
3. OSTaskResume()
唤醒一个用 OSTaskSuspend() 函数挂起的任务。OSTaskResume() 也是唯一能“解挂”挂起任务的函数。
函数原型:INT8U OSTaskResume(INT8U prio);
参数说明:prio指定要唤醒任务的优先级。
返回值:
OSTaskResume() 的返回值为下述之一:
* OS_NO_ERR:函数调用成功。
* OS_TASK_RESUME_PRIO:要唤醒的任务不存在。
* OS_TASK_NOT_SUSPENDED:要唤醒的任务不在挂起状态。
* OS_PRIO_INVALID:参数指定的优先级大于或等于OS_LOWEST_PRIO。
4.任务的优先级修改:
INT8U OSTaskChangePrio(INT8 oldprio,INT8 newprio);
5.任务查询:
INT8U OSTaskQuery(INT8U prio,OS_TCB *pdata);