其实就是模拟中断后堆栈的运行。
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)0x01000000L; //首先压入的是xPSR
*(–stk) = (INT32U)task; //然后自减一后把任务的入口地址压入
*(–stk) = (INT32U)0xFFFFFFFEL; //接下来压入LR,由于CORTEX-M3的LR在中断时是非常特殊值,所以这经的值须要根据实际情况去确定,比如在任务模式下使用PSP那么就得把LR的值设定为FFFFFFFE
*(–stk) = (INT32U)0x12121212L; /* R12 */
*(–stk) = (INT32U)0x03030303L; /* R3 */
*(–stk) = (INT32U)0x02020202L; /* R2 */
*(–stk) = (INT32U)0x01010101L; /* R1 */
*(–stk) = (INT32U)parg; /* R0 : ar 输入参数 */
/* 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的作者说明是最全面的.