痞子衡嵌入式:ARM Cortex-M内核那些事(6)- 系统堆栈机制
大家好,我是痞子衡,是正经搞技术的痞子。今天痞子衡给大家介绍的是ARM Cortex-M堆栈机制。
今天给大家分享的这篇依旧是2016年之前痞子衡写的技术文档,花了点时间重新编排了一下格式。前面痞子衡讲过 《嵌入式里的堆栈原理》,本篇算是堆栈原理的工程实践,更具体点说是在ARM Cortex-M上的应用。ARM Cortex-M家族发展至今已经很多代,我们且以最简单的Cortex-M0为例来讲述堆栈机制:
1.基本规则
1.1 R13 / sp寄存器

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

MSP是系统复位后(即其处于Handler Mode)的指定sp(vector table的前4Byte自动载入),用于处理异常中断。当结束Reset_Handler后,cpu进入正常运行状态(即其处于Thread Mode),仅在此状态下PSP才能被使用,当然MSP也可以使用。其后如有硬中断来临,则进入Handler Mode,如果硬件中断结束,则返回Thread Mode。

关于MSP和PSP的选用,其是通过CONTORL寄存器来配置,仅在Thread Mode下才可设置CONTORL寄存器。一般情况下,没有必要使用PSP,除非是有os存在时,MSP用于os内核的sp,而PSP用于thread级app的sp,这两个sp需严格分开。
在编译器中,可以通过r13(R13)或sp(SP)来访问堆栈(具体是MSP和PSP由当时环境决定);也可以通过指定的MRS、MSR指令来访问MSP和PSP。
1.2栈结构
无OS的堆栈结构:

有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寄存器均是32bit,故PUSH和POP指令均是32bit访问,故sp指针总是至少4Byte对齐(低2bit永远为0)。有时编译器也会分配8Byte对齐的栈,这是由于double浮点类型需要占用8Byte,为了处理方便,故将栈设为8Byte对齐。
2.入栈顺序
入栈顺序因编译器、处理器系统、OS而异,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上做过一次实验,详见下图:

至此,ARM Cortex-M堆栈机制痞子衡便介绍完毕了,掌声在哪里~~~
欢迎订阅
文章会同时发布到我的 博客园主页、CSDN主页、微信公众号 平台上。
微信搜索"痞子衡嵌入式"或者扫描下面二维码,就可以在手机上第一时间看了哦。

痞子衡嵌入式:ARM Cortex-M内核那些事(6)- 系统堆栈机制的更多相关文章
- 痞子衡嵌入式:ARM Cortex-M内核那些事(9.1)- 存储保护(MPU - PMSAv6/7)
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是ARM Cortex-M存储保护模块(MPU). <ARM Cortex-M内核MCU开发那些事>的内核篇连载最早是 201 ...
- 痞子衡嵌入式:ARM Cortex-M调试那些事(1)- 4线协议标准(JTAG)
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家讲的是嵌入式调试里的接口标准JTAG. 在结束<ARM Cortex-M文件那些事>系列文章之后,痞子衡休整了一小段时间,但是讲课的 ...
- 痞子衡嵌入式:ARM Cortex-M文件那些事(1)- 源文件(.c/.h/.s)
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家讲的是嵌入式开发里的source文件. 众所周知,嵌入式开发属于偏底层的开发,主要编程语言是C和汇编.所以本文要讲的source文件主要指的就是 ...
- 痞子衡嵌入式:ARM Cortex-M文件那些事(3)- 工程文件(.ewp)
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家讲的是嵌入式开发里的project文件. 前面两节课里,痞子衡分别给大家介绍了嵌入式开发中的两种典型input文件:源文件(.c/.h/.s). ...
- 痞子衡嵌入式:Ethos-U55,ARM首款面向Cortex-M的microNPU
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是ARM Ethos-U55. ARM 前几天刚发布了 Cortex-M 家族最新一款内核 - Cortex-M55 以及首款面向 Cor ...
- 痞子衡嵌入式:链接函数到8字节对齐地址或可进一步提升i.MXRT内核执行性能
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家分享的是i.MXRT上进一步提升代码执行性能的经验. 今天跟大家聊的这个话题还是跟痞子衡最近这段时间参与的一个基于i.MXRT1170的大项目有 ...
- 痞子衡嵌入式:超级下载算法(RT-UFL)开发笔记(1) - 执行在不同CM内核下
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是超级下载算法开发笔记(1)之执行在不同CM内核下. 文接上篇 <RT-UFL - 一个适用全平台i.MXRT的超级下载算法设计&g ...
- 痞子衡嵌入式:盘点国内RISC-V内核MCU厂商
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是国内RISC-V内核MCU厂商. 虽然RISC-V风潮已经吹了好几年,但2019年才是其真正进入主流市场的元年,最近国内大量芯片公司崛起 ...
- 痞子衡嵌入式:盘点国内RISC-V内核MCU厂商(2020年发布产品)
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是国内RISC-V内核MCU厂商(2020). 虽然RISC-V风潮已经吹了好几年,但2019年才是其真正进入主流市场的元年,最近国内大量 ...
随机推荐
- 龙芯 3B1500 Fedora28 安装笔记
版权声明:原创文章,未经博主允许不得转载 龙芯 3A4000 已经发布,十年前的 3B1500 早就落伍了.但我还是打算把它作为寒假刷 ACM 题的主力机 并将此当作年后收到 4000 的预习. 龙芯 ...
- Dynamics 365 CRM Action 和 workflow 的区别
workflow 总是需要一个record作为起始点(create, update, delete or on-demand) 但是action 不需要. 例如我们需要action来创建一个发送ema ...
- 远程桌面软件RDCMan汉化版
自己汉化的远程桌面控制软件RDCMan--Remote Desktop Connection Manager(RDCMan) v2.7 简体中文汉化版. 介绍 Remote Desktop Conne ...
- zookeeper3.4.6安装
1.关闭防火墙 service iptables stop chkconfig iptables off 2.编辑hosts文件: vi /etc/hosts 192.168.99.6 JacK6 1 ...
- 使用springboot Admin 2.0.6版本 集成监控springcloud微服务应用
一 新建 添加依赖 <dependencies> <dependency> <groupId>de.codecentric</groupId> < ...
- Asp.Net Core 混合全球化与本地化支持
前言 最近的新型冠状病毒流行让很多人主动在家隔离,希望疫情能快点消退.武汉加油,中国必胜! Asp.Net Core 提供了内置的网站国际化(全球化与本地化)支持,微软还内置了基于 resx 资源字符 ...
- 深入源码解析spring aop实现的三个过程
Spring AOP的面向切面编程,是面向对象编程的一种补充,用于处理系统中分布的各个模块的横切关注点,比如说事务管理.日志.缓存等.它是使用动态代理实现的,在内存中临时为方法生成一个AOP对象,这个 ...
- solaris系统磁盘镜像
查看磁盘分区 查看系统的磁盘数据与容量: 用format查看一下磁盘的情况,0号盘是c1t0d0,系统源磁盘,1号盘是c1t1d0,新增加磁盘,作为镜像盘使用. 注意:两块硬盘的容量最好相等,如果镜像 ...
- Codeforces_729_E
http://codeforces.com/problemset/problem/729/E 存在的数必须连续,若不连续,从最后选人来补,注意根不是0和其他点是0的情况. #include<io ...
- sql中常量和变量的引用
String name =jtf.getText().trim(); String sql="select * from stu where stuname=' "+name+& ...