www.久久久久|狼友网站av天堂|精品国产无码a片|一级av色欲av|91在线播放视频|亚洲无码主播在线|国产精品草久在线|明星AV网站在线|污污内射久久一区|婷婷综合视频网站

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

1.    μC/OS-Ⅱ概述
  μC/OS-Ⅱ在特定處理器上的移植大部分工作集中在多任務切換的實現(xiàn)上,這部分代碼主要用來保存和恢復處理器的現(xiàn)場。但許多操作如讀/寫寄存器不能用C語言而只能用匯編來實現(xiàn)。
  將μC/OS-Ⅱ移植到ARM處理器上,只需要修改與處理器相關的3個文件: 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處理器相關的宏定義
#define  OS_ENTER_CRITICAL()  ARMDisableINT
#define  OS_EXIT_CRITICAL()   ARMEnableINT
 3) 堆棧增長方向的定義
#define  OS_STK_GROWTH        1
3.    OS_CPU_C.C的移植
 1)  任務椎棧初始化
任務椎棧初始化函數(shù)由OSTaskCreat()或OSTaskCreatEXT()調(diào)用,用來初始化任務并返回新的堆棧指針STK.初始狀態(tài)的堆棧模擬發(fā)生一次中斷后的堆棧結(jié)構(gòu),在ARM體系結(jié)構(gòu)下,任務堆??臻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)動作時被調(diào)用,允許執(zhí)行函數(shù)中的用戶代碼。這些函數(shù)默認是空函數(shù),用戶根據(jù)實際情況添加相關代碼。
OSInitHookBegin()
OSInitHookEnd()
OSTaskCreateHook()
OSTaskDelHook()
OSTaskIdleHook()
OSTaskStatHook()
OSTaskStkInit()
OSTaskSwHook()
OSTCBInitHook()
OSTimeTickHook()
4.    OS_CPU_A.ASM的移植
1)    退出臨界區(qū)和進入臨界區(qū)代碼
它們分別是退出臨界區(qū)和進入臨界區(qū)代碼的宏實現(xiàn),主要用于在進入臨界區(qū)之前關閉中斷,在退出臨界區(qū)后恢復原來的中斷狀態(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)    任務級任務切換
任務級任務切換函數(shù)OS_TasK_Sw()是當前任務因為被阻塞而主動請求CPU高度時被執(zhí)行的,由于此時的任務切換都是在非異常模式直進行的,因此區(qū)別于中斷級別的任務切換。它的工作是先將當前任務的CPU現(xiàn)場保存到該任務的堆棧中,然后獲得最高優(yōu)先級任務的堆棧指針,從該堆棧中恢復此任務的CPU現(xiàn)場,使之繼續(xù)運行,從而完成任務切換。
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)  中斷級任務切換函數(shù)
  ① 該函數(shù)由OSIntExit()和OSExIntExit()調(diào)用,它若在時鐘中斷ISR中發(fā)現(xiàn)有高優(yōu)先級任務等特的時候信號到來,則需要在中斷退出后并不返回被中斷的,的而是直接調(diào)度就緒的高高優(yōu)先級任務執(zhí)行.這樣做的目的主要是能夠盡快的讓優(yōu)先級高的任務得到響應,進而保證系統(tǒng)的實時性。
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()多任務啟動后,負責從最高優(yōu)先級任務的TCB控制塊中獲得該任務的堆棧指針SP通過SP依次將CPU現(xiàn)場恢復。這時系統(tǒng)就將控制權交給用戶創(chuàng)建的該任務進程,直到該任務被阻塞或者被更高優(yōu)先級的任務搶占CPU。該函數(shù)僅僅在多任務啟動時被執(zhí)行一次,用來啟動第一個也即最高優(yōu)先級任務。
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.  多任務應用程序的編寫
 1)  C語言入口函數(shù)
