久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 2626|回復(fù): 0
打印 上一主題 下一主題
收起左側(cè)

以STC12C5A60H單片機(jī)文處理器的UCOS代碼的分析

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:216359 發(fā)表于 2020-5-10 16:55 | 只看該作者 回帖獎(jiǎng)勵(lì) |倒序?yàn)g覽 |閱讀模式
看到了好的UCOS文章, 僅以學(xué)習(xí)為目的。從帖子標(biāo)題同可見,這是基于宏晶單片機(jī)的,和51從內(nèi)部的結(jié)構(gòu),到語言是一樣的,內(nèi)存大了一點(diǎn)。結(jié)合前面的帖子,可以看懂模擬堆棧的使用。可重入函數(shù)的代碼依舊在ROM中的,這一點(diǎn)大家一定要明白。只是在256(0XFFH)以后的RAM(0X03FFH:1024)中開了堆棧,為各函數(shù)調(diào)用可重入函數(shù)保存變量,以避免主調(diào)函數(shù)的局部變量彼此覆蓋。而這個(gè)堆棧名稱為模擬堆棧。

$NOMOD51;不使用keil提供的51寄存器地址定義,而使用下面自己寫的寄存器地址定義
EA BIT 0A8H.7
SP DATA 081H
B DATA 0F0H
ACC DATA 0E0H
DPH DATA 083H
DPL DATA 082H
PSW DATA 0D0H
TR0 BIT 088H.4
TH0 DATA 08CH
TL0 DATA 08AH


TIMER_20MS_TH0 EQU 070H ;CPU=22.1184MHz, OS_TICKS_PER_SEC=50, TH0=0x70
TIMER_20MS_TL0 EQU 000H ;CPU=22.1184MHz, OS_TICKS_PER_SEC=50, TL0=0x00
  NAME OS_CPU_A ;模塊名
        
;定義重定位段
;1、無參函數(shù): ?PR?函數(shù)名?文件名
;2、有參函數(shù): ?PR?_函數(shù)名?文件名
;3、再入函數(shù): ?PR?_?函數(shù)名?文件名
?PR?OSStartHighRdy?OS_CPU_A    SEGMENT CODE  ;聲明一個(gè)可重定位的段,段名為?PR?OSStartHighRdy?OS_CPU_A,若想使用這個(gè)段中的空間,需要使用RSEG指令表明我要對下面的匯編語句進(jìn)行重定位
?PR?OSCtxSw?OS_CPU_A           SEGMENT CODE
?PR?OSIntCtxSw?OS_CPU_A        SEGMENT CODE
?PR?OSTickISR?OS_CPU_A         SEGMENT CODE


?PR?_?SerialISR?OS_CPU_A   SEGMENT CODE
        
;聲明引用全局變量和外部子程序
        EXTRN DATA  (?C_XBP) ;仿真堆棧指針用于可重入局部變量保存


        EXTRN IDATA (OSTCBCur)
        EXTRN IDATA (OSTCBHighRdy)
        EXTRN IDATA (OSRunning)
        EXTRN IDATA (OSPrioCur)
        EXTRN IDATA (OSPrioHighRdy)
   
        EXTRN CODE  (_?OSTaskSwHook)
        EXTRN CODE  (_?OSIntEnter)
        EXTRN CODE  (_?OSIntExit)
        EXTRN CODE  (_?OSTimeTick)


EXTRN CODE  (_?Serial)        
            
;對外聲明4個(gè)不可重入函數(shù)
        PUBLIC OSStartHighRdy
        PUBLIC OSCtxSw
        PUBLIC OSIntCtxSw
        PUBLIC OSTickISR
        
        ;PUBLIC SerialISR        
   
;分配堆棧空間。只關(guān)心大小,堆棧起點(diǎn)由keil決定,通過標(biāo)號可以獲得keil分配的SP起點(diǎn)
?STACK SEGMENT IDATA
        RSEG ?STACK


