當(dāng)前位置:首頁 > 嵌入式 > 嵌入式軟件
[導(dǎo)讀] 1. μC/OS-Ⅱ概述 μC/OS-Ⅱ在特定處理器上的移植大部分工作集中在多任務(wù)切換的實(shí)現(xiàn)上,這部分代碼主要用來保存和恢復(fù)處理

1.    μC/OS-Ⅱ概述
  μC/OS-Ⅱ在特定處理器上的移植大部分工作集中在多任務(wù)切換的實(shí)現(xiàn)上,這部分代碼主要用來保存和恢復(fù)處理器的現(xiàn)場。但許多操作如讀/寫寄存器不能用C語言而只能用匯編來實(shí)現(xiàn)。
  將μC/OS-Ⅱ移植到ARM處理器上,只需要修改與處理器相關(guān)的3個(gè)文件: OS_CPU.H, OS_CPU_C.C, OS_CPU_A.ASM 。
2.    OS_CPU.H的移植
 1) 數(shù)據(jù)類型的定義
typedef  unsigned  char   BOOLEAN;
typedef  unsigned  char   INT8U;
typedef  signed    char   INT8S;
typedef  unsigned  short  INT16U;
typedef  signed    short  INT16S;
typedef  unsigned  int    INT32U;
typedef  signed    int    INT32S;
typedef  float            FP32;
typedef  double           FP64;
typedef  unsigned  int    OS_STK;
typedef  unsigned  int    OS_CPU_SR;
 2) ARM處理器相關(guān)的宏定義
#define  OS_ENTER_CRITICAL()  ARMDisableINT
#define  OS_EXIT_CRITICAL()   ARMEnableINT
 3) 堆棧增長方向的定義
#define  OS_STK_GROWTH        1
3.    OS_CPU_C.C的移植
 1)  任務(wù)椎棧初始化
任務(wù)椎棧初始化函數(shù)由OSTaskCreat()或OSTaskCreatEXT()調(diào)用,用來初始化任務(wù)并返回新的堆棧指針STK.初始狀態(tài)的堆棧模擬發(fā)生一次中斷后的堆棧結(jié)構(gòu),在ARM體系結(jié)構(gòu)下,任務(wù)堆??臻g由高到低將依次保存著PC,LR,R12…R0,CPSR,SPSR。堆棧初始化結(jié)束后,OSTaskSTKInit()返回新的堆棧棧頂指針OSTaskCreat()或OSTaskCreatEXT()將新的指針保存的OS_TCB中。
OS_STK *OSTaskStkInit (void (*task)(void *p_arg), void *p_arg, OS_STK *ptos, INT16U opt)
{
    OS_STK *stk;
    opt    = opt;           [!--empirenews.page--]  
    stk    = ptos;                
    *stk   = (OS_STK)task;    
    *--stk = 0;               
    *--stk = 0;               
    *--stk = 0;              
    *--stk = 0;              
    *--stk = 0;              
    *--stk = 0;              
    *--stk = 0;              
    *--stk = 0;              
    *--stk = 0;               
    *--stk = 0;               
    *--stk = 0;               
    *--stk = 0;               
    *--stk = 0;  [!--empirenews.page--]             
    *--stk = unsigned int pdata;
    *--stk = USER_USING_MODE|0X00;
    *--stk = 0;              
    return (stk);
}
 2)  系統(tǒng)Hook()函數(shù)
這些函數(shù)在特定的系統(tǒng)動作時(shí)被調(diào)用,允許執(zhí)行函數(shù)中的用戶代碼。這些函數(shù)默認(rèn)是空函數(shù),用戶根據(jù)實(shí)際情況添加相關(guān)代碼。
OSInitHookBegin()
OSInitHookEnd()
OSTaskCreateHook()
OSTaskDelHook()
OSTaskIdleHook()
OSTaskStatHook()
OSTaskStkInit()
OSTaskSwHook()
OSTCBInitHook()
OSTimeTickHook()
4.    OS_CPU_A.ASM的移植
1)    退出臨界區(qū)和進(jìn)入臨界區(qū)代碼
它們分別是退出臨界區(qū)和進(jìn)入臨界區(qū)代碼的宏實(shí)現(xiàn),主要用于在進(jìn)入臨界區(qū)之前關(guān)閉中斷,在退出臨界區(qū)后恢復(fù)原來的中斷狀態(tài)。
ARMDisableINT
        MRS     R0,CPSR                     ; Set IRQ and FIQ bits in CPSR to disable all interrupts
        ORR     R1,R0,#NO_INT
        MSR     CPSR_c,R1
        MRS     R1,CPSR                     ; Confirm that CPSR contains the proper interrupt disable flags
        AND     R1,R1,#NO_INT
        CMP     R1,#NO_INT
        BNE     OS_CPU_SR_Save              ; Not properly disabled (try again)
        BX   [!--empirenews.page--]   LR                          ; Disabled, return the original CPSR contents in R0
