UC/OS-II中OSTaskStkInit()移植詳解(基于Cortex-M3)(轉(zhuǎn)載) 其實就是模擬中斷后堆棧的運行,。 OSTaskStkInit()在Cortex-M3中主要功能為初始化任務的棧的桔構(gòu),使任務的棧看起來就好像剛發(fā)生了一個中斷一樣的結(jié)構(gòu),這些UC/OS的作者都有說到.現(xiàn)在我們須要了解的是Cortex-M3在發(fā)生中斷時,它的堆棧結(jié)構(gòu).在我們之前有提它中斷時的壓棧過程為xPSR–>PC–>LR–>R12–>R3-R0(詳情點這里:Cortex-M3中斷時,自動壓棧的順序),推斷出中斷后的任務堆棧應該為下圖:
所以OSTaskStkInit()的作用就是將傳遞過來的參數(shù)(其中包含了堆棧地址與任務入口地址等)
標準的OSTaskStkInit()的原型為:
OS_STK *OSTaskStkInit(void (*task)(void *pd),void *pdata,OS_STK *ptos,INT16U opt);
ptos是傳入是堆棧的初始值,task則是任務PC的起始地址指針.opt則是操作數(shù),一般的任務都沒用上.
所以我們最主要的任務就是把ptos,task按中斷的方式壓入堆棧中,堆棧的地址由ptos給出,然后再把新的堆棧的值傳回去.方法:
opt=opt; //未使用,防止編譯器警告 OS_STK *OSTaskStkInit (void (*task)(void *pd), void *pdata, OS_STK *ptos, INT16U opt) { OS_STK *stk; //定義一個指針變量,用來對堆棧的操作
stk = ptos; //將傳遞過來的堆棧指針值賦值給STK
*(stk) = (INT32U)0x01000000L; //首先壓入的是xPSR *(–stk) = (INT32U)task; //然后自減一后把任務的入口地址壓入 *(–stk) = (INT32U)0xFFFFFFFEL; //接下來壓入LR,由于CORTEX-M3的LR在中斷時是非常特殊值,所以這經(jīng)的值須要根據(jù)實際情況去確定,比如在任務模式下使用PSP那么就得把LR的值設定為FFFFFFFE
*(–stk) = (INT32U)0x12121212L; /* R12 */ *(–stk) = (INT32U)0x03030303L; /* R3 */ *(–stk) = (INT32U)0x02020202L; /* R2 */ *(–stk) = (INT32U)0x01010101L; /* R1 */ *(–stk) = (INT32U)parg; /* R0 : ar 輸入?yún)?shù) */ /* Remaining registers saved on*/ /* process stack */ /* 剩下的寄存器保存到堆棧 */
*(–stk) = (INT32U)0x11111111L; /* R11 */ *(–stk) = (INT32U)0x10101010L; /* R10 */ *(–stk) = (INT32U)0x09090909L; /* R9 */ *(–stk) = (INT32U)0x08080808L; /* R8 */ *(–stk) = (INT32U)0x07070707L; /* R7 */ *(–stk) = (INT32U)0x06060606L; /* R6 */ *(–stk) = (INT32U)0x05050505L; /* R5 */ *(–stk) = (INT32U)0x04040404L; /* R4 */
return(stk); //最后,返回新的堆棧的值. }
至此,OSTaskStkInit就算移植完成,當然他具體的目的與作用,還是去看看UC/OS的作者說明是最全面的.
|