μC/OS-II在ARM平臺(tái)上移植的深入探討
(1)數(shù)據(jù)類型定義:在調(diào)試時(shí)發(fā)現(xiàn),雖然定義8 bit或16 bit數(shù)據(jù)類型時(shí),在編譯過程中不會(huì)報(bào)錯(cuò),但這些變量并不會(huì)按要求被正確初始化或賦值,運(yùn)行過程常常出錯(cuò)。所以,在改寫OS_CPU.H代碼時(shí),將所有變量都定義成32 bit或64 bit;
(2)堆棧生長(zhǎng)方向定義:ARM的堆棧是從上往下生長(zhǎng)的,OS_STK_GROWTH定義為1;
(3)開關(guān)中斷的宏定義:用開關(guān)中斷的匯編函數(shù)實(shí)現(xiàn),放在OS_CPU_A.ASM文件中。
(4)宏定義OS_TASK_SW():這個(gè)宏定義是在ARM中斷處理之外時(shí),μC/OS-II從低優(yōu)先級(jí)切換到高優(yōu)先級(jí)任務(wù)時(shí)所調(diào)用的代碼,它總是在任務(wù)級(jí)代碼中被調(diào)用。在有些資料中[1],將OS_TASK_SW()和OSIntCtxSw()等同起來(lái),這在ARM內(nèi)核中是不行的,因?yàn)楹笳呤茿RM內(nèi)核在中斷模式下的任務(wù)切換函數(shù),而不同模式下處理器的寄存器組是不同的,所要保護(hù)的寄存器內(nèi)容也不相同,經(jīng)過調(diào)試,發(fā)現(xiàn)以下代碼可達(dá)到目的。
OS_TASK_SW
stmfd sp!, {lr} ; PC入棧,lr其實(shí)是任務(wù)的返回地址,
stmfd sp!, {r0-r12, lr}
mrs r4, cpsr
stmfd sp!, {r4} ;最后保存CPSR ldr r4, =OSTCBCur
ldr r5, [r4]
str sp, [r5] ;將SP保存在當(dāng)前任務(wù)的控制塊中 ldr r5, =OSTCBHighRdy
ldr r5, [r5]
str r5, [r4] ;OSTCBCur = OSTCBHighRdy ldr r6, =OSPrioHighRdy
ldr r6, [r6]
ldr r4, =OSPrioCur
str r6, [r4] ;OSPrioCur = OSPrioHighRdy
ldr sp, [r5] ;得到新任務(wù)的堆棧指針
ldr r4, [sp], #4
msr cpsr_cxsf, r4 ;先恢復(fù)CPSR
ldmfd sp!, {r0-r12, lr, pc}
3.2 OS_CPU_C.C.H的移植
在OS_CPU_C.C中,最主要的函數(shù)是OSTaskStkInit(),它在任務(wù)建立時(shí),用來(lái)初始化任務(wù)堆棧結(jié)構(gòu),其余鉤子函數(shù)可以不用動(dòng),這個(gè)函數(shù)的代碼比較簡(jiǎn)單[2]。需要說(shuō)明的是,由于本文所述系統(tǒng),用戶任務(wù)運(yùn)行在SVC模式下,沒有保存SPSR寄存器。
3.3 OS_CPU_A.ASM的移植
OS_CPU_A.ASM文件的匯編程序是μC/OS-II移植工程的重點(diǎn)和難點(diǎn)。它通常包括OSStartHighRdy()、OSIntCtxSw()、OSTickISR()和開關(guān)中斷代碼等。其中,OSStartHighRdy()的主要工作是將優(yōu)先級(jí)最高任務(wù)對(duì)應(yīng)的所有寄存器按順序從任務(wù)堆棧中恢復(fù)出來(lái),其代碼簡(jiǎn)單[2]。對(duì)于開關(guān)中斷函數(shù),在調(diào)試時(shí)所用代碼如下:
EnterCritical
mrs r1, cpsr
str r1, [r0]
orr r1, r1, #NOINT
msr cpsr_cxsf, r1
mov pc, lr
ExitCritical
ldr r1, [r0]
msr cpsr_cxsf, r1
mov pc, lr
需要指出的是,在每次成對(duì)調(diào)用這兩個(gè)函數(shù)時(shí),需要提前聲明變量r,代碼如下所示:
INT32U r;
EnterCritical(r);
ExitCritical(r);
需要慎重對(duì)待的是OSIntCtxSw()、OSTickISR()函數(shù)。在調(diào)試時(shí)發(fā)現(xiàn),用一般參考資料所介紹的代碼都無(wú)法實(shí)現(xiàn)多任務(wù)的正常運(yùn)行,其主要原因是,對(duì)ARM9內(nèi)核而言,其每種特定的中斷返回,都有特定的返回指令,在中斷處理過程中,強(qiáng)制使用模式切換指令,使處理器的中斷處理機(jī)制發(fā)生混亂,程序無(wú)法正常執(zhí)行。例如在ISR模式中使用指令:
MSR CPSR_c, #(NO_INT | SVC32_MODE)
其目的是返回ISR發(fā)生之前的模式,然后保存一些寄存器。但調(diào)試時(shí)發(fā)現(xiàn),在上述指令執(zhí)行之后,處理器重新響應(yīng)ISR中斷,并沒有順序執(zhí)行,而是立即回到ISR模式下。
還有,對(duì)于S3C2410的ARM920T內(nèi)核而言,其ISR模式的返回指令是:
ldmfd sp!, {r0-r12, lr}
subs pc, lr, #04
其他任何形式的指令都無(wú)法使處理器正確返回。有些資料用下述指令:
Ldmfd sp!, {r0-r12, lr,pc}; 執(zhí)行之前堆棧中相應(yīng)存儲(chǔ)單元的內(nèi)容為(lr-4)。
看起來(lái)與前面的兩行代碼意義相同,但后面的代碼僅僅讓處理器實(shí)現(xiàn)PC指針的跳轉(zhuǎn),而無(wú)法實(shí)現(xiàn)處理器的模式轉(zhuǎn)換,即從ISR模式回到中斷發(fā)生之前的模式。
但在中斷發(fā)生時(shí),無(wú)法在中斷處理過程中保存所有的處理器寄存器。例如,在ISR模式下,無(wú)法保存SVC模式的LR寄存器等。為了解決這個(gè)問題,本文采取了如圖1所示的框圖結(jié)構(gòu)來(lái)編寫中斷處理代碼和OSIntCtxSw()函數(shù)。本文引用地址:http://cafeforensic.com/article/151716.htm
tcp/ip相關(guān)文章:tcp/ip是什么
評(píng)論