忽略前期初始化等细节,从main()开始:
/**************************************************************/
int Main(int argc, char **argv)
{
ARMTargetInit(); //初始化运行环境
OSInit(); //初始化OS
Sem_F=OSFlagCreate(0,&err); //创建信号量集
OSTaskCreate(StartTask,(void *)0,&StartTaskStk[STACKSIZE-1],0); //创建起始任务
OSStart(); //运行任务,在OSStart()调用StartTask()
return 0;
}
/**************************************************************/
void StartTask(void *pdata)
{
pdata=pdata;
ARMTargetStart(); //配置和打开中断,系统时钟开始运行
OSTaskCreate(Led1Task,(void *)s1,&Led1TaskStk[STACKSIZE-1],3); //创建任务Led1Task
OSTaskCreate(Led2Task,(void *)s2,&Led2TaskStk[STACKSIZE-1],4); //创建任务Led2Task
OSTaskCreate(Led3Task,(void *)s3,&Led3TaskStk[STACKSIZE-1],5); //创建任务Led3Task
do{
OSTaskDel(0); //删除此任务 在OSTaskDel中调用OS_Sched将运行优先级最高的Led1Task
}while(1);
}
/**************************************************************/
下面为简单起见,单独分析Led1Task
void Led1Task(void *pdata)
{
for(;;)
{
//OSFlagPend(Sem_F,(OS_FLAGS)3,OS_FLAG_WAIT_SET_ALL,0,&err); //请求信号量集的第0和第1位且都置1
rPDATC=0x02; //点亮led1
//串口打印pdata,pdata为形参,由Led1Task 创建时引入,为s1, s1定义为“led1 on”
Uart_Printf(pdata);
OSTimeDlyHMSM(0,0,2,0); //延时2秒
}
}
此时为死循环,观察循环体内的函数,唯有从OSTimeDlyHMSM(0,0,1,0)中下手,查看OSTimeDlyHMSM源代码,可发现里面调用了OSTimeDly()
/**************************************************************/
INT8U OSTimeDlyHMSM(INT8U hours, INT8U minutes, INT8U seconds, INT16U milli)
{
INT32U ticks;
INT16U loops;
¥%……%#¥&**&&%¥#¥#¥&……*
ticks = ((INT32U)hours * 3600L + (INT32U)minutes * 60L + (INT32U)seconds) * OS_TICKS_PER_SEC
+ OS_TICKS_PER_SEC * ((INT32U)milli + 500L / OS_TICKS_PER_SEC) / 1000L;
loops = (INT16U)(ticks / 65536L); /* Compute the integral number of 65536 tick delays */
ticks = ticks % 65536L; /* Obtain the fractional number of ticks */
OSTimeDly((INT16U)ticks);
while (loops > 0) {
OSTimeDly((INT16U)32768u);
OSTimeDly((INT16U)32768u);
loops--;
}
return (OS_NO_ERR);
}
这里调用了OSTimeDly ,至此,仍未发现与调度相关的内容,进一步查看OSTimeDly 源代码~
/**************************************************************/
void OSTimeDly (INT16U ticks)
{
#¥%……&*……#¥……¥&%……*
INT8U y;
if (ticks > 0) { /* 0 means no delay! */
OS_ENTER_CRITICAL();
y = OSTCBCur->OSTCBY; /* Delay current task */
OSRdyTbl[y] &= ~OSTCBCur->OSTCBBitX;
if (OSRdyTbl[y] == 0) {
OSRdyGrp &= ~OSTCBCur->OSTCBBitY;
}
/*ticks 非0值会使得任务延时函数OSTimeDly()将当前任务从就绪表中移除*/
OSTCBCur->OSTCBDly = ticks; /* Load ticks in TCB */
OS_EXIT_CRITICAL();
OS_Sched(); /* Find next task to run! */
}
}
终于发现亲人了....OS_Sched ==! 此时,如果ticks大于0,则该任务被OSTimeDly 挂起,由OS_Sched 运行更低优先级的任务。此时系统中用户共创建了三个任务,比Led1Task 稍低的是Led2Task因此,系统会运行Led2Task 基于同样的调度原理,进而运行Led3Task
然而,如果此时只有一个任务,那将会发生什么情况呢?换句话说,系统运行到OSTimeDly 时没有比当前任务优先级更低的任务时怎么办?哈哈 我们还有大招...OS_TaskIdle,OS_TaskIdle是ucosii中由OS自行创建的优先级最低的任务,且不能被用户删除。