今天学习了uC/OS II的任务切换,知道要实现任务的切换,要将原先任务的寄存器压入任务堆栈,再将新任务中任务堆栈的寄存器内容弹出到CPU的寄存器,其中的CS、IP寄存器没有出栈和入栈指令,所以只能引发一次中断,自动将CS、IP寄存器压入堆栈,再利用中断返回,将新任务的任务断点指针弹出到CPU的CS、IP寄存器中,实现任务切换。虽然明白个大概,但是其中的细节却有点模糊,为什么调用IRET中断返回指令后,弹入CPU的CS、IP寄存器的断点指针是新任务的断点指针,而不是当前任务的,UCOS II是如何实现这个过程的?网上的文章没有提及任务切换的细节,然而这些细节却是理解的重点,所以才有了今天这一篇文章!
在uC/OS II中,任务的调度由任务调度器完成,其主要的工作有两项:
1.在任务就绪表中查找最高优先级的就绪任务,该任务将是未来切换执行的任务;
2.实现任务的切换。
任务级的任务调度器,由OS_Sched()实现。
1 //!!!为简单说明问题,OS_Sched中特意删减了一些语句 2 void OS_Sched (void) 3 { 4 INT8U y; 5 OS_ENTER_CRITICAL(); 6 y =OSUnMapTbl[OSRdyGrp]; 7 //得到最高优先级任务,OSPrioHighRdy从此为就绪表中最高优先级任务的优先级别 8 OSPrioHighRdy=(INT8U)((y <<3)+OSUnMapTbl[OSRdyTbl[y]]); 9 //判断当前任务是否为就绪表中最高优先级任务 10 if(OSPrioHighRdy!=OSPrioCur) 11 { 12 //得到新任务的任务控制块的指针 13 OSTCBHighRdy=OSTCBPrioTbl[OSPrioHighRdy]; 14 //统计任务切换次数的计数器加1 15 OSCtxSwCtr++; 16 //此句关键!使用软件中断切换任务,OS_TASK_SW()其实为INT 0x80,128号中断 17 //中断产生后,CPU依次将PSW状态寄存器、断点指针段地址:偏移地址压入当前任务的堆栈中 18 OS_TASK_SW(); 19 } 20 OS_EXIT_CRITICAL(); 21 }