在OS_cpu_c.c中确定了任务堆栈的格式,这个格式根据不同的体系结构不同的寄存器结构有所不同,因为在上下文切换时需要将所有相关的寄存器(除了任务堆栈指针SP)压入堆栈,从而起到保护上下文的作用
修改任务堆栈初始化函数,这个函数在建立TCB的时候使用,建立TCB链表在系统初始化阶段就完成了
- /*
- *********************************************************************************************************
- * INITIALIZE A TASK'S STACK
- *
- * Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the
- * stack frame of the task being created. This function is highly processor specific.
- *
- * Arguments : task is a pointer to the task code
- *
- * p_arg is a pointer to a user supplied data area that will be passed to the task
- * when the task first executes.
- *
- * ptos is a pointer to the top of stack. It is assumed that 'ptos' points to
- * a 'free' entry on the task stack. If OS_STK_GROWTH is set to 1 then
- * 'ptos' will contain the HIGHEST valid address of the stack. Similarly, if
- * OS_STK_GROWTH is set to 0, the 'ptos' will contains the LOWEST valid address
- * of the stack.
- *
- * opt specifies options that can be used to alter the behavior of OSTaskStkInit().
- * (see uCOS_II.H for OS_TASK_OPT_???).
- *
- * Returns : Always returns the location of the new top-of-stack' once the processor registers have
- * been placed on the stack in the proper order.
- *
- * Note(s) : 1) Interrupts are enabled when your task starts executing.
- * 2) All tasks run in SVC mode.
- *********************************************************************************************************
- */
- OS_STK *OSTaskStkInit (void (*task)(void *pd), void *p_arg, OS_STK *ptos, INT16U opt)
- {
- OS_STK *stk;
- opt = opt; /* 'opt' is not used, prevent warning */
-
- stk = ptos; /* Load stack pointer */
-
- *(stk) = (OS_STK)task; /* Entry Point */
- *(--stk) = (INT32U)0; /* LR */
- *(--stk) = (INT32U)0; /* R12 */
- *(--stk) = (INT32U)0; /* R11 */
- *(--stk) = (INT32U)0; /* R10 */
- *(--stk) = (INT32U)0; /* R9 */
- *(--stk) = (INT32U)0; /* R8 */
- *(--stk) = (INT32U)0; /* R7 */
- *(--stk) = (INT32U)0; /* R6 */
- *(--stk) = (INT32U)0; /* R5 */
- *(--stk) = (INT32U)0; /* R4 */
- *(--stk) = (INT32U)0; /* R3 */
- *(--stk) = (INT32U)0; /* R2 */
- *(--stk) = (INT32U)0; /* R1 */
- *(--stk) = (INT32U)p_arg; /* R0 : argument */
- *(--stk) = (INT32U)0x00000013L; /* CPSR (SVC mode, Enable both IRQ and FIQ interrupts) */
-
- return (stk);
- }
在ARM体系结构中,共有R0-R15(sp=R13,LR=R14,PC=R15)和状态寄存器CPSR 非中断情况,这些以一定的格式被存储在堆栈中,在DSP中寄存器必然有所不同,使用其中一个寄存器作为SP,其余都可以进行保存。
另外在这个文件中还有许多hook函数,这些函数起到的作用是在某些重要的时间节点,如tick或者TCBinit时进行用户自定义的操作,方便许多
修改void ISRInit(void)中断初始化函数,这个函数在系统创建的第一个运行的task中实现,用来启动tick,定时器中断触发上一个文章中OS_CPU_a.s中的OSTickISR函数
- void ISRInit(void)
- {
- // 设置中断控制器
- rPRIORITY = 0x00000080; // 使用默认的固定的优先级
- rINTMOD = 0x00000000; // 所有中断均为IRQ中断
- pISR_TIMER0= (uint32) OSTickISR;
- rINTMSK &= ~(1<<10); // 打开TIMER0中断允许
- //**********************************************************
- }
在DSP中使用interrupt();函数关联定时器中断和服务子程序,配置全局寄存器设置优先级和使能中断
修改中断开关宏!
设置状态寄存器CPSR
读取CPSR状态查看是否成功,如果不成功重新设置
如果成功子程序返回
其实可以使用c语言编写,这是个宏,甚至可以在宏中直接设置寄存器实现
MOV PC LR 的使用:
当使用bl或者blx跳转到子过程的时候,r14保存了返回地址,可以在调用过程结尾恢复。
异常中断发生时,这个异常模式特定的物理R14被设置成该异常模式将要返回的地址。
另外注意pc,在调试的时候显示的是当前指令地址,而用mov lr,pc的时候lr保存的是此指令向后数两条指令的地址,大家可以试一下用mov pc,pc,结果得到的是跳转两条指令,这个原因是由于arm的流水线造成的,预取两条指令的结果.
另:子程序返回的三种方法:1.MOV PC,LR 2.BL LR 3 STMFD SP!,{,LR}压栈弹栈
最后完成数据的重新定义,在文件OS_CPU.h中配置各种数据格式,堆栈增长方式
阅读(1845) | 评论(0) | 转发(0) |