<acronym id="xonnx"></acronym>
      <td id="xonnx"></td>
    1. <pre id="xonnx"></pre>

      1. 專注電子技術學習與研究
        當前位置:單片機教程網 >> STM32 >> 瀏覽文章

        ucos 0S_CPU_A.ASM(STM32)

        作者:佚名   來源:本站原創   點擊數:  更新時間:2014年04月27日   【字體:

         IMPORT  OSRunning;參數指示內核是否運行的布爾型變量

                IMPORT  OSPrioCur;參數當前任務的優先級
                IMPORT  OSPrioHighRdy;參數優先級最高任務的優先級
                IMPORT  OSTCBCur;任務控制塊指針指向當前正在運行的任務
                IMPORT  OSTCBHighRdy;任務控制塊指針指向最高優先級任務的任務控制塊
                IMPORT  OSIntNesting;參數保存中斷嵌套級
                IMPORT  OSIntExit;函數退出軟中斷進行任務切換
                IMPORT  OSTaskSwHook;勾函數任務切換時運行自己的函數
        ;IMPORT外部文件定義的引入供本文件使用(輸入)  
        ;下面是六個需要自己編寫的匯編函數
                EXPORT  OSStartHighRdy;運行優先級最高的函數供OSstart調用               
                EXPORT  OSCtxSw;任務切換函數
                EXPORT  OSIntCtxSw;中斷結束時進行任務切換供OSintexit調用
        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  ; 中斷控制及狀態寄存器ICSR    P135
        NVIC_SYSPRI2     EQU     0xE000ED22  ; 系統優先級寄存器   P132*寫錯?ED22?好像兩個都可以
        NVIC_PENDSV_PRI EQU     0xFFFF0000  ; PendSV中斷和系統節拍中斷
                                                ; (都為最低,0xff).
        NVIC_PENDSVSET   EQU     0x10000000  ; 觸發軟件中斷的值.掛起PENDSV
         
         
        PRESERVE8;保證8字節對齊 
        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狀態寄存器大小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)這倆個函數是進出中斷延用的就是防止任務切換時被意外打斷
        ;0S_CPU_A.ASM(STM32)沒啥特別的開關中斷返回。
        OS_CPU_SR_Save
            MRS     R0, PRIMASK   ;讀取PRIMASK到R0,R0為返回值 
            CPSID   I ;PRIMASK=1,關中斷(NMI和硬件FAULT可以響應)屏蔽所有可屏蔽異常
            BX      LR    ;返回
         
        OS_CPU_SR_Restore
            MSR     PRIMASK, R0   ;讀取R0到PRIMASK中,R0為參數
            BX      LR ;返回
         
         
        ;0S_CPU_A.ASM(STM32)這個函數是一開始啟動時用的,設置PENDSV優先級最低,這樣只有在沒有其他異常(中斷,事件)運行下進行掛起。  
        ;PendSV可懸起系統調用確保任務切換不會打斷中斷
        OSStartHighRdy
                LDR     R4, =NVIC_SYSPRI2      ; set the PendSV exception priority
                LDR     R5, =NVIC_PENDSV_PRI   ;設置系統服務優先級為最低優先級
                STR     R5, [R4]               ;只有在沒有其他異常的情況下才會觸發系統服務中斷進行上下文切換
        ;0S_CPU_A.ASM(STM32)R4寫零這樣第一次運行在PendSV_Handler中將調用nosave函數,psp一開始為零如果保存psp-32將為不確定值,退出中斷后會跑飛。
                
                MOV     R4, #0                 ; set the PSP to 0 for initial context switch call
                MSR     PSP, R4                ;設置進程堆棧寄存器為0為初始化上下文切換指令
        ;0S_CPU_A.ASM(STM32)告訴系統ucos初始化完畢可以啟動了
                LDR     R4, =OSRunning         ; OSRunning = TRUE
                MOV     R5, #1                 ;
                STRB    R5, [R4]               ;STRB位傳送指令
         
        ;0S_CPU_A.ASM(STM32)STM32有PENDSV 任務切換是在PENDSV完成的,所以這里要觸發PENDSV                                      
                LDR     R4, =NVIC_INT_CTRL     ;rigger the PendSV exception (causes context switch)
                LDR     R5, =NVIC_PENDSVSET    ;懸起PENDSV觸發系統調用中斷進行任務調度
                STR     R5, [R4]
         
                CPSIE   I                      ;enable interrupts at processor level快速開中斷
         
        ;0S_CPU_A.ASM(STM32)這個函數就是告訴你出錯了,系統崩潰的都會到這里
        OSStartHang
                B       OSStartHang            ;should never get here好吧,正常的程序是不會跑到這里的。
         
        ;0S_CPU_A.ASM(STM32)管他是中斷切換還是任務切換,要做的就是觸發PENDSV
        OSCtxSw
        PUSH    {R4, R5}                ;PUSH    {R4, R5,LR}   
                LDR     R4, =NVIC_INT_CTRL   ;觸發PendSV異常 (causes context switch)
                LDR     R5, =NVIC_PENDSVSET
                STR     R5, [R4]
        POP     {R4, R5}                ;POP     {R4, R5,PC}改成這樣可以省略BX
                BX      LR
                ;BX跳轉并改變指令集
        ;
         
        OSIntCtxSw
        PUSH    {R4, R5}
                LDR     R4, =NVIC_INT_CTRL      ;觸發PendSV異常 (causes context switch)
                LDR     R5, =NVIC_PENDSVSET
                STR     R5, [R4]
        POP     {R4, R5}
                BX      LR
                NOP
         
        ;0S_CPU_A.ASM(STM32)這個就是任務切換的地方了,不能被打斷,所以先關中斷
         
        PendSV_Handler
            CPSID   I                                                   ; Prevent interruption         ;during context switch 關閉中斷防止在切換任務時打斷任務切換
        ;0S_CPU_A.ASM(STM32)硬件仿真的時候進中斷都是用MSP 所以保存還是有必要的。                                                         
            MRS     R0, PSP                                             ; PSP is process stack pointer 如 ;果在用PSP堆棧,則可以忽略保存寄存器,參考CM3權威中的雙堆棧-白菜注
            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內          
            ;MSR     MSP,R0                                             
            ;PUSH    {R4-R11}     
        ;0S_CPU_A.ASM(STM32) STM     R0, {R4-R11}   可以用上面兩句代替。上面一段把準備被切掉的函數的寄存器R4-R7都保存了。
        ;0S_CPU_A.ASM(STM32) 因為其他寄存器都是自動保存的所以不要管。
        LDR     R1, =OSTCBCur                                       ; OSTCBCur->OSTCBStkPtr = SP
        ;將OSTCBCur指針的地址保存在R1中
            LDR     R1, [R1]
        ;從R1中的地址處讀數據讀到得就是OSTCBCur指針存儲在R1中 
            STR     R0, [R1]  ; R0 is SP of process being switched out  R0是當前進程堆棧的PSP指針即即將被切換任務的進程的PSP指針
        ;將R0中的數據(即PSP-32的值)存放在OSTCBCur指針指向的地址中
         
                                                                        ; At this point, entire context of process has been saved
        ;0S_CPU_A.ASM(STM32)到這里進程的所有內容都保存完畢保存了,包括R4-R11的值和舊的任務堆棧的PSP地址
        ;0S_CPU_A.ASM(STM32)這里郁悶了我好久,原來匯編沒有跳轉指令會按代碼順序一直運行下去。只要有運行PENDSV HANDLER,一定會運行NOSAVE.仿真時候發現的。
        ;0S_CPU_A.ASM(STM32)這里要調用一個C函數,為了防止LR在C函數中被改必須要保存下。
        PendSV_Handler_Nosave
            PUSH    {LR}                                               ; Save LR exc_return value
        ;將R14壓棧                                                  ;保存回調地址                               
            LDR     R0, =OSTaskSwHook                                   ; OSTaskSwHook();
        ;取勾函數名所在的地址
            BLX     R0
        ;0S_CPU_A.ASM(STM32)BLX 帶鏈接跳轉并切換指令集 用戶代碼都是ARM代碼
            POP     {R14}
            ;出棧
        ;0S_CPU_A.ASM(STM32)這一塊完成任務優先級的變換,運行什么任務是OS判斷這個值決定的了。我之前一直以為這里會跳到將要
        ;0S_CPU_A.ASM(STM32)運行的任務
            LDR     R0, =OSPrioCur                                      ; OSPrioCur = OSPrioHighRdy
        ;將參數OSPrioCur的地址存在R0中  
            LDR     R1, =OSPrioHighRdy
        ;將參數OSPrioHighRdy的地址存放在R1中
            LDRB    R2, [R1]                                            ;R2中保存OSPrioHighRdy的值
        ;把R1地址中的數據取出來存在R2中
            STRB    R2, [R0]
            ;把R2中的數據存到R0地址對應的內存空間
        ;0S_CPU_A.ASM(STM32)任務換了任務控制塊也要換了
            LDR     R0, =OSTCBCur                                       ; OSTCBCur  = OSTCBHighRdy;
            LDR     R1, =OSTCBHighRdy
            LDR     R2, [R1]                                            ;R2中保存的是OSTCBHighRdy這個指針
            STR     R2, [R0]
            ;同上
        ;0S_CPU_A.ASM(STM32)新的任務,有新的進程堆棧
            LDR     R0, [R2]                                            ; R0 is new process SP; SP = OSTCBHighRdy->OSTCBStkPtr;
        ;將R2地址中的數據存到R0中OSTCBHighRdy這個指針(將要運行任務的指針)
        ;0S_CPU_A.ASM(STM32)恢復新任務進程堆棧的值。
            LDM     R0, {R4-R11}                                        ; Restore r4-11 from new process stack
                                                                  ;將R4-R11寄存器的值恢復到新進程的堆棧下
           ;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重新恢復了                                                          ;0S_CPU_A.ASM(STM32)下面這句應該是為了防止意外吧,正常退出都會用PSP堆棧 
            ORR     LR, LR, #0x04                                       ; Ensure exception return uses process stack
        ;將LR的第二位置為1并保存到LR確保返回使用進程堆棧。
        ;0S_CPU_A.ASM(STM32)結束了,開中斷吧
            CPSIE   I                                                   ; 開中斷
        ;0S_CPU_A.ASM(STM32)記得跳轉
            BX      LR                                                  ; Exception return will restore remaining context
         
         end  
        關閉窗口

        相關文章

        欧美性色欧美精品视频,99热这里只有精品mp4,日韩高清亚洲日韩精品一区二区,2020国自产拍精品高潮