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

專注電子技術(shù)學(xué)習(xí)與研究
當(dāng)前位置:單片機教程網(wǎng) >> STM32 >> 瀏覽文章

ucos 0S_CPU_A.ASM(STM32)

作者:佚名   來源:本站原創(chuàng)   點擊數(shù):  更新時間:2014年04月27日   【字體:

 IMPORT  OSRunning;參數(shù)指示內(nèi)核是否運行的布爾型變量

        IMPORT  OSPrioCur;參數(shù)當(dāng)前任務(wù)的優(yōu)先級
        IMPORT  OSPrioHighRdy;參數(shù)優(yōu)先級最高任務(wù)的優(yōu)先級
        IMPORT  OSTCBCur;任務(wù)控制塊指針指向當(dāng)前正在運行的任務(wù)
        IMPORT  OSTCBHighRdy;任務(wù)控制塊指針指向最高優(yōu)先級任務(wù)的任務(wù)控制塊
        IMPORT  OSIntNesting;參數(shù)保存中斷嵌套級
        IMPORT  OSIntExit;函數(shù)退出軟中斷進行任務(wù)切換
        IMPORT  OSTaskSwHook;勾函數(shù)任務(wù)切換時運行自己的函數(shù)
;IMPORT外部文件定義的引入供本文件使用(輸入)  
;下面是六個需要自己編寫的匯編函數(shù)
        EXPORT  OSStartHighRdy;運行優(yōu)先級最高的函數(shù)供OSstart調(diào)用               
        EXPORT  OSCtxSw;任務(wù)切換函數(shù)
        EXPORT  OSIntCtxSw;中斷結(jié)束時進行任務(wù)切換供OSintexit調(diào)用
EXPORT  OS_CPU_SR_Save;OS_ENTER_CRITICAL()進入臨界中斷
    EXPORT  OS_CPU_SR_Restore;OS_EXIT_CRITICAL()退出臨界中斷        
        EXPORT  PendSV_Handler;
;EXPORT本文件定義的供外部文件引用(輸出)   
     
NVIC_INT_CTRL   EQU     0xE000ED04  ; 中斷控制及狀態(tài)寄存器ICSR    P135
NVIC_SYSPRI2     EQU     0xE000ED22  ; 系統(tǒng)優(yōu)先級寄存器   P132*寫錯?ED22?好像兩個都可以
NVIC_PENDSV_PRI EQU     0xFFFF0000  ; PendSV中斷和系統(tǒng)節(jié)拍中斷
                                        ; (都為最低,0xff).
NVIC_PENDSVSET   EQU     0x10000000  ; 觸發(fā)軟件中斷的值.掛起PENDSV
 
 
PRESERVE8;保證8字節(jié)對齊 
AREA    |.text|, CODE, READONLY;只讀代碼
        THUMB;16位THUMB指令
    
           
 
;********************************************************************************************************
;                                   CRITICAL SECTION METHOD 3 FUNCTIONS
;
; Description: Disable/Enable interrupts by preserving the state of interrupts.  Generally speaking you
;              would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then
;              disable interrupts.  'cpu_sr' is allocated in all of uC/OS-II's functions that need to
;              disable interrupts.  You would restore the interrupt disable state by copying back 'cpu_sr'
;              into the CPU's status register.
;
; Prototypes :     OS_CPU_SR  OS_CPU_SR_Save(void);
;                  void       OS_CPU_SR_Restore(OS_CPU_SR cpu_sr);
;OS_CPU_SR 大小取決于CPU狀態(tài)寄存器大小32位
;
; Note(s)    : 1) These functions are used in general like this:
;
;                 void Task (void *p_arg)
;                 {
;                 #if OS_CRITICAL_METHOD == 3          
;                     OS_CPU_SR  cpu_sr;
;                 #endif
;
;                          :
;                          :
;                     OS_ENTER_CRITICAL();            
;                          :
;                          :
;                     OS_EXIT_CRITICAL();              
;                          :
;                          :
;                 }
;********************************************************************************************************
;0S_CPU_A.ASM(STM32)這倆個函數(shù)是進出中斷延用的就是防止任務(wù)切換時被意外打斷
;0S_CPU_A.ASM(STM32)沒啥特別的開關(guān)中斷返回。
OS_CPU_SR_Save
    MRS     R0, PRIMASK   ;讀取PRIMASK到R0,R0為返回值 
    CPSID   I ;PRIMASK=1,關(guān)中斷(NMI和硬件FAULT可以響應(yīng))屏蔽所有可屏蔽異常
    BX      LR    ;返回
 