OSStack:
;DS n:保留n個(gè)存儲(chǔ)單元
        DS 40H ;分配硬件堆棧的大小;STARTUP.A51啟動(dòng)文件中在?STACK段中分配了1 B,這里又分配了40H B,故?STACK段總共有41H個(gè)字節(jié)


OSStkStart IDATA OSStack-1


;定義手動(dòng)壓棧出棧宏。  有些CPU寄存器是自動(dòng)在系統(tǒng)棧中入棧出棧的,從程序中觀察不到,
;例如在調(diào)用函數(shù)前(也即JMP類指令時(shí)),會(huì)把PC入SP指向的系統(tǒng)棧,RET/RETI時(shí)會(huì)用SP把PC出棧
PUSHALL    MACRO
        PUSH PSW
        PUSH ACC
        PUSH B
        PUSH DPL
        PUSH DPH
        MOV  A,R0 ;R0~R7入棧;   工作寄存器Rn不能直接入棧,必須借助A或B等中轉(zhuǎn)一下入棧。更好的保護(hù)Rn的方法是切換工作寄存器組
        PUSH ACC
        MOV  A,R1
        PUSH ACC
        MOV  A,R2
        PUSH ACC
        MOV  A,R3
        PUSH ACC
        MOV  A,R4
        PUSH ACC
        MOV  A,R5
        PUSH ACC
        MOV  A,R6
        PUSH ACC
        MOV  A,R7
        PUSH ACC
        ;PUSH SP ;不必保存SP,任務(wù)切換時(shí)由相應(yīng)程序調(diào)整
        ENDM
   
POPALL    MACRO
        ;POP  ACC ;不必保存SP,任務(wù)切換時(shí)由相應(yīng)程序調(diào)整
        POP  ACC ;R0~R7出棧
        MOV  R7,A
        POP  ACC
        MOV  R6,A
        POP  ACC
        MOV  R5,A
        POP  ACC
        MOV  R4,A
        POP  ACC
        MOV  R3,A
        POP  ACC
        MOV  R2,A
        POP  ACC
        MOV  R1,A
        POP  ACC
        MOV  R0,A
        POP  DPH
        POP  DPL
        POP  B
        POP  ACC
        POP  PSW
        ENDM
   
;--------------------
;子程序
;--------------------


; --------------------------------------------------
; ---------------- OSStartHighRdy() ----------------
; --------------------------------------------------


        RSEG ?PR?OSStartHighRdy?OS_CPU_A


;調(diào)用用戶擴(kuò)展鉤子函數(shù)OSTaskSwHook()
;OSRunning=TRUE
;取得將要恢復(fù)的任務(wù)的堆棧指針:Stack pointer=OSTCBHighRdy->OSTCBStkPtr
;將所有寄存器內(nèi)容從任務(wù)棧中彈出來
;執(zhí)行中斷返回指令
OSStartHighRdy:


        USING 0 ;上電后51自動(dòng)關(guān)中斷,此處不必用CLR EA指令,因?yàn)榈酱颂庍未開中斷,本程序退出后,開中斷
        LCALL _?OSTaskSwHook
        
        ;OSRunning=TRUE
        MOV  R0,#LOW (OSRunning)
        MOV  @R0,#01


;--------------------
;OSCtxSw_in的功能流程:
;從將要執(zhí)行的任務(wù)的任務(wù)棧中獲取保存的系統(tǒng)棧現(xiàn)場的長度
;根據(jù)這個(gè)長度,從將要執(zhí)行的任務(wù)的任務(wù)棧中彈出系統(tǒng)棧的上一現(xiàn)場到系統(tǒng)棧,系統(tǒng)棧恢復(fù)完成,立即設(shè)置SP
;從將要執(zhí)行的任務(wù)的任務(wù)棧中彈出
;彈出任務(wù)切換函數(shù)OSCtxSw發(fā)生時(shí)的CPU現(xiàn)場到CPU寄存器
;--------------------

