标签:
今天学习了uC/OS II的任务切换,知道要实现任务的切换,要将原先任务的寄存器压入任务堆栈,再将新任务中任务堆栈的寄存器内容弹出到CPU的寄存器,其中的CS、IP寄存器没有出栈和入栈指令,所以只能引发一次中断,自动将CS、IP寄存器压入堆栈,再利用中断返回,将新任务的任务断点指针弹出到CPU的CS、IP寄存器中,实现任务切换。虽然明白个大概,但是其中的细节却有点模糊,为什么调用IRET中断返回指令后,弹入CPU的CS、IP寄存器的断点指针是新任务的断点指针,而不是当前任务的,UCOS II是如何实现这个过程的?网上的文章没有提及任务切换的细节,然而这些细节却是理解的重点,所以才有了今天这一篇文章!
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 }
1 _OSCtxSw PROC FAR 2 ; 3 ;保存当前任务寄存器内容,将它们压入当前任务堆栈,AX、CX、DX、BX、SP(原始值)、BP、SI 及 DI 4 PUSHA ; 5 PUSH ES ; 6 PUSH DS ; 7 ; 8 ;将当前任务的任务控制块的指针段值赋值给DS寄存器 9 MOV AX, SEG _OSTCBCur;Reload DS in case it was altered 10 MOV DS, AX ; 11 ; 12 ; LES指令作用,取得DS:_OSTCBCur任务控制块指针所指向的内容(因为任务控制块的第一个成员为任务堆栈指针,所以ES:[BX+0]指向的是任务堆栈),低字存放于BX,高字存放于ES,说明任务堆栈的前4字节是用于存放CPU堆栈相关寄存器的,有关LES详细查看另一篇文章! 13 ;同时由于任务控制块的第一成员为任务堆栈指针变量,所以任务堆栈指针成员变量的地址和任务控制块的地址一样 14 LES BX, DWORD PTR DS:_OSTCBCur;取得任务堆栈指针ES:[BX] 15 MOV ES:[BX+2], SS ;将当前SS(栈的基地址)寄存器值存放至当前任务堆栈的2,3内存单元 16 MOV ES:[BX+0], SP ;将当前SP(栈顶的偏移量)存放至当前任务堆栈的0,1内存单元 17 ; 18 CALL FAR PTR _OSTaskSwHook;Call user defined task switch hook 19 ; 20 ;存储器寻址,DS:_OSTCBHighRdy+2存放的是新任务的栈基址SS,DS:_OSTCBHighRdy存放的是栈顶偏移量SP 21 MOV AX, WORD PTR DS:_OSTCBHighRdy+2;将OSTCBHighRdy赋值给OSTCBCur,使OSTCBCur指向新的任务控制块 22 MOV DX, WORD PTR DS:_OSTCBHighRdy;OSTCBCur=OSTCBHighRdy 23 MOV WORD PTR DS:_OSTCBCur+2, AX ; 24 MOV WORD PTR DS:_OSTCBCur, DX ; 25 ; 26 MOV AL, BYTE PTR DS:_OSPrioHighRdy;OSPrioCur=OSPrioHighRdy 27 MOV BYTE PTR DS:_OSPrioCur, AL ; 28 ; 29 ;将最高级优先级任务的任务控制块包含的SS和SP寄存器值,CPU的SS和SP指向了新的任务堆栈 30 LES BX, DWORD PTR DS:_OSTCBHighRdy; SS:SP = *(OSTCBHighRdy->OSTCBStkPtr),为什么是*,因为存放SS和SP的地方其实是任务堆栈指针OSTCBStkPtr所指向的前4字节内存单元,而并不是任务堆栈指针本身! 31 MOV SS, ES:[BX+2]; 32 MOV SP, ES:[BX]; 33 ; 34 ;注意:这里弹出的是新任务的堆栈,而不是旧的,因为CPU的SS和SP已经指向了新的任务堆栈 35 POP DS ;Loadnew task‘s context 36 POP ES ; 37 POPA ; 38 ; 39 ;当新任务的堆栈都弹出的时候,只剩下新任务的CS、IP指针,刚好运行IRET弹到CPU的CS、IP寄存器,开始新任务的运行 40 IRET ;Return to new task 41 ; 42 _OSCtxSw ENDP
本文链接:http://www.cnblogs.com/cposture/p/4291503.html
标签:
原文地址:http://www.cnblogs.com/cposture/p/4291503.html