ARMEnableINT
       MSR     CPSR_c,R0
        BX      LR
2)    任務(wù)級任務(wù)切換
任務(wù)級任務(wù)切換函數(shù)OS_TasK_Sw()是當(dāng)前任務(wù)因?yàn)楸蛔枞鲃诱埱驝PU高度時(shí)被執(zhí)行的,由于此時(shí)的任務(wù)切換都是在非異常模式直進(jìn)行的,因此區(qū)別于中斷級別的任務(wù)切換。它的工作是先將當(dāng)前任務(wù)的CPU現(xiàn)場保存到該任務(wù)的堆棧中,然后獲得最高優(yōu)先級任務(wù)的堆棧指針,從該堆棧中恢復(fù)此任務(wù)的CPU現(xiàn)場,使之繼續(xù)運(yùn)行,從而完成任務(wù)切換。
OSCtxSw
                                        ; SAVE CURRENT TASK'S CONTEXT
        STMFD   SP!, {LR}               ; Push return address
        STMFD   SP!, {LR}
        STMFD   SP!, {R0-R12}           ; Push registers
        MRS     R4,  CPSR               ; Push current CPSR
        TST     LR, #1                  ; See if called from Thumb mode
        ORRNE   R4,  R4, #0x20          ; If yes, Set the T-bit
 [!--empirenews.page--]       STMFD   SP!, {R4}
        LDR     R4, OS_TCBCur           ; OSTCBCur->OSTCBStkPtr = SP;
        LDR     R5, [R4]
        STR     SP, [R5]
        LDR     R0,  OS_TaskSwHook      ; OSTaskSwHook();
        MOV     LR, PC
        BX      R0
        LDR     R4,  OS_PrioCur         ; OSPrioCur = OSPrioHighRdy
        LDR     R5,  OS_PrioHighRdy
        LDRB    R6, [R5]
        STRB    R6, [R4]
        LDR     R4, OS_TCBCur           ; OSTCBCur  = OSTCBHighRdy;
        LDR     R6, OS_TCBHighRdy
        LDR     R6, [R6]
        STR     R6, [R4]
        LDR     SP, [R6]        [!--empirenews.page--]        ; SP = OSTCBHighRdy->OSTCBStkPtr;

                                        ;STORE NEW TASK'S CONTEXT
        LDMFD   SP!, {R4}               ; Pop new task's CPSR
        MSR     SPSR_cxsf, R4
        LDMFD   SP!, {R0-R12,LR,PC}^    ; Pop new task's context
 3)  中斷級任務(wù)切換函數(shù)
  ① 該函數(shù)由OSIntExit()和OSExIntExit()調(diào)用,它若在時(shí)鐘中斷ISR中發(fā)現(xiàn)有高優(yōu)先級任務(wù)等特的時(shí)候信號到來,則需要在中斷退出后并不返回被中斷的,的而是直接調(diào)度就緒的高高優(yōu)先級任務(wù)執(zhí)行.這樣做的目的主要是能夠盡快的讓優(yōu)先級高的任務(wù)得到響應(yīng),進(jìn)而保證系統(tǒng)的實(shí)時(shí)性。
OSIntCtxSw
        LDR     R0, OS_TaskSwHook      ; OSTaskSwHook();
        MOV     LR, PC
        BX      R0
        LDR     R4, OS_PrioCur          ; OSPrioCur = OSPrioHighRdy
        LDR     R5, OS_PrioHighRdy
        LDRB    R6,[R5]
        STRB    R6,[R4]        
        LDR     R4,OS_TCBCur     [!--empirenews.page--]       ; OSTCBCur  = OSTCBHighRdy;
        LDR     R6,OS_TCBHighRdy
        LDR     R6,[R6]
        STR     R6,[R4]
        LDR     SP,[R6]                 ; SP = OSTCBHighRdy->OSTCBStkPtr;
                                        ; RESTORE NEW TASK'S CONTEXT
        LDMFD   SP!, {R4}               ; Pop new task's CPSR
        MSR     SPSR_cxsf, R4
        LDMFD   SP!, {R0-R12,LR,PC}^    ; Pop new task's context
 ② 兩種形式的中斷程序
