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();
}
留言
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