`
huobengluantiao8
  • 浏览: 1029388 次
文章分类
社区版块
存档分类
最新评论

uC/OSii 的学习笔记 ( 2 )

 
阅读更多

五、从睡眠态到就绪态

睡眠态到就绪态调用OSTaskCreate()或者OSTaskCreateEXt()建立一个任务,在多任务调度前 (也就是调用OSStart()) 必须要创建一个应用任务(除去空闲任务和统计任务)。

任务建立过程:

(1)首先对OSTaskCreate((void(*task))(void *pd),void *pdate,OS_STK *ptos,INT8U prio)参数赋值!

*Task(指向任务代码起始地址的指针)

*pdate(给task(*pdata)传递的参数的指针)

*ptos(起始栈顶位置,如果堆栈属于从高地址向低地址方向增长的,那么*ptos应该等于&taskstack[TASK_STACK_SIZE-1].如果是从低地址向高地址方向增长,那么*ptos的值等于&taskstack[0].)

Prio(该任务的优先级)

(2)判断设置的优先级是否已经存在。

OSTCBPrioTbl[prio]= =(OS_TCB*)0 :这就表明该优先级的任务还不存在

解释:OSTCBPrioTbl[]是一个指针数组,作用例如OSTCBPrioTbl[2],他代表的是指向任务优先级为2的任务的任务控制块,而OSTCBPrioTbl[prio]= =(OS_TCB*)0代表的是指向优先级prio的指针为空,没有指向任务快,这就表明该优先级的任务还不存在。

(3)为任务分配任务堆栈并初始化,调用函数OSTaskInit(task,pdata,ptos,0)

Ptos初始栈顶位置,这样就知道该任务堆栈在内存的位置。然后将Task(指向任务代码起始地址 ) pdate(给task(*pdata)传递的参数值)压入堆栈,还有R14—R0也要入堆栈。然后将现在的堆栈栈顶指针返回给变量psp。

(4)为任务分配TCB并初始化。调用函数OS_TCBInit( prio,psp,(void*)0,0,0,(void*)0,0)

将优先级和(psp)栈顶位置传给OS_TCBInit,用来建立TCB..

(5)然后调用OS_Sched()。 注:我认为只要某个函数里面有对优先级改变的,都要用到OS_Sched(),因为uC/Osii属于抢占式操作系统,因此CPU总是为优先级最高的任务服务,那么当每次改变任务优先级后,都要OS_Sched()用检查有没有新的最高优先级任务出现,如果有的话就将CPU分配给该任务。

OSTaskCreateEXt()与上面类似。

六、从就绪态到运行状态 以及从运行态都就绪态。

就绪态到运行状态调用到的 函数OS_Sched(void)相当于一个任务调度器。

OS_Sched(void)操作就两大块,

第一是从就绪表中OSRdyGrp和OSRdyTbl[ ]找到最高优先级的任务。所以通过

y=OSUNMapTbl[OSRdyGrp]

x= OSUNMapTbl[OSRdyTbl[y]]

最大Prio=INT((y<<3)+X)

第二步就是将CPU分配给该任务。

OSTCBHighRdy= OSTCBPrioTbl[prio]//OSTCBHighRdy指向高优先级的任务。

然后调用OS_TASK_SW( )函数将CPU的寄存器状态压入低优先级任务,并将OSTCBCur= OSTCBHighRdy 也就是将OSTCBCur指向高优先级的任务(OSTCBCur总是指向正在运行的任务),然后将高优先级任务的堆栈内容赋给CPU的寄存器,然后该任务运行。

从运行态都就绪态

同样是是是函数OS_Sched(void),当有一个新最高级的任务出现在就绪队列中,那么正在运行的任务将会被取代,转而进人就绪态。

七、从运行态到等待状态

从运行态到等待状态,分为三种:

第一种是挂起函数,OSTASKSupend(),任务挂起是一个附加功能,把任务从就绪表中移除,进入等待状态。

第二种是OsTimeDly()函数,它是将任务本身延时一定时间,这个函数其实就是对TCB中的OSTCBDly变量进行赋值且把任务从就绪表中移除,进入等待状态。然后通过用OSTimeTick()对每个TCB的OSTCBDly(非0值的)每过隔一个接拍就减一,直至为0,表明延时结束,然后将该任务恢复到就绪态。

第三种是等待某一事件的发生时,调用以下几个函数:OSFlagPend()、OSSemPend(),OSMutexPend()、OSMboxPend(),如果该事件发生了,那么该任务继续执行,如果该事件没有发生,那么将自身挂起,因而处于等待或挂起态。

与上面不同,不仅要从就绪表中移除该任务,还要将任务添加到相应事件ECB的等待列表OSEvenGrp和OSEvenTbl[]中(就像就绪表一样,等待列表允许多个任务,也就是可能有多个任务同时等待一个事件发生)。

所有的通信信号都被看成一个事件。

事件分为:信号量、互斥信号量,消息邮箱、队列消息。每一个信号量、互斥信号量,消息邮箱、消息队列都会分配到一个事件控制块ECB.

ECB的结构如下

Typedef struct{

Void *OSEventPtr //指向信号的指针

INT8U OSEventCnt //计数器,用于事件是信号量。

INT8U OSEventType //事件的类型(如信号量,互斥信号量,队列消息等)

INT8U OSEventGrp //等待任务组

INT8U OSEventTbl[ ] //等待任务列表

每个ECB都会有 事件的等待列表OSEvenGrp和OSEvenTbl[] ,它与就绪表中OSRdyGrp和OSRdyTbl[ ]极为相似。

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics