jzhang123 发表于 2013-10-16 15:00:11

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

yuanbuqi 发表于 2013-10-17 11:33:03

Mark            

Feco 发表于 2013-10-17 11:49:05


Mark                  

lidapang 发表于 2013-10-17 12:58:38

mark                                                                                    

jzhang123 发表于 2013-10-22 11:08:11

处理器自动压栈到R0,也就是说,此时R0即为栈顶指针。在往后空出8个空间的地址,手动入栈R4-R11

jzhang123 发表于 2013-10-30 08:47:25

{:smile:}            
页: [1]
查看完整版本: uC/OS-II学习笔记(二)-堆栈和CPU寄存器