uC/OS-II学习笔记(二)-堆栈和CPU寄存器
1. uC/OS-II有定义堆栈的生长方向,在OS_CPU.h里
#define OS_STK_GROWTH 1 //从高地址往低地址,STM32F10x就是往上生长方向
堆栈的是往上长的(就是说往顶的方向长,其实质是你的栈底是定死的不能动,入栈的东西只能不断往上
叠,这就像你在书桌上放书一样,桌底是定死的,所以你的书只能一本一本地往上堆,往上长)“先修改指
针,然后插入数据,出栈时刚好相反”,因为堆栈指针指向的总是栈顶元素,栈底不能动,所以数据入栈前
要先修改指针使它指向新的空余空间然后再把数据存进去,出栈的时候自然相反。
下图为任务的堆栈
;// Low Memory
// | .... |
;// |-----------------|
;// | .... |
;// |-----------------|
;// | .... |
;// |-----------------| |---- 任务切换时PSP
;// | .... | |
;// |-----------------| | |--------------------| |-----------------------|
;// ^ | R4 | <----|----| OSTCBStkPtr |<-----| (OS_TCB *) |
;// ^ |-----------------| |--------------------| |-----------------------|
;// ^ | R5 | |--------------------| OSTCBHighRdy
;// | |-----------------| |--------------------|
;// | | R6 | |--------------------|
;// | |-----------------| |-------------------|
;// | | R7 | |--------------------|
;// | |-----------------| |--------------------|
;// | | R8 | Task's
;// | |-----------------| OS_TCB
;// | | R9 |
;// | |-----------------|
;// | | R10 |
;// Stack |-----------------|
;// Growth | R11 |
;// = 1 |-----------------|
;// | | R0 = p_arg |<-------- 异常时的PSP (向上生长的满栈)
;// | |-----------------|
;// | | R1 |
;// | |-----------------|
;// | | R2 |
;// | |-----------------|
;// | | R3 |
;// | |-----------------|
;// | | R12 |
;// | |-----------------|
;// | | LR |
;// | |-----------------|
;// | |PC = task|
;// | |-----------------|
;// | | xPSR |
;// |-----------------|
;// High Memory
2. 需要说明的是uC/OS-II在执行任务切换中断时
1)xPSR,PC,LR,R12,R0~R3,这几个寄存器在进入中断的时候自动保存,只有剩下的几个寄存器需要手动保存。
2)每个任务初始化堆栈的时候,将堆栈指针R13指向相应的任务地址,这样初始化以后进行任务切换时,就能将变量存入自己的任务堆栈
3. Cortex-M3 处理器拥有 R0-R15 的寄存器组
http://uphotos.eepw.com.cn/sylar/pics/ba77a5f526eb8f1561901f77a39305b3.jpg
1) R0-R12:32位通用寄存器,用于数据操作。绝大多数 16位Thumb指令只能访问R0-R7,而 32位 Thumb-2指令可以访问所有寄存器。
2) R13:两个堆栈指针SP,但在同一时刻只能有一个可以看到,这也就是所谓的“banked”寄存器。
主堆栈指针(MSP):复位后缺省使用的堆栈指针,用于操作系统内核以及异常处理例程(包括中断服务例程) 进程堆栈指针(PSP):由用户的应用程序代码使用。 在ARM变成领域中,凡是打断程序顺序执行的时间,都被称为异常(exception),除了外部中断之外,当有指令执行了“非法操作”,或者
访问被禁的内存区间,因各种错误产生的错误Fault,以及不可屏蔽中断发生时,都会打断程序的执行,这些情况统称为异常,在不严格
的上下文中,异常与中断也可以混用,程序代码也可以主动请求进入异常状态。
堆栈指针的最低两位永远是0,即对阵总是4字节对齐的
3) R14:连接寄存器 ( LR )
当调用一个子程序时,由R14存储返回地址。
ARM为了减少访问内存的次数(访问内存的操作往往要 3个以上指令周期,带MMU和cache的就更加不确定了),把返回地址直接存储在寄存器
中。这样足以使很多只有1级子程序调用的代码无需访问内存(堆栈内存),从而提高了子程序调用的效率。如果多于 1 级,则需要把前一级的
R14 值压到堆栈里。在 ARM上编程时,应尽量只使用寄存器保存中间结果,迫不得以时才访问内存。在 RISC 处理器中,为了强调访内操作
越过了处理器的界线,并且带来了对性能的不利影响,给它取了一个专业的术语:溅出。
4) R15:程序计数寄存器 ( PC )
指向当前的程序地址。如果修改它的值,就能改变程序的执行流向(很多高级技巧就在这里面)。
5) 特殊功能寄存器
Cortex-M3还在内核水平上搭载了若干特殊功能寄存器,包括
程序状态字寄存器组(PSRs)
中断屏蔽寄存器组(PRIMASK, FAULTMASK, BASEPRI)
控制寄存器(CONTROL)
http://uphotos.eepw.com.cn/sylar/pics/a4e97f9993fdebfd34de9967fa4530a2.jpg Cortex-M3 中的特殊功能寄存器集合 http://uphotos.eepw.com.cn/sylar/pics/25253292ee383607565b9aa7ef9621af.jpg
Mark
Mark mark 处理器自动压栈到R0,也就是说,此时R0即为栈顶指针。在往后空出8个空间的地址,手动入栈R4-R11 {:smile:}
页:
[1]