OS_CPU_IRQ_ISR
        STMFD   SP!, {R1-R3}                   ; PUSH WORKING REGISTERS ONTO IRQ STACK
        MOV     R1, SP                         ; Save   IRQ stack pointer
        ADD    [!--empirenews.page--] SP, SP,#12                     ; Adjust IRQ stack pointer
        SUB     R2, LR,#4                      ; Adjust PC for return address to task
        MRS     R3, SPSR                       ; Copy SPSR (i.e. interrupted task's CPSR) to R3
        MSR     CPSR_c, #(NO_INT | SVC32_MODE) ; Change to SVC mode
                                               ; SAVE TASK'S CONTEXT ONTO TASK'S STACK
        STMFD   SP!, {R2}                      ; Push task's Return PC
        STMFD   SP!, {LR}                      ; Push task's LR
        STMFD   SP!, {R4-R12}                  ; Push task's R12-R4
        LDMFD   R1!, {R4-R6}   [!--empirenews.page--]                ; Move task's R1-R3 from IRQ stack to SVC stack
        STMFD   SP!, {R4-R6}
        STMFD   SP!, {R0}                      ; Push task's R0    onto task's stack
        STMFD   SP!, {R3}                      ; Push task's CPSR (i.e. IRQ's SPSR)                                             
        LDR     R0,   OS_IntNesting            ; OSIntNesting++;
        LDRB    R1, [R0]
        ADD     R1, R1,#1
        STRB    R1, [R0]
        CMP     R1, #1                         ; if (OSIntNesting == 1) {
        BNE     OS_CPU_IRQ_ISR_1
       [!--empirenews.page--] LDR     R4,  OS_TCBCur                 ; OSTCBCur->OSTCBStkPtr = SP
        LDR     R5, [R4]
        STR     SP, [R5]                       ; }
OS_CPU_IRQ_ISR_1
        MSR     CPSR_c, #(NO_INT | IRQ32_MODE) ; Change to IRQ mode (to use the IRQ stack to handle interrupt)
        LDR     R0,  OS_CPU_IRQ_ISR_Handler    ; OS_CPU_IRQ_ISR_Handler();
        MOV     LR, PC
        BX      R0         
        MSR     CPSR_c, #(NO_INT | SVC32_MODE) ; Change to SVC mode
        LDR     R0,  OS_IntExit                ; OSIntExit();
        MOV     LR, PC
        BX      R0                             ; RESTORE NEW TASK'S CONTEXT
        LDMFD   SP!, {R4}    [!--empirenews.page--]                  ; Pop new task's CPSR
        MSR     SPSR_cxsf, R4
        LDMFD   SP!, {R0-R12,LR,PC}^           ; Pop new task's context
        RSEG CODE:CODE:NOROOT(2)
        CODE32
OS_CPU_FIQ_ISR
        STMFD   SP!, {R1-R3}                   ; PUSH WORKING REGISTERS ONTO FIQ STACK
        MOV     R1, SP                         ; Save   FIQ stack pointer
        ADD     SP, SP,#12                     ; Adjust FIQ stack pointer
        SUB     R2, LR,#4                      ; Adjust PC for return address to task
        MRS     R3, SPSR                       ; Copy SPSR (i.e. interrupted task's CPSR) to R3
        MSR     CPSR_c, #(NO_INT | SVC32_MODE) ; Change to SVC mode
 [!--empirenews.page--]                                              ; SAVE TASK'S CONTEXT ONTO TASK'S STACK
        STMFD   SP!, {R2}                      ; Push task's Return PC
        STMFD   SP!, {LR}                      ; Push task's LR
        STMFD   SP!, {R4-R12}                  ; Push task's R12-R4
        LDMFD   R1!, {R4-R6}                   ; Move task's R1-R3 from FIQ stack to SVC stack
        STMFD   SP!, {R4-R6}
        STMFD   SP!, {R0}                      ; Push task's R0    onto task's stack
        STMFD   SP!, {R3}                      ; Push task's CPSR (i.e. FIQ's SPSR)
            [!--empirenews.page--]                                   ; HANDLE NESTING COUNTER
        LDR     R0, OS_IntNesting              ; OSIntNesting++;
        LDRB    R1, [R0]
        ADD     R1, R1,#1
        STRB    R1, [R0]
        CMP     R1, #1                         ; if (OSIntNesting == 1){
        BNE     OS_CPU_FIQ_ISR_1
        LDR     R4, OS_TCBCur                  ; OSTCBCur->OSTCBStkPtr = SP
        LDR     R5, [R4]
        STR     SP, [R5]                       ; }
