在任一给定的时刻,任务的状态一定是在这五种状态之一。 (1) 睡眠态(DORMANT):指任务驻留在程序空间之中,还没有交给μC/OS-Ⅱ
管理。一个任务可以通过调用OSTaskDel()返回到睡眠态,或通过调用该函数让另一个任务进入睡眠态。
(2) 就绪态(READY):当任务一旦建立,这个任务就进入就绪态准备运行。把
任务交给μC/OS-Ⅱ是通过调用下述两个函数之一:OSTaskCreate()或OSTaskCreateExt()。
(3) 运行态(RUN): 调用OSStart()可以启动多任务。OSStart()函数运行进入就
绪态的优先级最高的任务。
(4) 等待状态(WAITING): 正在运行的任务可以通过调用两个函数之一将自
身延迟一段时间,这两个函数是OSTimeDly()或OSTimeDlyHMSM()。这个任务于是进入等待状态,等待这段时间过去,下一个优先级最高的、并进入了就绪态的任务立刻被赋予了CPU的控制权。正在运行的任务期待某一事件的发生时也要等待,手段是调用以下3个函数之一:OSSemPend(),OSMboxPend(),或OSQPend()。调用后任务进入了等待状态(WAITING)。
(5) 中断状态(ISR): 正在运行的任务是可以被中断的,除非该任务将中断关
了,或者μC/OS-Ⅱ将中断关了。被中断了的任务就进入了中断服务态(ISR)。
2. 论述μC/OS-Ⅱ的核心数据结构任务控制块(OS_TCBs) 答:
任务控制块(OS_TCBs)是μC/OS-Ⅱ的核心数据结构,当任务的CPU使用权被剥夺时,μC/OS-Ⅱ用它来保存该任务的状态。当任务重新得到CPU使用权时,任务控制块能确保任务从当时被中断的那一点丝毫不差地继续执行。OS_TCBs全部驻留在RAM中。一旦任务建立了,任务控制块OS_TCBs将被赋值。μC/OS-II任务控制块数据结构定义如下: typedef struct os_tcb {
OS_STK *OSTCBStkPtr; #if OS_TASK_CREATE_EXT_EN void *OSTCBExtPtr;
OS_STK *OSTCBStkBottom;
13
INT32U OSTCBStkSize; INT16U OSTCBOpt; INT16U OSTCBId; #endif
struct os_tcb *OSTCBNext; struct os_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
INT16U OSTCBDly; INT8U OSTCBStat; INT8U OSTCBPrio; INT8U OSTCBX; INT8U OSTCBY; INT8U OSTCBBitX; INT8U OSTCBBitY; #if OS_TASK_DEL_EN
BOOLEAN OSTCBDelReq; #endif } OS_TCB; 其中:
OSTCBStkPtr是指向当前任务栈顶的指针。
OSTCBExtPtr 指向用户定义的任务控制块扩展。 OSTCBStkBottom是指向任务栈底的指针。
OSTCBStkSize存有栈中可容纳的指针元数目而不是用字节(Byte)表示的栈容量总数。
OSTCBId用于存储任务的识别码。
OSTCBNext和OSTCBPrev用于任务控制块OS_TCBs的双重链接。 OSTCBEventPtr是指向事件控制块的指针。 OSTCBMsg是指向传给任务的消息的指针。 OSTCBStat是任务的状态字。 OSTCBPrio是任务优先级。
OSTCBDelReq是一个布尔量,用于表示该任务是否需要删除。
OSTCBX, OSTCBY, OSTCBBitX和 OSTCBBitY用于加速任务进入就绪态的过程或进入等待事件发生状态的过程。
3.论述事件控制块ECB数据结构 答:μC/OS-II通过uCOS_II.H 中定义的OS_EVENT数据结构来维护一个事件控制块的所有信息。该事件控制块ECB数据结构的定义如下: typedef struct {
void *OSEventPtr; /* 指向消息或者消息队列的指针 */
14
INT8U OSEventTbl[OS_EVENT_TBL_SIZE]; /* 等待任务列表 */ INT16U OSEventCnt; /* 计数器(当事件是信号量时) */ INT8U OSEventType; /* 时间类型 */
INT8U OSEventGrp; /* 等待任务所在的组 */ } OS_EVENT; 其中:
OSEventPtr指针: 只有在所定义的事件是邮箱或者消息队列时才使用。当所定义的事件是邮箱时,它指向一个消息,而当所定义的事件是消息队列时,它指向一个数据结构.
OSEventTbl[] 和 OSEventGrp: 两者包含的是系统中处于就绪状态的任务。
OSEventCnt:当事件是一个信号量时,用于信号量的计数器。 OSEventType:定义了事件的具体类型。
4.论述μC/OS-II内存的管理的内存控制块数据结构 答:为了便于内存的管理,在μC/OS-II中使用内存控制块(memory control blocks)的数据结构来跟踪每一个内存分区,系统中的每个内存分区都有它自己的内存控制块。
内存控制块的数据结构定义如下: typedef struct {
void *OSMemAddr; void *OSMemFreeList; INT32U OSMemBlkSize; INT32U OSMemNBlks; INT32U OSMemNFree; } OS_MEM; 其中:
OSMemAddr是指向内存分区起始地址的指针。
OSMemFreeList是指向下一个空闲内存控制块或者下一个空闲的内存块的指针。
OSMemBlkSize是内存分区中内存块的大小,是用户建立该内存分区时指定的。
OSMemNBlks是内存分区中总的内存块数量,也是用户建立该内存分区时指定的。
OSMemNFree是内存分区中当前可以得空闲内存块数量。
五、uC_OS-II程序题
一、编写一个uC/OS-II应用程序,要求:(1) 包含两个用户任务(MyTask、YouTask)和两个系统任务(统计任务、空闲任务); (2)把MyTask作为起始任务,MyTask、YouTask的优先级分别为0、2; (3) 当MyTask运行10次后对调度器进行加锁,运行到80次时对调度器进行解锁; (4) 当MyTask运行的运行次数大于85次后,要求YouTask删除它自己,YouTask接到要求后,等待15s钟,然后删除自己。
15
(这个程序要仔细点看,注释写得最详细,这个看懂了,后面的就应该也能看懂了,这三个程序大部分代码都是差不多的,蓝色粗体字的部分是一些关键语句或可能随着题目要求变化的语句)
#include \
#define TASK_STK_SIZE 512 //任务堆栈长度 OS_STK MyTaskStk[TASK_STK_SIZE]; //定义MyTask任务堆栈区 OS_STK YouTaskStk[TASK_STK_SIZE]; //定义YouTask任务堆栈区 INT8U x=0,y=0; //这两个变量分别用来指定要显示字符的横纵坐标,即列和行,标准的DOS窗口是80x25,也就是可以显示80行、25列字符,
//有了这两个变量就可以将字符精确的显示在DOS窗口的某个地方。
INT8U times=0; //这个变量用了记录MyTask任务的运行次数 void MyTask(void* pdata); void YouTask(void* pdata);
void main (void) { char* s_M=\ OSInit(); //初始化uCOS_II PC_DOSSaveReturn(); //保存Dos环境 PC_VectSet(uCOS, OSCtxSw); //安装uCOS_II中断 OSTaskCreate(MyTask, s_M, &MyTaskStk[TASK_STK_SIZE - 1], 0);
// 创建起始任务(此题中要求将MyTask作为起始任务), 将s_M //作为参数传递给MyTask函数,并将该任务的优先级设置为0(优先级按照题目的规定去设置,一般起始任务要设置为最高[数值越小,优先级越高])。
OSStart(); //启动系统 }
void MyTask (void *pdata) {
char* s_M=\OSInit(); //初始化
uCOS_II PC_DOSSaveReturn(); //保存Dos环境 PC_VectSet(uCOS, OSCtxSw); //安装uCOS_II中断
OSTaskCreate(MyTask, s_M, &MyTaskStk[TASK_STK_SIZE - 1], 0);// 创建起始任务(此题中要求将MyTask作为起始任务), 将s_M
//作为参数传递给MyTask函数,并将该任务的优先级设置为0(优先级按照题目的规定去设置,一般起始任务要设置为最高[数值越小,优先级越高])。 OSStart(); //启动系统 }
void MyTask (void *pdata) {
char* s_Y=\
char* s=\#if OS_CRITICAL_METHOD == 3 //如果使用的是第3种方法来开关中断,则需要用
16