---------------------------------------------
-- 时间:2018-12-09
-- 创建人:Ruo_Xiao
-- 邮箱:[email protected]
---------------------------------------------
一、声明
本人在“网易云课堂”报名了李述铜老师的《自己动手从0到1写嵌入式操作系统》课程,在《内核编程实践》这堂课中讲解了任务切换的基本方法。对于核心函数“PendSV_Handler”的自己的理解我将记录在下面,由于该课程是付费课程,该工程的源码我觉得不能随便贴上,故只在这里粘贴必要的“PendSV_Handler”的源码,以供自己和该课程的学员参考,本人不会将该贴用于商业用途。如若我有侵权行为请告知,我会及时删除该贴。
二、源码
三、功能
1、该函数的功能是初步理解任务切换的本质,即:保存当前任务所使用的寄存器(R4~R11)的值到内存,中断或者异常服务例程执行完之后,再恢复中断或者异常之前任务的寄存器的值,从而继续执行该任务。
2、第8行~第13行代码是当前任务所使用的寄存器保存到内存。
3、第16行~第18行代码,我理解的是更新栈指针,即:R1。这里的R1相当于SP。
四、解释
1、开始执行该函数时,各个变量的地址及内容如下:
blockPtr 地址:0x2000 0000 , 内容 : 0x2000 0008
blockPtr->stackPtr 地址 :0x2000 0008 , 内容 :0x2000 1018
2、第8行:LDR R0, =blockPtr
这里blockPtr相当于符号,该代码的含义是将blockPtr的地址传给R0,即:R0 = &blockPtr = 0x2000 0000 。
3、第9行:LDR R0, [R0]
该代码的含义是R0 = *R0,也就是R0 = R0中的内容,即:R0 = blockPtr = &(bolckPtr->stackPtr) = 0x2000 0008。
4、第10行:LDR R0, [R0]
该代码的含义同上,即:R0 = bolckPtr->stackPtr = &stackBuffer[1024]= 0x20001018。
执行完该句,R0就指向了stackBuffer[1024]。
5、第13行:STMDB R0!, {R4-R11}
该代码的含义是将R11~R4的值逐个存储在stackBuffer[1023]~stackBuffer[1016]中。
过程如下:
(1)R0 = R0 - 4 , 将R11压入*R0中。
(2)R0 = R0 - 4 , 将R10压入*R0中。 ……
(3)R0 = R0 - 4, , 将R4压入*R0中。
结果如下:
执行到这里,就完成了将R4~R11压入内存中的使命。
6、第16行~17行,含义同第8行~第9行。
7、第18行: STR R0, [R1]
该代码的含义是将R0的值压入*R1中,即:bolckPtr->stackPtr = R0 = 0x20000FF8。
这里0x20000FF8是第13行执行完成之后,R0的值由0x2000 1018 - 0x0000 0020 (4*8的十六进制) = 0x20000FF8。
8、第21~22行,相当于执行是其他任务,任务内容是R4 = R4 + 1,,R5 = R5 + 1。
9、第25行:LDMIA R0!, {R4-R11}
将R0所执行的内存中的数据依次压入R4~R11中。
过程如下:
将*R0中的内容压入R4中,R0 = R0 + 4;
将*R0中的内容压入R5中,R0 = R0 + 4; ……
将*R0中的内容压入R11中,R0 = R0 + 4;
执行完之后,R0中的内容恢复到0x2000 1018,即:指向了stackBuffer[1024]。
10、第28行:BX LR
异常返回。
整个函数执行完成之后,实现了保存寄存器入栈,执行其他任务,弹栈恢复寄存器的值,从而完成任务切换功能。
(SAW:Game Over!)