OS_CPU_FIQ_ISR_1
        MSR     CPSR_c, #(NO_INT | FIQ32_MODE) ; Change to FIQ mode (to use the FIQ stack to handle interrupt)
        LDR     R0, ??OS_CPU_FIQ_ISR_Handler  [!--empirenews.page--] ; OS_CPU_FIQ_ISR_Handler();
        MOV     LR, PC
        BX      R0
        MSR     CPSR_c, #(NO_INT | SVC32_MODE) ; Change to SVC mode
        LDR     R0,  OS_IntExit                 ; OSIntExit();
        MOV     LR, PC
        BX      R0                             ; RESTORE NEW TASK'S CONTEXT
        LDMFD   SP!, {R4}                      ; Pop new task's CPSR
        MSR     SPSR_cxsf, R4
        LDMFD   SP!, {R0-R12,LR,PC}^           ; Pop new task's context
 4) OSStartHighRdy()函數(shù)
該函數(shù)是在OSStart()多任務(wù)啟動后,負(fù)責(zé)從最高優(yōu)先級任務(wù)的TCB控制塊中獲得該任務(wù)的堆棧指針SP通過SP依次將CPU現(xiàn)場恢復(fù)。這時(shí)系統(tǒng)就將控制權(quán)交給用戶創(chuàng)建的該任務(wù)進(jìn)程,直到該任務(wù)被阻塞或者被更高優(yōu)先級的任務(wù)搶占CPU。該函數(shù)僅僅在多任務(wù)啟動時(shí)被執(zhí)行一次,用來啟動第一個(gè)也即最高優(yōu)先級任務(wù)。
OSStartHighRdy  
        MSR     CPSR_cxsf, #0xD3        ; Switch to SVC mode with IRQ and FIQ disabled
        LDR     R0, ??OS_TaskSwHook   [!--empirenews.page--]  ; OSTaskSwHook();
        MOV     LR, PC
        BX      R0
        LDR     R4,  OS_Running         ; OSRunning = TRUE
        MOV     R5, #1
        STRB    R5, [R4]
                                        ; SWITCH TO HIGHEST PRIORITY TASK
        LDR     R4,  OS_TCBHighRdy         Get highest priority task TCB address
        LDR     R4, [R4]                   get stack pointer
        LDR     SP, [R4]                   switch to the new stack
        LDR     R4,  [SP], #4              pop new task's CPSR
        MSR     SPSR_cxsf,R4
        LDMFD  [!--empirenews.page--] SP!, {R0-R12,LR,PC}^       pop new task's context     
2.  多任務(wù)應(yīng)用程序的編寫
 1)  C語言入口函數(shù)
函數(shù)Main()為C語言入口函數(shù),所有C程序從這里開始運(yùn)行,在該函數(shù)中進(jìn)行如下操作:
③    調(diào)用函數(shù)ARMTaskgetInit初始化ARM處理器
④    調(diào)用OSInit初始化系統(tǒng)
⑤    調(diào)用OSTaskCreat函數(shù)創(chuàng)建任務(wù):Task1和Task2
⑥    調(diào)用ARMTaskgetStart函數(shù)啟動時(shí)鐘節(jié)拍中斷
⑦    調(diào)用OSStart啟動系統(tǒng)任務(wù)調(diào)度
#i nclude “config.h”
OS_STK  TaskStartStk[TASK_STK_SIZE];
OS_STK  TaskStk[TASK_STK_SIZE];
int Main(void){
    OSInit();
    OSTaskCreate(Task1,(void*)0,&TaskStartStk[TASK_STK_SIZE-1],0);
    OSStart();
    return();
}
 2) 任務(wù)處理函數(shù)
①   Task1
void Task1(void *pdata){
    pdata=pdata;
    TargetInit();
    For(;;){
        OSTimeDly(OS_TICKS_PER_SEC/50);
        If(GetKey()!=KEY1)    {
            continue;
        }
        OSTaskCreate(Task2,(void *)0,&TaskStk[TASK_STK_SIZE-1],10);
        While(GetKey()!=0)    {
            OSTimeDly(OS_TICKS_PER_SEC/50);
}
}
}
②   Task2
void Task2(void *pdata){
        pdata=pdata;
        BeeMoo();
OSTimeDly(OS_TICKS_PER_SEC/8);
        BeeMoo();
OSTimeDly(OS_TICKS_PER_SEC/4);
        BeeMoo();
OSTimeDly(OS_TICKS_PER_SEC/8);
     [!--empirenews.page--]   OSTaskDel(OS_PRIO_SELF);
}
本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請及時(shí)聯(lián)系本站刪除。
換一批
延伸閱讀

9月2日消息,不造車的華為或?qū)⒋呱龈蟮莫?dú)角獸公司,隨著阿維塔和賽力斯的入局,華為引望愈發(fā)顯得引人矚目。

關(guān)鍵字: 阿維塔 塞力斯 華為

加利福尼亞州圣克拉拉縣2024年8月30日 /美通社/ -- 數(shù)字化轉(zhuǎn)型技術(shù)解決方案公司Trianz今天宣布,該公司與Amazon Web Services (AWS)簽訂了...

關(guān)鍵字: AWS AN BSP 數(shù)字化

倫敦2024年8月29日 /美通社/ -- 英國汽車技術(shù)公司SODA.Auto推出其旗艦產(chǎn)品SODA V,這是全球首款涵蓋汽車工程師從創(chuàng)意到認(rèn)證的所有需求的工具,可用于創(chuàng)建軟件定義汽車。 SODA V工具的開發(fā)耗時(shí)1.5...

關(guān)鍵字: 汽車 人工智能 智能驅(qū)動 BSP

北京2024年8月28日 /美通社/ -- 越來越多用戶希望企業(yè)業(yè)務(wù)能7×24不間斷運(yùn)行,同時(shí)企業(yè)卻面臨越來越多業(yè)務(wù)中斷的風(fēng)險(xiǎn),如企業(yè)系統(tǒng)復(fù)雜性的增加,頻繁的功能更新和發(fā)布等。如何確保業(yè)務(wù)連續(xù)性,提升韌性,成...

關(guān)鍵字: 亞馬遜 解密 控制平面 BSP

8月30日消息,據(jù)媒體報(bào)道,騰訊和網(wǎng)易近期正在縮減他們對日本游戲市場的投資。

關(guān)鍵字: 騰訊 編碼器 CPU

8月28日消息,今天上午,2024中國國際大數(shù)據(jù)產(chǎn)業(yè)博覽會開幕式在貴陽舉行,華為董事、質(zhì)量流程IT總裁陶景文發(fā)表了演講。

關(guān)鍵字: 華為 12nm EDA 半導(dǎo)體

8月28日消息,在2024中國國際大數(shù)據(jù)產(chǎn)業(yè)博覽會上,華為常務(wù)董事、華為云CEO張平安發(fā)表演講稱,數(shù)字世界的話語權(quán)最終是由生態(tài)的繁榮決定的。

關(guān)鍵字: 華為 12nm 手機(jī) 衛(wèi)星通信

要點(diǎn): 有效應(yīng)對環(huán)境變化,經(jīng)營業(yè)績穩(wěn)中有升 落實(shí)提質(zhì)增效舉措,毛利潤率延續(xù)升勢 戰(zhàn)略布局成效顯著,戰(zhàn)新業(yè)務(wù)引領(lǐng)增長 以科技創(chuàng)新為引領(lǐng),提升企業(yè)核心競爭力 堅(jiān)持高質(zhì)量發(fā)展策略,塑強(qiáng)核心競爭優(yōu)勢...

關(guān)鍵字: 通信 BSP 電信運(yùn)營商 數(shù)字經(jīng)濟(jì)

北京2024年8月27日 /美通社/ -- 8月21日,由中央廣播電視總臺與中國電影電視技術(shù)學(xué)會聯(lián)合牽頭組建的NVI技術(shù)創(chuàng)新聯(lián)盟在BIRTV2024超高清全產(chǎn)業(yè)鏈發(fā)展研討會上宣布正式成立。 活動現(xiàn)場 NVI技術(shù)創(chuàng)新聯(lián)...

關(guān)鍵字: VI 傳輸協(xié)議 音頻 BSP

北京2024年8月27日 /美通社/ -- 在8月23日舉辦的2024年長三角生態(tài)綠色一體化發(fā)展示范區(qū)聯(lián)合招商會上,軟通動力信息技術(shù)(集團(tuán))股份有限公司(以下簡稱"軟通動力")與長三角投資(上海)有限...

關(guān)鍵字: BSP 信息技術(shù)
關(guān)閉
關(guān)閉