Abstract
UC/OS2 是即時系統核心,跟其它微型作業系統一樣,它沒有shell, file system, network stack…等,所以對porting來說,改動的幅度不大
原始碼可在此網頁查看
在porting的過程中只需改動5個檔案,分別是
1.OS_CPU_A.s:增加4個函式的實作(OSStartHighRdy, OSIntCtxSw, OSCtxSw, OS_CPU_SR_Save, OS_CPU_SR_Restore)
2.OS_CPU_C.c:實做process stack的存放方式,和critical section進入和離開的函式
3.OS_CPU.H:宣告相關cpu-specified的變數
4.Vector.s:實做IRQ中斷時的uc/os context switch
5.timer.c:呼叫OS的計時函式

OS_CPU.H

宣告以ARM cpu資料型太為基準的OS相關的變數

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 INT32U         OS_STK;

OS_CPU_C .c

1.    設置Process Stack(function name:OSTaskStkInit)
根據uc/os2的文件,當我們用OSTaskCreateExt去建立process時,會需要宣告這個process所需要用到的stack address,而uc/os2做context switch時,會根據stack內所存的內容而決定context switch時所需替換的暫存器和PC.uc/os2運作在ARM SVC模式,所以我們要存R0-R14,PC,和SPSR這些暫存器的值

在OSTaskStkInit內可看到程式碼如下

OS_STK *OSTaskStkInit (void (*task)(void *pd), void *pdata, OS_STK *ptos, INT16U opt)
{
 INT32U *stk;
 
    stk = (INT32U*)ptos;   
    *stk-- = (INT32U)task;
    *stk-- = (INT32U)0x14141414;  //R14(LR)
    *stk-- = (INT32U)0x12121212;  //R12
    *stk-- = (INT32U)0x11111111;  //R11
    *stk-- = (INT32U)0x10101010;  //R10
    *stk-- = (INT32U)0x09090909;  //R9
    *stk-- = (INT32U)0x08080808;  //R8
    *stk-- = (INT32U)0x07070707;  //R7
    *stk-- = (INT32U)0x06060606;  //R6
    *stk-- = (INT32U)0x05050505;  //R5
    *stk-- = (INT32U)0x04040404;  //R4
    *stk-- = (INT32U)0x03030303;  //R3
    *stk-- = (INT32U)0x02020202;  //R2
    *stk-- = (INT32U)0x01010101;  //R1
    *stk-- = (INT32U)(pdata);     //R0   
    *stk   = (INT32U)0x13;        //SPSR(SVC MODE)
  
    return ((OS_STK *)stk);
}

2.Critical section的進入與離開(OS_ENTER_CRITICAL and OS_EXIT_CRITICAL)

這個函式目的在保存CPU切換模式時的CPSR暫存器的值

OS_CPU_A .s

1. OSStartHighRdy
此函式是uc/os2執行時呼叫的第一個函式,它會尋找最高優先權的process並執行它

; OSRunning = TRUE
 LDR     R0, =OSRunning //程式執行變數
MOV     R1, #1
 STRB    R1, [R0]
    
 ; Load First Task//把第一個high ready process拿來執行
 LDR     R0, OSTCBHighRdy    ; Load address of OSTCBHighRdy
 LDR     SP, [R0]            ; Load SP of task
 //開始還原最高優先權process的執行環境
 LDMFD   SP!, {R1}       ; get spsr of first task
 MSR     SPSR_cxsf, R1
 LDMFD   SP!, {R0-R12, LR, PC}^  ;run first task!

OSCtxSw   
    STMFD   SP!, {LR}           ; save context of previous task
    STMFD   SP!, {LR}
    STMFD   SP!, {R0-R12}
    MRS     R4, CPSR//保存CPSR
    STMFD   SP!, {R4}
    
    LDR     R4, =OSTCBCur       ; OSTCBCur->OSTCBStkPtr = SP;
    LDR     R5, [R4]
    STR     SP, [R5]
    
    LDR     R4, =OSPrioCur         ; OSPrioCur = OSPrioHighRdy   
    LDR     R6, =OSPrioHighRdy   
    LDRB    R6, [R6]
    STRB    R6, [R4]
    
    LDR     R4, =OSTCBCur          ; OSTCBCur = OSTCBHighRdy
    LDR     R6, =OSTCBHighRdy
    LDR     R6, [R6]
    STR     R6, [R4]
    
    LDR     SP, [R6]                ; SP = OSTCBCur->OSTCBStkPtr
    
    LDMFD   SP!, {R4}
    MSR     SPSR_cxsf, R4
    
    LDMFD   SP!, {R0-R12, LR, PC}^  ; pop new task's context

