您的位置:首页 > 其它

浅析μC/OS-II OSTimeDly()函数和OSTimeTick()函数工作原理

2015-10-13 10:51 411 查看
浅析μC/OS-II
v2.85内核OSTimeDly()函数工作原理

文章来源:http://gliethttp.cublog.cn[转载请声明出处]

//----------------------------------------------------------------------

//1.OSTimeDly()函数

void OSTimeDly (INT16U
ticks)

{

INT8U y;

#if OS_CRITICAL_METHOD == 3

OS_CPU_SR cpu_sr = 0;

#endif

if (OSIntNesting > 0) {

return;//在中断处理函数中调用了OSTimeDly(),那么直接退出

}

if (ticks > 0) {

OS_ENTER_CRITICAL();

//调用OSTimeDly()的进程自己把自己从就绪控制矩阵中拿下来,

//即:去掉调度器(x,y)矩形阵列(OSRdyTbl,OSRdyGrp)中该task对应的bit位,使得调度器不考虑

//该task的调度

y = OSTCBCur->OSTCBY;

OSRdyTbl[y] &= ~OSTCBCur->OSTCBBitX;

if (OSRdyTbl[y] == 0) {

OSRdyGrp &= ~OSTCBCur->OSTCBBitY;

}

//延时ticks值,放入OSTCBDly单元,在os时钟滴答处理函数OSTimeTick()中,会处理该单元[gliethttp]

OSTCBCur->OSTCBDly = ticks;

OS_EXIT_CRITICAL();

//因为本task正在运行,所以本task现在的优先级最高,现在本task已经将自己从就绪控制矩阵中--调度器(x,y)矩形阵列

//把自己摘掉,所以调度函数OS_Sched()一定会切换到另一个task中执行新task的代码[gliethttp]

OS_Sched();//具体参见《浅析μC/OS-II
v2.85内核调度函数》

}//ticks==0,那么什么也不做

}

//----------------------------------------------------------------------

//2.OSTimeTick()--在定时中断里引用的系统滴答函数

void OSTimeTick (void)

{

OS_TCB *ptcb;

#if OS_TICK_STEP_EN > 0

BOOLEAN step;

#endif

#if OS_CRITICAL_METHOD == 3

OS_CPU_SR cpu_sr = 0;//该3方式将使中断状态寄存器放入堆栈中

#endif

#if OS_TIME_TICK_HOOK_EN > 0

OSTimeTickHook();

#endif

#if OS_TIME_GET_SET_EN > 0

OS_ENTER_CRITICAL();

OSTime++;

OS_EXIT_CRITICAL();

#endif

if (OSRunning == OS_TRUE) {

#if OS_TICK_STEP_EN > 0

//控制内核的tick

switch (OSTickStepState) {

case OS_TICK_STEP_DIS:

step = OS_TRUE;

break;

case OS_TICK_STEP_WAIT:

step = OS_FALSE;

break;

case OS_TICK_STEP_ONCE:

//本次tick将将影响到task的OSTCBDly域

//但以后的tick将一直被屏蔽,不会影响到OSTCBDly域

//直到外部将OSTickStepState改变为止[gliethttp]

step = OS_TRUE;

OSTickStepState = OS_TICK_STEP_WAIT;

break;

default:

step = OS_TRUE;//本次tick将影响到task的OSTCBDly域

OSTickStepState = OS_TICK_STEP_DIS;

break;

}

if (step == OS_FALSE) {

return;

}

#endif

ptcb = OSTCBList;

//2007-09-08 gliethttp

//OSTCBList是一个按进程创建的先后顺序链接成的task单向链表,最后创建的task在最前面,最先创建的

//task在单向链表的尾端,

//所以OS_TaskIdle空闲进程在链表的最后,因为它最先创建

while (ptcb->OSTCBPrio != OS_TASK_IDLE_PRIO) {

OS_ENTER_CRITICAL();

if (ptcb->OSTCBDly != 0) {

if (--ptcb->OSTCBDly == 0) {

//该task的延时时间已到,解析此次延时是OSTimeDly()引起的,还是OSQPend()之类超时引起的[gliethttp]

if ((ptcb->OSTCBStat & OS_STAT_PEND_ANY) != OS_STAT_RDY) {

//2007-09-08
gliethttp

//如:由OSSemPend
(pevent,timeout,perr);定义的timeout已经到了,对应task需要运行了

//超时时间到,所以不论当前进程是在做什么,只要时间一到

//该task就可以运行了,所以清除所有事件标志,之后状态标示为OS_STAT_PEND_TO(超时)

ptcb->OSTCBStat &= ~(INT8U)OS_STAT_PEND_ANY;

ptcb->OSTCBStatPend = OS_STAT_PEND_TO;//超时异常

} else {

//2007-09-08
gliethttp

//说明该task调用的是OSTimeDly()

ptcb->OSTCBStatPend = OS_STAT_PEND_OK;//正常结束

}

if ((ptcb->OSTCBStat & OS_STAT_SUSPEND) == OS_STAT_RDY) {

//2007-09-08
gliethttp

//如果该task没有suspend,那么把当前就绪的task加入到运行调度器的就绪控制矩阵中

//等待被调度

OSRdyGrp |= ptcb->OSTCBBitY;

OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX;

}

}

}

ptcb = ptcb->OSTCBNext;//继续运算下一个task的OSTCBDly时间域

OS_EXIT_CRITICAL();

}

}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: