μC/OS-II的内核结构
图3.1任务的状态
本文引用地址:https://www.eepw.com.cn/article/201610/305744.htm正在运行的任务可以通过调用两个函数之一将自身延迟一段时间,这两个函数是OSTimeDly()或OSTimeDlyHMSM()。这个任务于是进入等待状态,等待这段时间过去,下一个优先级最高的、并进入了就绪态的任务立刻被赋予了CPU的控制权。等待的时间过去以后,系统服务函数OSTimeTick()使延迟了的任务进入就绪态(见3.10节,时钟节拍)。
正在运行的任务期待某一事件的发生时也要等待,手段是调用以下3个函数之一:
OSSemPend(),OSMboxPend(),或OSQPend()。调用后任务进入了等待状态(WAITING)。当任务因等待事件被挂起(Pend),下一个优先级最高的任务立即得到了CPU的控制权。当事件发生了,被挂起的任务进入就绪态。事件发生的报告可能来自另一个任务,也可能来自中断服务子程序。
正在运行的任务是可以被中断的,除非该任务将中断关了,或者μC/OS-Ⅱ将中断关了。被中断了的任务就进入了中断服务态(ISR)。响应中断时,正在执行的任务被挂起,中断服务子程序控制了CPU的使用权。中断服务子程序可能会报告一个或多个事件的发生,而使一个或多个任务进入就绪态。在这种情况下,从中断服务子程序返回之前,μC/OS-Ⅱ要判定,被中断的任务是否还是就绪态任务中优先级最高的。如果中断服务子程序使一个优先级更高的任务进入了就绪态,则新进入就绪态的这个优先级更高的任务将得以运行,否则原来被中断了的任务才能继续运行。当所有的任务都在等待事件发生或等待延迟时间结束,μC/OS-Ⅱ执行空闲任务(idletask),执行OSTaskIdle()函数。
3.3 任务控制块(TaskControlBlocks,OS _TCBs)
一旦任务建立了,任务控制块OS _TCBs将被赋值(程序清单3.3)。任务控制块是一个数据结构,当任务的CPU使用权被剥夺时,μC/OS-Ⅱ用它来保存该任务的状态。当任务重新得到CPU使用权时,任务控制块能确保任务从当时被中断的那一点丝毫不差地继续执行。OS _TCBs全部驻留在RAM中。读者将会注意到笔者在组织这个数据结构时,考虑到了各成员的逻辑分组。任务建立的时候,OS _TCBs就被初始化了(见第四章任务管理)。
程序清单 L3.3μC/OS-II任务控制块.
typedefstructos_tcb{
OS_STK*OSTCBStkPtr;
#ifOS_TASK_CREATE_EXT_EN
void*OSTCBExtPtr;
OS_STK*OSTCBStkBottom;
INT32UOSTCBStkSize;
INT16UOSTCBOpt;
INT16UOSTCBId;
#endif
structos_tcb*OSTCBNext;
structos_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
INT16UOSTCBDly;
INT8UOSTCBStat;
INT8UOSTCBPrio;
INT8UOSTCBX;
INT8UOSTCBY;
INT8UOSTCBBitX;
INT8UOSTCBBitY;
#ifOS_TASK_DEL_EN
BOOLEANOSTCBDelReq;
#endif
}OS_TCB;
.OSTCBStkPtr 是指向当前任务栈顶的指针。μC/OS-Ⅱ允许每个任务有自己的栈,尤为重
要的是,每个任务的栈的容量可以是任意的。有些商业内核要求所有任务栈的容量都一
样,除非用户写一个复杂的接口函数来改变之。这种限制浪费了RAM,当各任务需要的栈
空间不同时,也得按任务中预期栈容量需求最多的来分配栈空间。OSTCBStkPtr是OS_TCB
数据结构中唯一的一个能用汇编语言来处置的变量(在任务切换段的代码Context-
switchingcode之中,)把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,而后又建立、删除
评论