OSCtxSw_in:      ;找到要恢復(fù)的任務(wù)的任務(wù)棧TCB,并讀出要恢復(fù)的系統(tǒng)棧的長度


        ;OSTCBHighRdy ==> DPTR 獲得當(dāng)前就緒的最高優(yōu)先級任務(wù)的TCB指針.注:OSTCBHighRdy本身是個(gè)TCB指針
        MOV  R0,#LOW (OSTCBHighRdy) ;把指針變量OSTCBHighRdy的低地址=>R0,指針占3B。+0類型 +1高8位數(shù)據(jù) +2低8位數(shù)據(jù).
        INC  R0 ;
        MOV  DPH,@R0    ;全局變量OSTCBHighRdy在IDATA中;51為大端模式,u變量的低8位在高地址
        INC  R0
        MOV  DPL,@R0
;注意:指針變量OSTCBHighRdy占了3字節(jié),用匯編讀寫這個(gè)指針變量時(shí),建議先debug或仿真觀察一下,看看這個(gè)指針是否是占了3個(gè)字節(jié),有時(shí)keil編譯出的指針只占2個(gè)字節(jié)的地址信息,并不包含前文所述的第0字節(jié)的類型信息
;以上5行匯編用C表示:
;R0= (u8)(&OSTCBHighRdy);  //OSTCBHighRdy存放的地址內(nèi)容是U16的,但指針變量OSTCBHighRdy本身所處的地址是3 byte的
;R0++;
;DPH=*R0;
;R0++;
;DPL=*R0;
;截止到這里,相當(dāng)于執(zhí)行了C語言:DPTR= (uint16_t)OSTCBHighRdy;

        ;OSTCBHighRdy->OSTCBStkPtr ==> DPTR 獲得用戶堆棧指針。。為了把OSTCBHighRdy->OSTCBStkPtr 送入 DPTR,必須先找到OSTCBHighRdy,OSTCBHighRdy本身
;又是個(gè)地址,通過這個(gè)地址才能找到任務(wù)的TCB,進(jìn)而找到任務(wù)的棧頂OSTCBStkPtr
        INC  DPTR ;指針占3B。+0類型 +1高8位數(shù)據(jù) +2低8位數(shù)據(jù)。本行INC的目的是跳過第0字節(jié),第1、2 byte開始才是OSTCBStkPtr存放的棧頂?shù)刂?br />         MOVX A,@DPTR ;OSTCBStkPtr是void指針
        MOV  R0,A
        INC  DPTR
        MOVX A,@DPTR
        MOV  R1,A
        MOV  DPH,R0
        MOV  DPL,R1
;截止到這里,相當(dāng)于執(zhí)行了C語言:DPTR= (*DPTR).OSTCBStkPtr;//C語言取指向*DPTR,等價(jià)于匯編的取值@DPTR
;也即,相當(dāng)于:DPTR= =OSTCBHighRdy->OSTCBStkPtr;
  ;*UserStkPtr ==> R5 用戶堆棧起始地址內(nèi)容(即用戶堆棧長度放在此處,為什么用戶棧的起始處放的是用戶棧的長度?這個(gè)是人為的,放在起始處比較方便,見OS_CPU_C.c文件的圖示)   
        MOVX A,@DPTR ;用戶堆棧中是unsigned char類型數(shù)據(jù)     相當(dāng)于:A=*(OSTCBHighRdy->OSTCBStkPtr)
        MOV  R5,A ;R5=用戶堆棧長度  ?
   
        ;恢復(fù)現(xiàn)場堆棧內(nèi)容
        MOV  R0,#OSStkStart    ;這時(shí)R0中存放的是系統(tǒng)棧的棧底減1    注:減1是滿棧的特性


;--------------------
;restore_stack     51是sp++的滿增棧
;--------------------
;截至本行,DPTR中存放的是“目前搜索到的優(yōu)先級最高的任務(wù)的任務(wù)棧”的棧頂?shù)刂?br /> ;R0存放的是系統(tǒng)棧的棧底地址


restore_stack:     ;從任務(wù)棧中復(fù)制上次保存的系統(tǒng)棧內(nèi)容到系統(tǒng)棧
   
        INC  DPTR
        INC  R0
        MOVX A,@DPTR
        MOV  @R0,A
        DJNZ R5,restore_stack
