05
28

UCOS2 porting HOWTO

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相關的變數
  1. typedef unsigned char  BOOLEAN; 
  2. typedef unsigned char  INT8U;                   
  3. typedef signed   char  INT8S;                   
  4. typedef unsigned short INT16U;                 
  5. typedef signed   short INT16S;                 
  6. typedef unsigned int   INT32U;                 
  7. typedef signed   int   INT32S;                 
  8. typedef float          FP32;                   
  9. typedef double         FP64;                   
  10. 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內可看到程式碼如下

  1. OS_STK *OSTaskStkInit (void (*task)(void *pd), void *pdata, OS_STK *ptos, INT16U opt)
  2. {
  3.  INT32U *stk;
  4.  
  5.     stk = (INT32U*)ptos;   
  6.     *stk-- = (INT32U)task;
  7.     *stk-- = (INT32U)0x14141414;  //R14(LR)
  8.     *stk-- = (INT32U)0x12121212;  //R12
  9.     *stk-- = (INT32U)0x11111111;  //R11
  10.     *stk-- = (INT32U)0x10101010;  //R10
  11.     *stk-- = (INT32U)0x09090909;  //R9
  12.     *stk-- = (INT32U)0x08080808;  //R8
  13.     *stk-- = (INT32U)0x07070707;  //R7
  14.     *stk-- = (INT32U)0x06060606;  //R6
  15.     *stk-- = (INT32U)0x05050505;  //R5
  16.     *stk-- = (INT32U)0x04040404;  //R4
  17.     *stk-- = (INT32U)0x03030303;  //R3
  18.     *stk-- = (INT32U)0x02020202;  //R2
  19.     *stk-- = (INT32U)0x01010101;  //R1
  20.     *stk-- = (INT32U)(pdata);     //R0   
  21.     *stk   = (INT32U)0x13;        //SPSR(SVC MODE)
  22.   
  23.     return ((OS_STK *)stk);
  24. }


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

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

OS_CPU_A .s

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

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


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的執行環境
  1. OSCtxSw   
  2.     STMFD   SP!, {LR}           ; save context of previous task
  3.     STMFD   SP!, {LR}
  4.     STMFD   SP!, {R0-R12}
  5.     MRS     R4, CPSR//保存CPSR
  6.     STMFD   SP!, {R4}
  7.     
  8.     LDR     R4, =OSTCBCur       ; OSTCBCur->OSTCBStkPtr = SP;
  9.     LDR     R5, [R4]
  10.     STR     SP, [R5]
  11.     
  12.     LDR     R4, =OSPrioCur         ; OSPrioCur = OSPrioHighRdy   
  13.     LDR     R6, =OSPrioHighRdy   
  14.     LDRB    R6, [R6]
  15.     STRB    R6, [R4]
  16.     
  17.     LDR     R4, =OSTCBCur          ; OSTCBCur = OSTCBHighRdy
  18.     LDR     R6, =OSTCBHighRdy
  19.     LDR     R6, [R6]
  20.     STR     R6, [R4]
  21.     
  22.     LDR     SP, [R6]                ; SP = OSTCBCur->OSTCBStkPtr
  23.     
  24.     LDMFD   SP!, {R4}
  25.     MSR     SPSR_cxsf, R4
  26.     
  27.     LDMFD   SP!, {R0-R12, LR, PC}^  ; pop new task's context

3. OSIntCtxSw
OSIntCtxSw這個函式是當第二個情況發生時(當CPU碰到中斷時)會呼叫的函式,當中斷執行完畢時,CPU會執行這個context switch函式,因為前一個執行的process已經在IRQ中斷周期發生前保存了自己的執行環境,所以這個函式只要選擇最高優先權的PROCESS並執行它就可以了
  1. OSIntCtxSw
  2.     LDR     R4, =OSPrioCur         ; OSPrioCur = OSPrioHighRdy
  3.     LDR     R5, =OSPrioHighRdy
  4.     LDRB    R6, [R5]
  5.     STRB    R6, [R4]
  6.     
  7.     LDR     R4, =OSTCBCur          ; OSTCBCur = OSTCBHighRdy
  8.     LDR     R5, =OSTCBHighRdy
  9.     LDR     R6, [R5]
  10.     STR     R6, [R4]
  11.     
  12.     LDR     SP, [R6]                ; SP = OSTCBCur->OSTCBStkPtr
  13.     
  14.     LDMFD   SP!, {R4}
  15.     MSR     SPSR_cxsf, R4
  16.     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
  1. STMFD   SP!, {R0-R2}                         
  2.     MOV     R1, SP
  3.     ADD     SP, SP, #12//把IRQ SP的指標還原,我們只是暫時借用
  4.     SUB     R2, LR, #4
  5.     MRS     R0, SPSR

(2)切換還SVC模式並保存PROCESS CONTEXT
  1. MSR     CPSR_c, #Mode_SVC | I_BIT | F_BIT   
  2.     
  3.     STMFD   SP!, {R2}           ; PC
  4.     STMFD   SP!, {LR}           ; LR
  5.     STMFD   SP!, {R3-R12}       ; R3-R12
  6.  
  7.     LDMFD   R1, {R4-R6}         ; get R1-R3 from IRQ's stack
  8.     
  9.     STMFD   SP!, {R4-R6}        ; push task's R1-R3
  10.     STMFD   SP!, {R0}           ; push task's spsr

(3)呼叫OSIntEnter,切換回IRQ模式,並執行IRQ routine,再切回SVC模式然後再呼叫OSIntExit,並還原上一個PROCESS的執行環境
  1. BL OSIntEnter
  2.     ; switch to interrupt mode
  3.     MSR     CPSR_c, #Mode_IRQ | I_BIT | F_BIT   ; change to IRQ mode and disable IRQ,FIQ       
  4.     BL        ISR_IRQ       
  5.     ;restore task after interrupt routine is finished
  6.     MSR     CPSR_c, #Mode_SVC | I_BIT | F_BIT   ; change to SVC mdoe
  7.     BL      OSIntExit
  8.     LDMFD   SP!, {R4}
  9.     MSR     SPSR_cxsf, R4
  10.     LDMFD   SP!, {R0-R12, LR, PC}^              ; pop new task's context


timer.c

1. Timer0_ISR
在timer ISR內執行系統計時函式OSTimeTick()
  1. void Timer0_ISR(void)
  2. {
  3.     OSTimeTick();
  4. }
標籤: embedded
評論: 0 | 引用: 0 | 閱讀: 8207
發表評論
暱 稱: 密 碼:
網 址: E - mail:
驗證碼: 驗證碼圖片 選 項:
頭 像:
內 容: