|
05 28 |
UCOS2 porting HOWTO作者: Joey 日期: 2008-05-28 10:23 |
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相關的變數
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內可看到程式碼如下
2.Critical section的進入與離開(OS_ENTER_CRITICAL and OS_EXIT_CRITICAL)
這個函式目的在保存CPU切換模式時的CPSR暫存器的值
OS_CPU_A .s
1. OSStartHighRdy
此函式是uc/os2執行時呼叫的第一個函式,它會尋找最高優先權的process並執行它
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並執行它就可以了
vector.s
1. IRQ_Handler
因為已經切換到IRQ模式,所以我們暫存器的LR,CPSR都已經改變了,當ARM切換IRQ中斷時,會把上一個模式的CPSR存在SPSR,所以我們所要做的動作如下
(1)計算LR和保存LR和SPSR
(2)切換還SVC模式並保存PROCESS CONTEXT
(3)呼叫OSIntEnter,切換回IRQ模式,並執行IRQ routine,再切回SVC模式然後再呼叫OSIntExit,並還原上一個PROCESS的執行環境
timer.c
1. Timer0_ISR
在timer ISR內執行系統計時函式OSTimeTick()
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!
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的執行環境
- 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
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();
- }
評論: 0 |
引用: 0 |
閱讀: 3033
發表評論
訂閱
上一篇 |
返回
下一篇
標籤:


fw_printenv-control u-boot enviroment variables under linux (2009-05-12 16:35)
rpcapd與netcat-測試嵌入式系統的好工具 (2009-04-09 17:06)
udev-強大的device node管理系統 (2009-02-02 20:35)
Framebuffer兩三事-Test On QT2410 (2009-01-12 16:29)
UIO-Linux user space I/O driver (2008-12-15 14:50)
GDB-刺入bug心臟的寶劍 (2008-10-15 16:11)
Telnet daemon-RS232以外的選擇 (2008-10-03 18:57)
在嵌入式系統切換file system-以squashfs和jffs2為例 (2008-10-01 19:44)
Linux kernel module-進入系統核心的鑰匙 (2008-09-12 14:03)