函數(shù)Main()為C語言入口函數(shù),所有C程序從這里開始運行,在該函數(shù)中進行如下操作:
③    調(diào)用函數(shù)ARMTaskgetInit初始化ARM處理器
④    調(diào)用OSInit初始化系統(tǒng)
⑤    調(diào)用OSTaskCreat函數(shù)創(chuàng)建任務:Task1和Task2
⑥    調(diào)用ARMTaskgetStart函數(shù)啟動時鐘節(jié)拍中斷
⑦    調(diào)用OSStart啟動系統(tǒng)任務調(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) 任務處理函數(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);
}
本站聲明: 本文章由作者或相關機構(gòu)授權發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點,本站亦不保證或承諾內(nèi)容真實性等。需要轉(zhuǎn)載請聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權益,請及時聯(lián)系本站刪除。
換一批
延伸閱讀

LED驅(qū)動電源的輸入包括高壓工頻交流(即市電)、低壓直流、高壓直流、低壓高頻交流(如電子變壓器的輸出)等。

關鍵字: 驅(qū)動電源

在工業(yè)自動化蓬勃發(fā)展的當下,工業(yè)電機作為核心動力設備,其驅(qū)動電源的性能直接關系到整個系統(tǒng)的穩(wěn)定性和可靠性。其中,反電動勢抑制與過流保護是驅(qū)動電源設計中至關重要的兩個環(huán)節(jié),集成化方案的設計成為提升電機驅(qū)動性能的關鍵。

關鍵字: 工業(yè)電機 驅(qū)動電源

LED 驅(qū)動電源作為 LED 照明系統(tǒng)的 “心臟”,其穩(wěn)定性直接決定了整個照明設備的使用壽命。然而,在實際應用中,LED 驅(qū)動電源易損壞的問題卻十分常見,不僅增加了維護成本,還影響了用戶體驗。要解決這一問題,需從設計、生...

關鍵字: 驅(qū)動電源 照明系統(tǒng) 散熱

根據(jù)LED驅(qū)動電源的公式,電感內(nèi)電流波動大小和電感值成反比,輸出紋波和輸出電容值成反比。所以加大電感值和輸出電容值可以減小紋波。

關鍵字: LED 設計 驅(qū)動電源

電動汽車(EV)作為新能源汽車的重要代表,正逐漸成為全球汽車產(chǎn)業(yè)的重要發(fā)展方向。電動汽車的核心技術之一是電機驅(qū)動控制系統(tǒng),而絕緣柵雙極型晶體管(IGBT)作為電機驅(qū)動系統(tǒng)中的關鍵元件,其性能直接影響到電動汽車的動力性能和...

關鍵字: 電動汽車 新能源 驅(qū)動電源

在現(xiàn)代城市建設中,街道及停車場照明作為基礎設施的重要組成部分,其質(zhì)量和效率直接關系到城市的公共安全、居民生活質(zhì)量和能源利用效率。隨著科技的進步,高亮度白光發(fā)光二極管(LED)因其獨特的優(yōu)勢逐漸取代傳統(tǒng)光源,成為大功率區(qū)域...

關鍵字: 發(fā)光二極管 驅(qū)動電源 LED

LED通用照明設計工程師會遇到許多挑戰(zhàn),如功率密度、功率因數(shù)校正(PFC)、空間受限和可靠性等。

關鍵字: LED 驅(qū)動電源 功率因數(shù)校正

在LED照明技術日益普及的今天,LED驅(qū)動電源的電磁干擾(EMI)問題成為了一個不可忽視的挑戰(zhàn)。電磁干擾不僅會影響LED燈具的正常工作,還可能對周圍電子設備造成不利影響,甚至引發(fā)系統(tǒng)故障。因此,采取有效的硬件措施來解決L...

關鍵字: LED照明技術 電磁干擾 驅(qū)動電源

開關電源具有效率高的特性,而且開關電源的變壓器體積比串聯(lián)穩(wěn)壓型電源的要小得多,電源電路比較整潔,整機重量也有所下降,所以,現(xiàn)在的LED驅(qū)動電源

關鍵字: LED 驅(qū)動電源 開關電源

LED驅(qū)動電源是把電源供應轉(zhuǎn)換為特定的電壓電流以驅(qū)動LED發(fā)光的電壓轉(zhuǎn)換器,通常情況下:LED驅(qū)動電源的輸入包括高壓工頻交流(即市電)、低壓直流、高壓直流、低壓高頻交流(如電子變壓器的輸出)等。

關鍵字: LED 隧道燈 驅(qū)動電源
關閉