OS_CPU_SR_Restore
    MSR     PRIMASK, R0   ;讀取R0到PRIMASK中,R0為參數(shù)
    BX      LR ;返回
 
 
;0S_CPU_A.ASM(STM32)這個函數(shù)是一開始啟動時用的,設(shè)置PENDSV優(yōu)先級最低,這樣只有在沒有其他異常(中斷,事件)運行下進行掛起。  
;PendSV可懸起系統(tǒng)調(diào)用確保任務(wù)切換不會打斷中斷
OSStartHighRdy
        LDR     R4, =NVIC_SYSPRI2      ; set the PendSV exception priority
        LDR     R5, =NVIC_PENDSV_PRI   ;設(shè)置系統(tǒng)服務(wù)優(yōu)先級為最低優(yōu)先級
        STR     R5, [R4]               ;只有在沒有其他異常的情況下才會觸發(fā)系統(tǒng)服務(wù)中斷進行上下文切換
;0S_CPU_A.ASM(STM32)R4寫零這樣第一次運行在PendSV_Handler中將調(diào)用nosave函數(shù),psp一開始為零如果保存psp-32將為不確定值,退出中斷后會跑飛。
        
        MOV     R4, #0                 ; set the PSP to 0 for initial context switch call
        MSR     PSP, R4                ;設(shè)置進程堆棧寄存器為0為初始化上下文切換指令
;0S_CPU_A.ASM(STM32)告訴系統(tǒng)ucos初始化完畢可以啟動了
        LDR     R4, =OSRunning         ; OSRunning = TRUE
        MOV     R5, #1                 ;
        STRB    R5, [R4]               ;STRB位傳送指令
 
;0S_CPU_A.ASM(STM32)STM32有PENDSV 任務(wù)切換是在PENDSV完成的,所以這里要觸發(fā)PENDSV                                      
        LDR     R4, =NVIC_INT_CTRL     ;rigger the PendSV exception (causes context switch)
        LDR     R5, =NVIC_PENDSVSET    ;懸起PENDSV觸發(fā)系統(tǒng)調(diào)用中斷進行任務(wù)調(diào)度
        STR     R5, [R4]
 
        CPSIE   I                      ;enable interrupts at processor level快速開中斷
 
;0S_CPU_A.ASM(STM32)這個函數(shù)就是告訴你出錯了,系統(tǒng)崩潰的都會到這里
OSStartHang
        B       OSStartHang            ;should never get here好吧,正常的程序是不會跑到這里的。
 
;0S_CPU_A.ASM(STM32)管他是中斷切換還是任務(wù)切換,要做的就是觸發(fā)PENDSV
OSCtxSw
PUSH    {R4, R5}                ;PUSH    {R4, R5,LR}   
        LDR     R4, =NVIC_INT_CTRL   ;觸發(fā)PendSV異常 (causes context switch)
        LDR     R5, =NVIC_PENDSVSET
        STR     R5, [R4]
POP     {R4, R5}                ;POP     {R4, R5,PC}改成這樣可以省略BX
        BX      LR
        ;BX跳轉(zhuǎn)并改變指令集
;
 