;以上5行對應(yīng)的C如下:
; 在下面的C代碼中,DPTR、R0、R5都看做普通的指針變量
;DPTR=OSTCBHighRdy->OSTCBStkPtr;//用戶棧的棧頂
;R0= #OSStkStart = OSStack-1;//系統(tǒng)棧的棧底
;R5= OSTCBHighRdy->OSTCBStkPtr[0];//用戶棧中已占用的字節(jié)數(shù)?
;do
; {
;DPTR++;
;R0++;
;*R0 = *DPTR;//匯編中用了兩行:A= *DPTR;
;// *R0=A;    //把用戶棧的內(nèi)容從棧頂依次拷貝出R5個(gè)到系統(tǒng)棧棧底
;R5--;
; }while(R5 != 0);


        ;恢復(fù)堆棧指針SP   
        MOV  SP,R0   ;R0指向了系統(tǒng)棧已存入的最后一個(gè)數(shù),符合滿棧特性,直接給SP賦值即可
   
        ;恢復(fù)仿真堆棧指針?C_XBP        
        INC  DPTR
        MOVX A,@DPTR
        MOV  ?C_XBP,A ;?C_XBP 仿真堆棧指針高8位
        INC  DPTR
        MOVX A,@DPTR
        MOV  ?C_XBP+1,A ;?C_XBP 仿真堆棧指針低8位
  
        POPALL
        SETB EA ;開中斷
  RETI  ;RET和RETI有一個(gè)共同點(diǎn),就是都使硬件執(zhí)行了PC出棧指令,而RETI除了出棧PC,
;還清除了中斷狀態(tài)寄存器觸發(fā)器標(biāo)志,否則同優(yōu)先級的,和比本中斷優(yōu)先級還低的中斷講無法觸發(fā)。
;這個(gè)中斷狀態(tài)寄存器觸發(fā)器標(biāo)志無法使用軟件清除,即使用匯編也不行,只能由RETI來觸發(fā)硬件清除。


; --------------------------------------------------
; ------------------- OSCtxSw() --------------------
; --------------------------------------------------


        RSEG ?PR?OSCtxSw?OS_CPU_A


;保存處理器寄存器,即CPU現(xiàn)場
;將當(dāng)前任務(wù)的堆棧指針保存到當(dāng)前任務(wù)的OS_TCB中:OSTCBCur->OSTCBStkPtr=Stack pointer
;調(diào)用用戶擴(kuò)展函數(shù)OSTaskSwHook()
;OSTCBCur=OSTCBHighRdy
;OSPrioCur=OSPrioHighRdy
;得到需要恢復(fù)的任務(wù)的堆棧指針:Stack pointer=OSTCBHighRdy->OSTCBStkPtr
;將所有處理器寄存器從新任務(wù)的堆棧中恢復(fù)出來
;執(zhí)行中斷返回指令


OSCtxSw:  
  USING 0  
        PUSHALL     ;當(dāng)前任務(wù)進(jìn)行過程中執(zhí)行了OSCtxSw函數(shù),相當(dāng)于普通程序流程中發(fā)生中斷,
;需要立即保護(hù)CPU現(xiàn)場->PUSHALL,以及保護(hù)系統(tǒng)棧(必選)、仿真棧(可選,若仿真棧本身就定義在了各個(gè)任務(wù)棧中,就不必保存了)


;--------------------
;OSIntCtxSw_in
;--------------------
        
