yanshanbao 发表于 2012-3-1 21:03:48

第三天 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级检测技术与仪器

airfex 发表于 2012-3-1 21:53:01

楼主学的真快。

yanshanbao 发表于 2012-3-1 22:08:19

回复【1楼】airfex
-----------------------------------------------------------------------
不是我学的快,我学的慢啊,在寒假有半个月的时间都在看邵贝贝老师的书,现在是一边复习,一边记笔记。还没自己独立移植一下呢。
页: [1]
查看完整版本: 第三天 UC/OS-II的学习