Lpc1768移植UCOS-II(三)

三、移植OS_CPU_A.ASM

1、移植OS_CPU_SR_Save() OS_CPU_SR_Restore()

clip_image002

OS_CPU_SR_Save()保存当前的开关中断状态到R0,使用R0是因为编译器一般用R0传递参数。然后关中断。

Bx LR

从被OS_CPU_SR_Save()函数中断的程序处继续执行。进入临界段。

OS_CPU_SR_Restore()恢复R0中保存的开关状态,

Bx LR

从被OS_CPU_SR_Restore()函数中断的程序处继续执行。退出临界段。

这里使用的是PRIMASK,PRIMASK用于除能在 NMI和硬 fault之外的所有异常。

FAULTMASK能关闭所有异常和硬fault。

这里使用PRIMASK而不是FAULTMASK,是因为出现硬fault,必须要去处理,硬fault不能被关掉。

2、移植OSStartHighRdy()

clip_image004

OSStart()调用OSStartHighRdy()来使就绪态任务中优先级最高的任务开始运行。

clip_image006

这个函数里首先设置PENDSV中断优先级最低。

把PSP进程堆栈寄存器的值设为0.

设置MSP主堆栈寄存器的值为OS_CPU_ExceptStkBase。OS_CPU_ExceptStkBase在OS_CPU.H中定义,指向一个堆栈类型数组。

把OSRunning置1,表示OS内核开始运行。

悬起PendSV,开总中断。

3、移植任务切换函数OSCtxSw()

clip_image008

这个函数也是悬起PendSV中断,在PendSV中断程序中进行上下文切换。

OSCtxSw()在OS_Sched()函数中被调用。

4、移植中断切换函数OSIntCtxSw()

clip_image010

悬起PendSV中断,在PendSV中断程序中进行上下文切换。

OSIntCtxSw()在OSIntExit()函数中被调用。

5、移植PendSV_Handler()

clip_image012

PendSV用于上下文切换,这是CM3推荐的做法。因为CM3对任何异常自动保存和恢复xPSR,PC,LR,r12,r3,r4,r1,r0,所以只有R4-R11需要手动保存到任务堆栈。

1、 关闭中断

2、 判断PSP是否为0,因为在开始执行第一个任务时,在函数OSStartHighRdy()中把PSP置0,所以如果PSP为0,那么表示当前执行的是第一个任务,没有上文需要保存,直接跳转到OS_CPU_PendSVHandler_nosave。

如果PSP不为0,需要保存R4-R11的值到当前任务的堆栈。因为CM3自动保存了8个字节寄存器,每个寄存器32位,4个字节,4*8=32=0x20.所以R0-0x20,得到当前的堆栈指针,然后把R4-R11压入堆栈。最后把当前的堆栈值送给当前任务的任务控制块OSTCBCur->OSTCBStkPtr。

3、 LR压栈,调用钩子函数OSTaskSwHook(),LR出栈。如果不使用钩子函数,这一段可以屏蔽。

4、 OSPrioCur = OSPrioHighRdy; OSPrioHighRdy是一个8位数,指待运行的优先级最高的任务的优先级号。OSPrioCur是当前任务的优先级号。

5、 改变OSTCBCur的值,使OSTCBCur指向待运行任务的控制块OSTCBHighRdy。

6、 把待运行任务的堆栈指针放到R0

7、 从待运行任务的堆栈中取出R4-R11的值送给R4-R11

8、 因为已经出栈8个寄存器的值,每个寄存器占4字节,调整待运行任务的堆栈指针,R0+0X20。

9、 把待运行任务的当前堆栈值送到CM3的进程堆栈PSP。

10、 ORR LR, LR, #0x04,确保异常返回后使用PSP

11、 开中断

12、 退出异常,从PSP弹出xPSR,PC,LR,r12,r3,r4,r1,r0(这几个寄存器的值也是保存在待运行任务的栈中),开始执行新任务。

注意中断函数名是PendSV_Handler,要和要和startup_LPC17xx.s中的中断向量表定义的PendSV中断函数名称对应起来。在startup_LPC17xx.s中定义了

clip_image014

这是默认的PendSV_Handler中断函数,是一个死循环。后面[WEAK]的意思是告诉编译器,如果程序其它地方定义了PendSV_Handler(),就不用这里定义的PendSV_Handler()。如果在OS_CPU_A.ASM中没有声明PendSV_Handler()可以被外部引用

clip_image016

就是这段代码没有EXPORT PendSV_Handler,即使OS_CPU_A.ASM中定义了PendSV_Handler()函数,编译时也会用

clip_image014[1]

这段代码,在发送PendSV中断时,程序一直在B.处死循环。

到这里,整个移植工作就完成了。

© 版权声明
THE END
喜欢就支持以下吧
点赞0
分享
评论 抢沙发