OSIntCtxSw_in:


        ;獲得系統(tǒng)堆棧長度和起始地址,任務(wù)棧結(jié)構(gòu)示意圖(見文件OS_CPU_C.C)
        MOV  A,SP
        CLR  C ;進(jìn)位標(biāo)志位Cy清零
        SUBB A,#OSStkStart ;A = A-OSStkStart-Cy
        MOV  R5,A     ;獲得系統(tǒng)堆棧長度到R5        
    ;R5=SP-OSStkStart;
   
        ;OSTCBCur ==> DPTR  獲得當(dāng)前TCB指針
        MOV  R0,#LOW (OSTCBCur) ;獲得OSTCBCur指針低地址,指針占3B。+0類型 +1高8位數(shù)據(jù) +2低8位數(shù)據(jù)
        INC  R0
        MOV  DPH,@R0 ;全局變量OSTCBCur在IDATA中
        INC  R0
        MOV  DPL,@R0
        ;DPTR=OSTCBCur;


   
        ;OSTCBCur->OSTCBStkPtr ==> DPTR  獲得用戶堆棧指針
        INC  DPTR        ;指針占3B。+0類型 +1高8位數(shù)據(jù) +2低8位數(shù)據(jù)
        MOVX A,@DPTR     ;OSTCBStkPtr是void指針
        MOV  R0,A
        INC  DPTR
        MOVX A,@DPTR
        MOV  R1,A
        MOV  DPH,R0
        MOV  DPL,R1
;DPTR=OSTCBCur->OSTCBStkPtr;


        
        ;保存硬件堆棧的長度
MOV  A,R5
        MOVX @DPTR,A
        ; *DPTR=R5;  相當(dāng)于:OSTCBCur->OSTCBStkPtr[0] = SP - OSStkStart;

        MOV  R0,#OSStkStart ;獲得系統(tǒng)堆棧起始地址


;--------------------
;save_stack
;--------------------


save_stack:
   
        INC  DPTR
        INC  R0
        MOV  A,@R0
        MOVX @DPTR,A
        DJNZ R5,save_stack
        
        ;保存仿真堆棧指針?C_XBP
        INC  DPTR
        MOV  A,?C_XBP ;?C_XBP 仿真堆棧指針高8位
        MOVX @DPTR,A
        INC  DPTR
        MOV  A,?C_XBP+1 ;?C_XBP 仿真堆棧指針低8位
        MOVX @DPTR,A        
   
        ;調(diào)用用戶程序
        LCALL _?OSTaskSwHook


        ;OSTCBCur = OSTCBHighRdy
        MOV  R0,#OSTCBCur
MOV  R1,#OSTCBHighRdy
MOV  A,@R1
        MOV  @R0,A
        INC  R0
INC  R1
MOV  A,@R1
        MOV  @R0,A
        INC  R0
INC  R1
MOV  A,@R1
        MOV  @R0,A
               
        ;OSPrioCur = OSPrioHighRdy 使用這兩個(gè)變量主要目的是為了使指針比較變?yōu)樽止?jié)比較,以便節(jié)省時(shí)間
        MOV  R0,#OSPrioCur
MOV  R1,#OSPrioHighRdy
MOV  A,@R1
        MOV  @R0,A
        
        LJMP OSCtxSw_in   ;本任務(wù)現(xiàn)場已保存完畢,跳去恢復(fù)下一任務(wù)的現(xiàn)場
; -------------------------------------------
; --------------- OSIntCtxSw() --------------
; -------------------------------------------


        RSEG ?PR?OSIntCtxSw?OS_CPU_A


;調(diào)整堆棧指針來去掉在調(diào)用過程中壓入堆棧的多余內(nèi)容
;將當(dāng)前任務(wù)堆棧指針保存到當(dāng)前任務(wù)的OS_TCB中:OSTCBCur->OSTCBStkPtr=Stack pointer
;調(diào)用用戶擴(kuò)展函數(shù)OSTaskSwHook()
;OSTCBCur=OSTCBHighRdy
;OSPrioCur=OSPrioHighRdy
;得到需要恢復(fù)的任務(wù)的堆棧指針:Stack pointer=OSTCBHighRdy->OSTCBStkPtr
;將所有處理器寄存器從新任務(wù)的堆棧中恢復(fù)出來
;執(zhí)行中斷返回指令
        
OSIntCtxSw:


        USING 0


;調(diào)整SP指針去掉在調(diào)用OSIntExit()、OSIntCtxSw()過程中壓入堆棧的多余內(nèi)容
;SP=SP-4
;為什么要調(diào)整SP呢?見本文件下面的注釋1。
MOV  A,SP
CLR  C
SUBB A,#4
MOV  SP,A


