ARM Cortex-M0堆栈机制详解:从R13/sp寄存器到MSP与PSP的应用实践

今天给大家分享的这篇文章仍然是皮子恒在2016年之前写的技术文档,花了一些时间重新整理了格式。皮子恒之前讲过《嵌入式应用中的堆栈原理》。本文是堆栈原理的工程实践,更具体地说是它在ARM Cortex-M上的应用。 ARM Cortex-M 系列已经发展了很多代。我们以最简单的Cortex-M0为例来描述一下堆栈机制:

ARM Cortex-M0堆栈机制详解:从R13/sp寄存器到MSP与PSP的应用实践

1. 基本规则

1.1 R13/sp寄存器

R0-R12为通用寄存器,R13为系统堆栈指针sp。堆栈指针用于访问堆栈,即系统的RAM区域。 Cortex-M0 使用两个堆栈指针:主堆栈指针(MSP)和进程堆栈指针(PSP)。 R13在任何时候都只能是其中之一。默认为 MSP,可以通过控制寄存器(CONTORL)更改。

MSP是系统复位(即处于Handler Mode)后指定的sp(向量表的前4个字节自动加载),用于处理异常中断。当Reset_Handler结束时,CPU进入正常运行状态(即处于Thread Mode)。只有在这种状态下才能使用PSP。当然,也可以使用MSP。如果稍后出现硬中断,则会进入Handler Mode。如果硬件中断结束,则返回线程模式。

关于MSP和PSP的选择,是通过CONTORL寄存器进行配置的。 CONTORL 寄存器只能在线程模式下设置。一般情况下,没有必要使用PSP,除非有os。 MSP用于os内核的sp,PSP用于线程级应用程序的sp。这两个sps需要严格分开。

在编译器中,可以通过r13(R13)或sp(SP)来访问堆栈(具体的MSP和PSP由当时的环境决定); MSP和PSP也可以通过指定的MRS和MSR指令来访问。

1.2 栈结构

不带操作系统的堆栈结构:

OS有一个栈结构:

1.3 堆栈操作

Cortex-M0中的栈方向是向低地址增长的,这是一种全栈机制。栈操作是通过PUSH和POP来进行的。

堆栈一般放在ARM的RAM的高位区域。例如,某MCU中的RAM地址为0x20000000-0x20007fff,共32KByte。如果栈大小设置为4KByte,那么它的地址一般放在0x20007000-0x20007fff,其中0x20007000是绝对栈顶,0x20007ffc是绝对栈底,sp总是指向相对栈顶。第一个PUSH数据存放在绝对栈底(此时绝对栈底也是相对栈顶)。事实上,除了POP指令可以从栈顶取数据外,MOV指令也可以从任意位置取数据,但不会影响栈结构(即不会影响其sp) 。

由于ARM寄存器都是32位的,PUSH和POP指令都是32位访问,所以sp指针总是至少4Byte对齐(低2位总是0)。有时编译器也会分配一个8Byte对齐的堆栈。这是因为双浮点类型需要占用8Byte。为了处理方便,栈设置为8Byte对齐。

2. 推送顺序

堆栈顺序因编译器、处理器系统和操作系统而异。 C 语言中没有强制的堆栈顺序。这里我们主要讲一下ARM Cortex-M系列处理器在指定编译器下的堆栈顺序。

2.1 通用函数调用(通用)

上图展示了一般函数嵌套调用(无参数、无局部变量、无返回值)时sp的运行情况。当执行 BL FunctionA 指令时,LR 会记录 BL FunctionA 的下一条指令。进入FunctionA后执行的第一个操作是PUSH {LR},即将下一条顺序指令压入堆栈,然后开始执行FunctionA。函数体。函数体执行完毕后,使用POP {PC}指令将栈顶数据弹出到PC中,然后返回继续执行BL FunctionA的下一条指令。

2.2 极限函数调用(因平台而异)

考虑一个极端情况来详细描述堆栈序列,即函数包含4个以上参数,函数体中定义了多个局部变量,并且有返回值。这种情况比较特殊。皮子衡专门在IAR上做了一个实验。具体请看今天的推文(图很长,需要有一定的编译基础才能看懂):

你可能想看:
« 上一篇
下一篇 »

相关推荐

FreeBasic:强大免费开源的64位basic编译器及应用优势

2025年05月10日

82阅读

脊柱侧弯矫正方法大盘点:运动康复、支具矫正等多种方式

2025年05月09日

87阅读

如何在winForm标题栏去掉标题文字且任务栏图标正常显示

2025年05月09日

86阅读

十一黄金周促销广告词大全,国庆购物狂欢等你来

2025年05月09日

78阅读

关闭快速编辑模式及插入模式,设置控制台指定文字颜色举例

2025年05月09日

63阅读

黄金搭档低糖高钙饮品包装及成分功效全解析,适合人群要知晓

2025年05月09日

91阅读