OSIntCtxSw
PUSH    {R4, R5}
        LDR     R4, =NVIC_INT_CTRL      ;觸發(fā)PendSV異常 (causes context switch)
        LDR     R5, =NVIC_PENDSVSET
        STR     R5, [R4]
POP     {R4, R5}
        BX      LR
        NOP
 
;0S_CPU_A.ASM(STM32)這個就是任務(wù)切換的地方了,不能被打斷,所以先關(guān)中斷
 
PendSV_Handler
    CPSID   I                                                   ; Prevent interruption         ;during context switch 關(guān)閉中斷防止在切換任務(wù)時打斷任務(wù)切換
;0S_CPU_A.ASM(STM32)硬件仿真的時候進中斷都是用MSP 所以保存還是有必要的。                                                         
    MRS     R0, PSP                                             ; PSP is process stack pointer 如 ;果在用PSP堆棧,則可以忽略保存寄存器,參考CM3權(quán)威中的雙堆棧-白菜注
    CBZ     R0, PendSV_Handler_Nosave                         ; Skip register save the first time
;0S_CPU_A.ASM(STM32)如果PSP的值為零則運行PendSV_Handler_Nosave
    SUBS    R0, R0, #0x20                                       ; Save remaining regs r4-11 on process stack
;將PSP的值-32保存在R0 
    
    STM     R0, {R4-R11}                                        ;一個批量入棧操作將R4到R11全部保存在進程堆棧中地址保存在R0內(nèi)          
    ;MSR     MSP,R0                                             
    ;PUSH    {R4-R11}     
;0S_CPU_A.ASM(STM32) STM     R0, {R4-R11}   可以用上面兩句代替。上面一段把準(zhǔn)備被切掉的函數(shù)的寄存器R4-R7都保存了。
;0S_CPU_A.ASM(STM32) 因為其他寄存器都是自動保存的所以不要管。
LDR     R1, =OSTCBCur                                       ; OSTCBCur->OSTCBStkPtr = SP
;將OSTCBCur指針的地址保存在R1中
    LDR     R1, [R1]
;從R1中的地址處讀數(shù)據(jù)讀到得就是OSTCBCur指針存儲在R1中 
    STR     R0, [R1]  ; R0 is SP of process being switched out  R0是當(dāng)前進程堆棧的PSP指針即即將被切換任務(wù)的進程的PSP指針
;將R0中的數(shù)據(jù)(即PSP-32的值)存放在OSTCBCur指針指向的地址中
 
                                                                ; At this point, entire context of process has been saved
;0S_CPU_A.ASM(STM32)到這里進程的所有內(nèi)容都保存完畢保存了,包括R4-R11的值和舊的任務(wù)堆棧的PSP地址
;0S_CPU_A.ASM(STM32)這里郁悶了我好久,原來匯編沒有跳轉(zhuǎn)指令會按代碼順序一直運行下去。只要有運行PENDSV HANDLER,一定會運行NOSAVE.仿真時候發(fā)現(xiàn)的。
;0S_CPU_A.ASM(STM32)這里要調(diào)用一個C函數(shù),為了防止LR在C函數(shù)中被改必須要保存下。
PendSV_Handler_Nosave
    PUSH    {LR}                                               ; Save LR exc_return value
;將R14壓棧                                                  ;保存回調(diào)地址                               
    LDR     R0, =OSTaskSwHook                                   ; OSTaskSwHook();
;取勾函數(shù)名所在的地址
    BLX     R0
;0S_CPU_A.ASM(STM32)BLX 帶鏈接跳轉(zhuǎn)并切換指令集 用戶代碼都是ARM代碼
    POP     {R14}
    ;出棧
;0S_CPU_A.ASM(STM32)這一塊完成任務(wù)優(yōu)先級的變換,運行什么任務(wù)是OS判斷這個值決定的了。我之前一直以為這里會跳到將要
;0S_CPU_A.ASM(STM32)運行的任務(wù)
    LDR     R0, =OSPrioCur                                      ; OSPrioCur = OSPrioHighRdy