2. OSCtxSw
此函式是在OS_Sched函式內呼叫,uc/os2執行context switch的時間點有兩個
(1)當函式執行OSTimeDly函式時
(2)當CPU碰到中斷時
而OSCtxSw是當第一個情況發生時(當函式執行OSTimeDly函式時)會呼叫的函式,所以,假設我們目前有兩個process分別是PA和PB,當PA執行到OSTimeDly,CPU會保存PA目前執行環境的所有暫存器並從process queue裡面拿出最高優先權的process,也就是PB,取得PB的TCB(task control buffer),並從PB的TCB內取得它的stack,然後根據PB stack的內容,逐一還原PB的執行環境

3. OSIntCtxSw
OSIntCtxSw這個函式是當第二個情況發生時(當CPU碰到中斷時)會呼叫的函式,當中斷執行完畢時,CPU會執行這個context switch函式,因為前一個執行的process已經在IRQ中斷周期發生前保存了自己的執行環境,所以這個函式只要選擇最高優先權的PROCESS並執行它就可以了

OSIntCtxSw
    LDR     R4, =OSPrioCur         ; OSPrioCur = OSPrioHighRdy
    LDR     R5, =OSPrioHighRdy
    LDRB    R6, [R5]
    STRB    R6, [R4]
    
    LDR     R4, =OSTCBCur          ; OSTCBCur = OSTCBHighRdy
    LDR     R5, =OSTCBHighRdy
    LDR     R6, [R5]
    STR     R6, [R4]
    
    LDR     SP, [R6]                ; SP = OSTCBCur->OSTCBStkPtr
    
    LDMFD   SP!, {R4}
    MSR     SPSR_cxsf, R4
    LDMFD   SP!, {R0-R12, LR, PC}^  ; pop new task's context

vector.s

1. IRQ_Handler
因為已經切換到IRQ模式,所以我們暫存器的LR,CPSR都已經改變了,當ARM切換IRQ中斷時,會把上一個模式的CPSR存在SPSR,所以我們所要做的動作如下
(1)計算LR和保存LR和SPSR

STMFD   SP!, {R0-R2}                         
    MOV     R1, SP
    ADD     SP, SP, #12//把IRQ SP的指標還原,我們只是暫時借用
    SUB     R2, LR, #4
    MRS     R0, SPSR

(2)切換還SVC模式並保存PROCESS CONTEXT

MSR     CPSR_c, #Mode_SVC | I_BIT | F_BIT   
    
    STMFD   SP!, {R2}           ; PC
    STMFD   SP!, {LR}           ; LR
    STMFD   SP!, {R3-R12}       ; R3-R12
 
    LDMFD   R1, {R4-R6}         ; get R1-R3 from IRQ's stack
    
    STMFD   SP!, {R4-R6}        ; push task's R1-R3
    STMFD   SP!, {R0}           ; push task's spsr

(3)呼叫OSIntEnter,切換回IRQ模式,並執行IRQ routine,再切回SVC模式然後再呼叫OSIntExit,並還原上一個PROCESS的執行環境

BL OSIntEnter
    ; switch to interrupt mode
    MSR     CPSR_c, #Mode_IRQ | I_BIT | F_BIT   ; change to IRQ mode and disable IRQ,FIQ       
    BL        ISR_IRQ       
    ;restore task after interrupt routine is finished
    MSR     CPSR_c, #Mode_SVC | I_BIT | F_BIT   ; change to SVC mdoe
    BL      OSIntExit
    LDMFD   SP!, {R4}
    MSR     SPSR_cxsf, R4
    LDMFD   SP!, {R0-R12, LR, PC}^              ; pop new task's context

timer.c

1. Timer0_ISR
在timer ISR內執行系統計時函式OSTimeTick()

void Timer0_ISR(void)
{
    OSTimeTick();
}

最後修改日期: 3 6 月, 2022

作者

留言

Buy levothyroxine in uk canada pharmacy 24h sky pharmacy canada myskypharmacy on line pharmacy healthyman healthy man viagra scam sky pharmacy canada usa pharmacy no script supremesuppliers.net sky pharmacy supreme suppliers buy metronidazole 500mg no prescription Buy neurontin overnight

撰寫回覆或留言

發佈留言必須填寫的電子郵件地址不會公開。