Stk stk = ptos;         //將傳遞過來的堆棧指針值賦值給STKOSTaskStkInit

UC/OS-II中OSTaskStkInit()移植詳解(基於Cortex-M3)



  OSTaskStkInit()在Cortex-M3中主要功能爲初始化任務的棧的桔構,使任務的棧看起來就好像剛發生了一箇中斷一樣的結構,這些UC/OS的作者都有說到.現在我們須要瞭解的是Cortex-M3在發生中斷時,它的堆棧結構.在我們之前有提它中斷時的壓棧過程爲xPSR–>PC–>LR–>R12–>R3-R0(詳情點這裏:Cortex-M3中斷時,自動壓棧的順序),推斷出中斷後的任務堆棧應該爲下圖:

所以OSTaskStkInit()的作用就是將傳遞過來的參數(其中包含了堆棧地址與任務入口地址等)

標準的OSTaskStkInit()的原型爲:

OS_STK *OSTaskStkInit(void  (*task)(void *pd),void *pdata,OS_STK *ptos,INT16U opt);

ptos是傳入是堆棧的初始值,task則是任務PC的起始地址指針.opt則是操作數,一般的任務都沒用上.

所以我們最主要的任務就是把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)0×01000000L; //首先壓入的是xPSR
*(–stk) = (INT32U)task;                    //然後自減一後把任務的入口地址壓入
*(–stk) = (INT32U)0xFFFFFFFEL; //接下來壓入LR,由於CORTEX-M3的LR在中斷時是非常特殊值,所以這經的值須要根據實際情況去確定,比如在任務模式下使用PSP那麼就得把LR的值設定爲FFFFFFFE

*(–stk) = (INT32U)0×12121212L; /* R12 */
*(–stk) = (INT32U)0×03030303L; /* R3 */
*(–stk) = (INT32U)0×02020202L; /* R2 */
*(–stk) = (INT32U)0×01010101L; /* R1 */
*(–stk) = (INT32U)parg; /* R0 : ar 輸入參數 */
/* Remaining registers saved on*/
/* process stack */
/* 剩下的寄存器保存到堆棧 */

*(–stk) = (INT32U)0×11111111L; /* R11 */
*(–stk) = (INT32U)0×10101010L; /* R10 */
*(–stk) = (INT32U)0×09090909L; /* R9 */
*(–stk) = (INT32U)0×08080808L; /* R8 */
*(–stk) = (INT32U)0×07070707L; /* R7 */
*(–stk) = (INT32U)0×06060606L; /* R6 */
*(–stk) = (INT32U)0×05050505L; /* R5 */
*(–stk) = (INT32U)0×04040404L; /* R4 */

return(stk);   //最後,返回新的堆棧的值.
}

至此,OSTaskStkInit就算移植完成,當然他具體的目的與作用,還是去看看UC/OS的作者說明是最全面的.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章