;LCALL _?OSTaskSwHook
        LJMP OSIntCtxSw_in

; -------------------------------------------
; --------------- OSTickISR() ---------------
; -------------------------------------------


        CSEG AT 000BH ;定時(shí)器T0中斷入口地址
;CSEG [AT 絕對地址表達(dá)式] //絕對代碼段
;DSEG [AT 絕對地址表達(dá)式] //內(nèi)部絕對數(shù)據(jù)段
;XSEG [AT 絕對地址表達(dá)式] //外部絕對數(shù)據(jù)段
;ISEG [AT 絕對地址表達(dá)式] //內(nèi)部間接尋址絕對數(shù)據(jù)段
;BSEG [AT 絕對地址表達(dá)式] //絕對位尋址段
        LJMP OSTickISR;中斷入口處絕對定位程序只有一條跳轉(zhuǎn)指令,跳到中斷服務(wù)函數(shù)中去

        RSEG ?PR?OSTickISR?OS_CPU_A


;關(guān)中斷
;保存處理器寄存器的值
;調(diào)用OSIntEnter()或是將OSIntNesting加1
;關(guān)時(shí)鐘中斷
;調(diào)用OSTimeTick()
;開時(shí)鐘中斷
;調(diào)用OSIntExit()
;恢復(fù)處理器寄存器的值
;重新允許中斷
;執(zhí)行中斷返回指令


OSTickISR:
        
        USING 0 ;工作寄存器0
        CLR  EA ;關(guān)中斷,防止中斷嵌套
        PUSHALL ;現(xiàn)場保護(hù)
        LCALL _?OSIntEnter ;通知內(nèi)核進(jìn)入中斷
              
CLR  TR0
        MOV  TH0,#TIMER_20MS_TH0 ;定義Tick=50次/秒,即0.02秒/次
        MOV  TL0,#TIMER_20MS_TL0 ;OS_CPU_C.C 和 OS_TICKS_PER_SEC
        LCALL _?OSTimeTick ;調(diào)用C語言的中斷服務(wù)子程序
SETB TR0


        LCALL _?OSIntExit ;通知內(nèi)核退出中斷
        POPALL ;恢復(fù)現(xiàn)場   
SETB EA ;開中斷   
        RETI
;上面定時(shí)器服務(wù)函數(shù)的調(diào)用鏈如下:
OSTickISR -> OSIntEnter
OSTickISR -> OSTimeTick


;--------------------
;SerialISR
;--------------------


        CSEG AT 0023H ;串口中斷。CSEG指代碼段絕對定位到23H(中斷向量表的串口中斷入口地址)
        LJMP SerialISR
        RSEG ?PR?_?SerialISR?OS_CPU_A
   
SerialISR:
USING 0
        CLR  EA ;關(guān)中斷,防止中斷嵌套
        PUSHALL
        LCALL _?OSIntEnter ;通知內(nèi)核進(jìn)入中斷
     
        LCALL _?Serial ;調(diào)用中斷服務(wù)子程序  
      
        LCALL _?OSIntExit ;通知內(nèi)核退出中斷
        POPALL
SETB EA
        RETI


