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的作者说明是最全面的.

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