第三天 UC/OS-II的学习
第三天1-2 回答了任务时如何被调度的。
1. 任务调度:(scheduler)
任务级的调度是由函数OSSched()完成的,中断级的调度是由OSIntExt()完成的。
1.1任务调度所化的时间是常数。与应用程序建立的任务数无关。(可参考OSSched()函数的代码,代码如3.1.1所示。)
void OSSched (void)
{
INT8U y;
OS_ENTER_CRITICAL();//进入临界区
if ((OSLockNesting | OSIntNesting) == 0)//调用了任务调度函数 | 中断嵌套层数
{
y=OSUnMapTbl;
OSPrioHighRdy=(INT8U)((y << 3) + OSUnMapTbl]);
if (OSPrioHighRdy != OSPrioCur)
{
OSTCBHighRdy = OSTCBPrioTbl;
OSCtxSwCtr++;//跟踪任务切换次数。
OS_TASK_SW();//进行任务切换。
}
}
OS_EXIT_CRITICAL();
}
1.2 任务切换分两步完成。 将被挂起的微处理器寄存器推入堆栈,然后将较高优先级的任务的寄存器值从栈中恢复到寄存器。运行OS_TASK_SW()在移植到51中用的是宏定义#defineOS_TASK_SW() OSCtxSw()在51中 OSCtxSw()是用的是汇编写的。
1.3 OSCtxSw()人为模仿一次中断,下面是51单片机的汇编程序
; --------------------------------------------------
; --------------------- OSCtxSw() ------------------
; --------------------------------------------------
RSEG ?PR?OSCtxSw?OS_CPU_A
OSCtxSw:
;-----------------
; push registers
;-----------------
PUSH ACC
PUSH B
PUSH DPH
PUSH DPL
PUSH PSW
PUSH 00
PUSH 01
PUSH 02
PUSH 03
PUSH 04
PUSH 05
PUSH 06
PUSH 07
OSCPUAUniformCtxSw:
;assume register is pushed to hardware stack, in the format as discripted at the beginning of this file
;Before jump OSCPUAUniformCtxSw, OSCtxSw or OSIntCtxSw must first push registers to hardware stack as this format.
;----------------------
;Get OSTCBCurRdy->OSTCBStkPtr to DPTR
;-----------------------
;high byte is at low address
;OSTCBCurRdy to dptr
MOV DPH,#HIGH(OSTCBCur)
MOV DPL,#LOW (OSTCBCur)
MOVX A,@DPTR
MOV R0,A
INC DPTR
MOVX A,@DPTR
MOV DPH,R0
MOV DPL,A
;OSTCBStkPtr to dptr
MOVX A,@DPTR
MOV R0,A
INC DPTR
MOVX A,@DPTR
MOV DPH,R0
MOV DPL,A
;--------------------
;save stack
;--------------------
;store ?C_IBP
MOV A,?C_IBP
MOVX @DPTR,A
;store simulated stack
JZ OSCPUASmltSaveOver ;simulated stack size == 0, that is A == 0x100
MOV R0,A
OSCPUASmltSave:
INC DPTR
MOV A,@R0
MOVX @DPTR,A
INC R0
CJNE R0,#0,OSCPUASmltSave
OSCPUASmltSaveOver:
;store sp size
INC DPTR
MOV A,SP
CLR C
SUBB A,#StkBottom - 1
MOVX @DPTR,A
;store hardware stack and registers
;stack top is at high address
MOV R1,A ;caluate copy rotation times
MOV R0,#StkBottom - 1 ;start of stack defined by keilc system
OSCPUASaveStk:
INC R0
INC DPTR
MOV A,@R0
MOVX @DPTR,A
DJNZ R1,OSCPUASaveStk
;-------------------
;call OSTaskSwHook
;-------------------
LCALL _?OSTaskSwHook
;-------------------
; OSTCBCur = OSTCBHighRdy
;-------------------
MOV DPH,#HIGH (OSTCBHighRdy)
MOV DPL,#LOW(OSTCBHighRdy)
MOVX A,@DPTR
MOV R7,A ;store to R7/R6
INC DPTR
MOVX A,@DPTR
MOV R6,A
MOV DPH,#HIGH (OSTCBCur)
MOV DPL,#LOW(OSTCBCur)
MOV A,R7
MOVX @DPTR,A
MOV A,R6
INC DPTR
MOVX @DPTR,A
;-----------------
; OSPrioCur = OSPrioHighRdy
;-----------------
MOV DPH,#HIGH (OSPrioHighRdy)
MOV DPL,#LOW(OSPrioHighRdy)
MOVX A,@DPTR
MOV DPH,#HIGH (OSPrioCur)
MOV DPL,#LOW(OSPrioCur)
MOVX @DPTR,A
;-----------------
; Restore Ctx
;-----------------
LJMP OSCPUARstStk
1.4 为缩短切换时间,OSSched()可以用汇编写。 OSCtxSw()中除了需要OSTCBHighRdy指向即将被挂起的任务,还需要让当前任务控制块OSTCBCur指向即将被挂起的任务。
2. 给调度器上锁 OSSchedlock() 和给调度器解锁 OSSchedUnlock()
2.1 OSSchedlock()用于禁止任务调度,知道任务完成后调用给调度器开锁函数OSschedUnlock()。
2.2 这两个函数要成对出现。
2.3 OSSchedLock()这个函数就是OSLockNesting++ ;代码3.1.1中的if语句,可以明白是如何上锁的。。。。
2.4 调用了OSSchedlock()函数的任务保持对CPU的控制权。但此时中断程序可以进行。
2.5 调用了OSSchedlock()之后,用户的应用程序,不能调用OSMboxPend()、OSQPend()
等函数了。
3. 空闲任务 idle task
永远设为最低优先级 OS_LOWEST_PRIO 空闲任务就是让OSIdleCtr++; 中断要关闭。
燕山大学电气工程学院09级检测技术与仪器 楼主学的真快。 回复【1楼】airfex
-----------------------------------------------------------------------
不是我学的快,我学的慢啊,在寒假有半个月的时间都在看邵贝贝老师的书,现在是一边复习,一边记笔记。还没自己独立移植一下呢。
页:
[1]