;將參數(shù)OSPrioCur的地址存在R0中  
    LDR     R1, =OSPrioHighRdy
;將參數(shù)OSPrioHighRdy的地址存放在R1中
    LDRB    R2, [R1]                                            ;R2中保存OSPrioHighRdy的值
;把R1地址中的數(shù)據(jù)取出來存在R2中
    STRB    R2, [R0]
    ;把R2中的數(shù)據(jù)存到R0地址對應(yīng)的內(nèi)存空間
;0S_CPU_A.ASM(STM32)任務(wù)換了任務(wù)控制塊也要換了
    LDR     R0, =OSTCBCur                                       ; OSTCBCur  = OSTCBHighRdy;
    LDR     R1, =OSTCBHighRdy
    LDR     R2, [R1]                                            ;R2中保存的是OSTCBHighRdy這個指針
    STR     R2, [R0]
    ;同上
;0S_CPU_A.ASM(STM32)新的任務(wù),有新的進程堆棧
    LDR     R0, [R2]                                            ; R0 is new process SP; SP = OSTCBHighRdy->OSTCBStkPtr;
;將R2地址中的數(shù)據(jù)存到R0中OSTCBHighRdy這個指針(將要運行任務(wù)的指針)
;0S_CPU_A.ASM(STM32)恢復(fù)新任務(wù)進程堆棧的值。
    LDM     R0, {R4-R11}                                        ; Restore r4-11 from new process stack
                                                          ;將R4-R11寄存器的值恢復(fù)到新進程的堆棧下
   ;POP{R4-R11}                                                 
   ;可以用這句替換上句
    ADDS    R0, R0, #0x20                                       ;+32得到新的PSP地址                        
    MSR     PSP, R0                                             ; Load PSP with new process SP
;0S_CPU_A.ASM(STM32)最后把PSP指向新的堆棧位置
;0S_CPU_A.ASM(STM32)到這里又把PSP指針,和R4-R7重新恢復(fù)了                                                          ;0S_CPU_A.ASM(STM32)下面這句應(yīng)該是為了防止意外吧,正常退出都會用PSP堆棧 
    ORR     LR, LR, #0x04                                       ; Ensure exception return uses process stack
;將LR的第二位置為1并保存到LR確保返回使用進程堆棧。
;0S_CPU_A.ASM(STM32)結(jié)束了,開中斷吧
    CPSIE   I                                                   ; 開中斷
;0S_CPU_A.ASM(STM32)記得跳轉(zhuǎn)
    BX      LR                                                  ; Exception return will restore remaining context
 
 end  
關(guān)閉窗口

相關(guān)文章

主站蜘蛛池模板: 日韩欧美视频免费在线观看 | 国产第一页在线观看 | 91av导航| 激情一区二区三区 | 欧美成人一区二区三区片免费 | 91视频免费 | 亚洲欧美一区二区三区国产精品 | 久久久久久国产精品免费免费 | 国内成人免费视频 | 国产精品一二三区 | 欧美日韩精品在线一区 | 久久久女 | 久久99久久久久 | 日日射夜夜骑 | 亚洲成人免费在线观看 | 99爱视频 | 狠狠干网站 | 人人看人人爽 | 亚洲精品在线看 | 国产精品一区二区在线 | 日韩www| 成人免费看片网 | 91免费观看国产 | 伊人影院在线观看 | 久久av网站| 北条麻妃99精品青青久久 | 久久久国产精品入口麻豆 | www.亚洲精品 | 性高湖久久久久久久久aaaaa | 成人在线播放网址 | 精品视频一区二区 | 91一区二区三区 | 日韩精品在线看 | 91精品国产综合久久福利软件 | 中文字幕日韩一区 | 天堂中文字幕av | 精品久久国产视频 | 亚洲三区在线观看 | 国产精品日韩一区二区 | 91最新入口 | 欧美视频精品 |