;--------------------
END
;--------------------
;注釋1:
;為什么在中斷中進(jìn)行任務(wù)切換,需要調(diào)整SP?原因如下:
;任務(wù)切換的本質(zhì),無非就是,先從當(dāng)前任務(wù)的TCB中獲取當(dāng)前任務(wù)的任務(wù)棧指針OSTCBStkPtr,再把當(dāng)前任務(wù)的現(xiàn)場保存到這個(gè)指針處(只保存系統(tǒng)棧即可),
;然后從下一個(gè)任務(wù)的TCB讀取下一個(gè)任務(wù)的任務(wù)棧指針,從這個(gè)指針處把保存的系統(tǒng)棧現(xiàn)場彈到任務(wù)棧中去。在中斷中執(zhí)行任務(wù)切換(確切的說是在定時(shí)器中
;斷服務(wù)函數(shù)中執(zhí)行切換),那么本任務(wù)的現(xiàn)場應(yīng)該是在執(zhí)行中斷服務(wù)之前的那一條匯編語句時(shí)的現(xiàn)場,而不是進(jìn)入中斷后執(zhí)行OSIntCtxSw這個(gè)函數(shù)時(shí)的現(xiàn)場
;試想,如果我們保存的是進(jìn)入中斷后的現(xiàn)場,那么等這個(gè)任務(wù)再次被切回來時(shí),豈不是會(huì)回到中斷函數(shù)中!因?yàn)檫M(jìn)入中斷服務(wù)函數(shù)(甚至中斷服務(wù)函數(shù)又調(diào)用了其他
;函數(shù)且未被調(diào)函數(shù)尚未返回時(shí))后,中斷之前的PC、中斷函數(shù)調(diào)的函數(shù)的返回PC都會(huì)已經(jīng)被壓入SP系統(tǒng)棧了,所以,在中斷中切換,我們把進(jìn)入中斷時(shí)多壓入的幾次PC都不保存,這樣保存的系統(tǒng)棧
;才模仿出了進(jìn)入中斷前的現(xiàn)場。對于本工程來做個(gè)分析,首先定時(shí)中斷調(diào)用了服務(wù)函數(shù)OSTickISR,在進(jìn)入中斷函數(shù)前假設(shè)SP=a, 進(jìn)入中斷函數(shù)時(shí)PC被自動(dòng)壓棧一次,
;SP變成了a+2,(tip:51的PC是2字節(jié)),OSTickISR函數(shù)又調(diào)用了OSIntEnter函數(shù)、OSTimeTick函數(shù),這兩個(gè)函數(shù)在執(zhí)行OSIntCtxSw時(shí)都已經(jīng)返回了,所以SP還是a+2,
;OSTickISR函數(shù)又調(diào)用了OSIntExit函數(shù),進(jìn)入OSIntExit函數(shù)后,PC壓棧,SP變成了a+4,在OSIntExit函數(shù)中執(zhí)行了“中斷中的任務(wù)切換函數(shù)OSIntCtxSw”,所以在
;OSIntCtxSw函數(shù)中保存現(xiàn)場時(shí)的系統(tǒng)棧內(nèi)容為從(#?STACK)到(SP-4)。注:(#?STACK)為系統(tǒng)棧的棧底地址。

以上的Word格式文檔51黑下載地址:
51單片機(jī)ucos ii任務(wù)切換匯編代碼分析.docx (30.35 KB, 下載次數(shù): 15)



評分

參與人數(shù) 1黑幣 +50 收起 理由
admin + 50 共享資料的黑幣獎(jiǎng)勵(lì)!

查看全部評分

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏1 分享淘帖 頂 踩
回復(fù)

使用道具 舉報(bào)

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

手機(jī)版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表
主站蜘蛛池模板: 日韩一区不卡 | 水蜜桃久久夜色精品一区 | 久久精品 | 色屁屁在线观看 | 成人免费视频观看 | 日韩在线 | 久久999| 日韩成人av在线播放 | 在线天堂免费中文字幕视频 | 国产精品99久久久久久久久久久久 | 中文字幕第二区 | 青青激情网| 国产日韩欧美另类 | 精品一二区 | 天天射中文 | 黄色一级大片在线免费看产 | 国产香蕉视频在线播放 | 日韩精品成人免费观看视频 | 91在线观看免费视频 | 色综合一区二区三区 | 亚洲午夜精品久久久久久app | 天天做日日做 | 国产一区二区电影 | 国产精品99久久久久久动医院 | 特级生活片| 久久夜视频 | 国产美女在线看 | 久久99精品视频 | 天堂中文av | 伊人伊人伊人 | 亚洲欧洲精品成人久久奇米网 | 日韩在线观看中文字幕 | 一级毛片大全免费播放 | 亚洲福利在线观看 | 国产在线不卡视频 | 亚洲三区视频 | 天堂一区 | 久久99网站 | 国产视频中文字幕在线观看 | 黄网站涩免费蜜桃网站 | 亚洲一区在线观看视频 |