浅析μ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 ( ) ;
}
}
}
文章来源 : 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 ( ) ;
}
}
}