以前用8位
单片机时,中断分内部中断和外部中断,内部中断是定时器产生的。
UCOS中涉及到了软中断。通过这段时间的学习,我觉得只有理解了软中断,才算了解了UCOS任务调度的基础。
UCOS中任务调度是调用
OS_SCHED()函数实现的,当有优先级更高的任务就绪时,就会进行任务调度,在OS_SCHED()函数最后通过调用宏
OS_TASK_SW()来完成任务切换。
在OS_CPU.H中定义了
#define OS_TASK_SW() OSCtxSw()
OSCtxSw()是在OS_CPU_A.ASM中定义的。
_OSCtxSw PROC FAR
;
PUSHA ; Save current task's context
PUSH ES ;
PUSH DS ;
;
MOV AX, SEG _OSTCBCur ; Reload DS in case it was altered
MOV DS, AX ;
;
LES BX, DWORD PTR DS:_OSTCBCur ; OSTCBCur->OSTCBStkPtr = SS:SP
MOV ES:[BX+2], SS ;
MOV ES:[BX+0], SP ;
;
CALL FAR PTR _OSTaskSwHook ; Call user defined task switch hook
;
MOV AX, WORD PTR DS:_OSTCBHighRdy+2 ; OSTCBCur = OSTCBHighRdy
MOV DX, WORD PTR DS:_OSTCBHighRdy ;
MOV WORD PTR DS:_OSTCBCur+2, AX ;
MOV WORD PTR DS:_OSTCBCur, DX ;
;
MOV AL, BYTE PTR DS:_OSPrioHighRdy ; OSPrioCur = OSPrioHighRdy
MOV BYTE PTR DS:_OSPrioCur, AL ;
;
LES BX, DWORD PTR DS:_OSTCBHighRdy ; SS:SP = OSTCBHighRdy->OSTCBStkPtr
MOV SS, ES:[BX+2] ;
MOV SP, ES:[BX] ;
;
POP DS ; Load new task's context
POP ES ;
POPA ;
;
IRET ; Return to new task
;
_OSCtxSw ENDP
程序调用OSCtxSw()函数时,就产生软件中断,强制处理器保存当前任务的状态寄存器和PC值到当前任务的堆栈,然后在_OSCtxSw程序中把CPU的重要寄存器内容都保存进当前任务的堆栈。
然后把高优先级任务堆栈中的寄存器值送到对应的CPU寄存器,最后执行中断返回指令,把高优先级任务堆栈中的状态寄存器和PC值送到CPU的状态寄存器和PC寄存器中。程序就从当前PC寄存器指向的地址开始执行。这就完成了任务切换。
执行OSCtxSw()函数就类似于51中产生了一次中断,不同的是,51产生中断后,执行完中断程序,退出中断,然后从产生中断的地方继续往下执行。UCOS中,调用完
OSCtxSw()后,执行的是另外一个优先级更高的任务.
UCOS-II假定任务切换是靠中断级代码完成的。一种任务切换是调用OSCtxSw()函数产生软件中断。还有一种任务切换是硬件产生中断,执行完硬件中断程序后,如果有更高优先级的任务就绪。就进行任务切换。原理和上面说的类似。
文章评论(0条评论)
登录后参与讨论