STM32(F407)—— 堆栈

2023-05-16

目录

1. SRAM

2. 堆栈的作用

3. 堆栈的设置

4. 堆栈的实现 

5. 双堆栈机制


堆栈是一种数据结构。堆栈都是一种数据项按序排列的数据结构,只能在一端(称为栈顶(top))对数据项进行插入和删除,相应地,另一端为成为栈底(bottom),不含元素的空表称为空栈。

其实堆栈是由栈(Stack)堆(Heap)组成的,汇编中应用的 PUSH 和 POP 就是对 栈(Stack)的操作,其按照后进先出(LIFO-Last In First Out)的原理运作。​

笼统地讲,堆栈操作就是对内存的读写操作,但是其地址由 SP 给出。

1. SRAM

STM32的内存(存储器)的地址空间大小为4G(0x0000 0000 ~ 0xFFFF FFFF),被分为8个block(block0~block7),每个block512Mbyte,如下图所示。

SRAM 被分配到 block 1,内有SARM1(112KB,0x2000 00000 ~ 0x2001 BFFF)和SRAM2(16KB, 0x2001 C000 ~ 0x2001 FFFF)两块连续的SRAM,可供所有的AHB 主控总线访问。

  • 不同系类单片机的 SRAM 是不一样的,但它们的起始地址都是0x2000 0000。
  • 为什么是两块SRAM?这是因为主总线支持并发SRAM访问,提高执行效率。例如当 CPU 对 112 KB SRAM 进行读/写操作时,以太网MAC 可以同时对 16 KB SRAM 进行读/写操作;或者CPU和DMA可以同时访问不同的SRAM。

STM32F40xxx 存储器映射

2. 堆栈的作用

栈(Stack):由编译器自动分配和释放。栈存放局部变量,函数调用时的返回地址和现场保护,函数的参数(形参)等。

堆(Heap):有程序员主动分配和释放。主要用于动态内存分配,malloc 申请,free 释放。

  • 在函数中定义的局变量占用栈空间,当数据较多,栈空间使用完,则会占用堆空间,甚至其他全局变量空间,造成程序崩溃或数据错误(内存溢出错误)。

  • 在不断申请、释放的过程中,容易产生碎片化内存;当然如果不是在短时间内频繁的使用 malloc 申请和 free 释放内存,系统是有足够的时间来回收碎片内存。

  • 堆栈指针的最低两位永远是 0,这意味着堆栈总是 4 字节对齐的。

3. 堆栈的设置

这里我们以 STM32F407 的程序代码为例进行说明,找到启动文件 startup_stm32f407xx.s,设置栈大小为 2048(0x800),堆大小为 1024(0x400)。

 编译代码后,在 Build output 窗口中显示编译结果信息,如下图所示:

这里只是针对当前测试实例程序进行说明,但万变不离其宗,一样可以对照理解。

  •  Code:存储到Flash(ROM)中的程序代码,显示占用了 12372  个字节。
  • RO-data:只读数据(Read Only data),被存储到ROM中的数据,也就是常量等不能被程序修改的数据;例如 const 修饰的变量。
  • RW-data:可读写数据(Read Write data),在程序编写时已经初始化初始值。
  • ZI-data:(Zero Initialized data),没有初始化的变量,被编译器初始化为0;(使用了RTOS)

Total RO  Size (CodeRO-data) = 12876 (  12.57kB)

Total RW  Size (RW-data + ZI-data)  = 24888 (  24.30kB)

Total ROM Size (Code + RO-dataRW-data)  = 12984 (  12.68kB)

编译成功后会在工程文件下生成一个 xxxx.map 文件,这个文件的详细讲解网上很多,请百度一下即可;如图红框所示,STACK 和 HEAP 的大小和我们所设置的一样,

不知道大家注意到 HEAP 和 STACK 的起始地址分别 0x2000 55380x2000 5938,这个其实是有编译器决定的,是不固定的;起始地址后面紧跟的就是HEAP 和 STACK 的大小(size)。

若程序中完全没有使用 malloc 动态申请堆(HEAP)空间,编译器会优化,不把堆空间计算在内。

最后,这里再看下上面实例的MSP(R13,主堆栈指针)和PC(R15,程序计数器)初始化流程图:

4. 堆栈的实现 

STM32使用的是“向下生长的满栈”模型,堆栈指针 SP 指向最后一个被压入堆栈的 32位数值。

堆栈指针指向最后压入的堆栈的有效数据项,称为满栈;堆栈指针指向下一个要放入的空位置,称为空栈

为什么说“向上生长(向高地址方向生长)”和“向下生长(向低地址方向生长)”呢?那是因为,一般画堆栈示意图都是把低地址画在下面,高地址画在上面。如下图。

压栈(PUSH): SP 先自减 4,再存入新的数值。

出栈(POP):先从 SP 指针处读取上一次被压入的值,再把 SP 指针自增 4。

 虽然 POP 后被压入的数值还保存在栈中,但它已经无效了,因为为下次的 PUSH 将覆盖它的值!

5. 双堆栈机制

堆栈分为主堆栈(MSP)和进程堆栈(PSP),选择当前使用哪个堆栈指针由CONTROL寄存器(特殊功能寄存器)决定。

图5-1 特殊功能寄存器

当处理器处于线程模式时,控制寄存器控制所使用的堆栈和软件执行的特权级别,并指示 FPU 状态是否为活动的。

表5-1 Cortex-M4 的控制寄存器位定义
位(bits)功能(Function)
31:3Reserved
2

FPCA:指示当前浮点上下文是否活动:

0:不激活浮点上下文

1:表示浮点上下文活动。

Cortex-M4在处理异常时使用该位来决定是否保留浮点状态。

1

SPSEL:激活选择的堆栈指针。选择当前堆栈:

0:MSP是当前的堆栈指针

1:PSP是当前的堆栈指针。

在 Handle 模式下,该位读为零并忽略写。在异常返回时,Cortex-M4会自动更新此位。

0

nPRIV:线程模式权限级别。定义线程模式权限级别。

0:特权

1:无特权的。

在 Cortex‐M4 的 handler 模式中, CONTROL[1](CONTROL寄存器的bit[1])总是 0(Handle 模式下总是使用 MSP)。

当 CONTROL[1]=0 时,只使用 MSP,此时用户程序和异常 handler 共享同一个堆栈。这也是复位后的缺省使用方式。
 

CONTROL[1]=0 时的堆栈使用情况

当 CONTROL[1]=1 时,线程模式将不再使用 PSP,而改用 MSP( handler 模式永远使用 MSP)。
 

CONTROL[1]=1 时的堆栈使用情况

注意,在这种情况下,进入异常时的自动压栈使用的是进程堆栈,进入异常 handler 后才自动改为 MSP,退出异常时切换回 PSP,并且从进程堆栈上弹出数据。

在特权级下,可以直接对 MSP 和 PSP 执行读/写操作,而不会混淆你所引用的R13,示例代码如下:

MRS R0, MSP ; 读取主堆栈指针到 R0

MSR MSP, R0 ; 写入 R0 的值到主堆栈中

MRS R0, PSP ; 读取进程堆栈指针到 R0

MSR PSP, R0 ; 写入 R0 的值到进程堆栈中

通过MRS指令读取 PSP 的值,OS(操作系统) 可以读取用户应用程序堆积的数据(比如在系统服务调用前的寄存器内容,SVC)。此外,OS 可以改变 PSP 指针的值,例如,在多任务系统的上下文切换。


参考资料

  1. STM32F407数据手册 —— https://www.st.com/resource/en/datasheet/stm32f405rg.pdf
  2. STM32F407参考手册
  3. Cortex‐M3 权威指南(中文) 
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

STM32(F407)—— 堆栈 的相关文章

随机推荐

  • pycharm中做web应用(一)第一个web页

    目录 pycharm中做web应用 xff08 一 xff09 第一个web页Django 简介开发环境搭建django插件选择查看django版本 新项目创建启动项目web端验证项目 pycharm中做web应用 xff08 一 xff0
  • Matlab中利用FFT实现信号频谱搬移

    目录 Matlab中利用FFT实现信号频谱搬移只有实部的频谱搬移只有虚部的频谱搬移复函数下的频谱搬移 Matlab中利用FFT实现信号频谱搬移 在fft的理论中 xff0c fft的频移特性表示为 xff1a 也就是说 xff0c 要想对信
  • 解析IEC 61850通信规约

    目录 解析IEC 61850通信规约IEC61850适用场景IEC61850组成IEC61850库 解析IEC 61850通信规约 IEC61850标准是基于通用网络通信平台的变电站自动化系统唯一国际标准 xff0c 由国际电工委员会第57
  • C语言中的字符串转数字函数常见问题详解

    目录 C语言中的字符串转数字函数常见问题详解字符串转整形atoi函数 字符串转长整形strtol函数 xff0c C语言中的字符串转数字函数常见问题详解 字符串转整形 atoi函数 函数原型 xff1a int atoi const cha
  • 使用MATLAB进行三维空间绘图

    目录 使用MATLAB进行三维空间绘图一个入门例程matlab中的mesh 函数matlab中的meshgrid 函数matlab中的plot3函数例程代码解释 使用MATLAB进行三维空间绘图 三维图具有直观 立体的空间形象 xff0c
  • python特殊数据类型应用(2)元组类型

    目录 标题python特殊数据类型应用 xff08 2 xff09 元组类型元组的定义声明元组元组的访问元组和列表的相互转换元组和列表的区别 标题python特殊数据类型应用 xff08 2 xff09 元组类型 元组的定义 在python
  • python特殊数据类型应用(3)集合类型

    目录 python特殊数据类型应用 xff08 3 xff09 集合类型集合的定义集合的声明集合的运算集合元素的增加 xff1a 交集intersection 并集union差集difference xff1a 对称差集symmetric
  • python中字符串及其格式转换技巧

    目录 python中字符串及其格式转换技巧其他数据转为字符串字符串的格式化带格式限定符的格式化字符串的连接字符串切片字符串转换为 ASCII 值 python中字符串及其格式转换技巧 在python语言中 xff0c 对字符串的处理可以说是
  • Linux命令发送Http的get或post请求(curl和wget两种方法)

    xfeff xfeff Http请求指的是客户端向服务器的请求消息 xff0c Http请求主要分为get或post两种 xff0c 在Linux系统下可以用curl和wget命令来模拟Http的请求 下面就来介绍一下Linux系统如何模拟
  • 让bat文件后台运行

    让bat文件后台运行 文章目录 让bat文件后台运行 前言方法一方法二 前言 bat文件运行时会有一个黑黑的cmd exe窗口 xff0c 很吓人 xff0c 就算用start min命令去运行bat文件 xff0c 电脑的任务栏下仍然会有
  • 5.C语言中全局变量在多个文件中使用

    转自 xff1a https www eefocus com codevisionlife blog 13 12 300658 1a0b8 html 用C语言编写程序的时候 xff0c 我们经常会遇到这样一种情况 xff1a 希望在头文件中
  • 利用GitHub actions实现Docker Image的构建并传送到Docker Hub或者harbor

    目录 1 github actions的介绍 2 dockerfile 的编写 2 1 dockerfile 范例 2 2 其他指令 3 workflow的编写 3 1 上传到docker hub 3 2 上传到 harbor 4 结果展示
  • UCOSIII编写无人机飞控程序——第一篇

    研究无人机飞控已经接近两年 xff0c 作为一个业余的兴趣爱好 兴趣源于看到国外大神Raffaello D 39 Andrea在TED做的无人机演讲和展示 xff0c 感觉无人机很像工程师所施展的魔法 xff0c 给一向给人苦逼印象的工程师
  • 解决 Ubuntu :: Configure: Error: The QtCore Library >= 4.3.0 Could Not Be Found? 问题

    解决 Ubuntu Configure Error The QtCore Library gt 61 4 3 0 Could Not Be Found 问题 作者 19届YJF 日期 2020 10 2 这是我在打 robocup 2D仿真
  • 魔都,3年,程序员到CTO

    过一个平凡无趣的人生实在太容易了 xff0c 你可以不读书 xff0c 不冒险 xff0c 不运动 xff0c 不写作 xff0c 不外出 xff0c 不折腾 但是 xff0c 人生最后悔的事情就是 xff1a 我本可以 陈素封 我可以 在
  • 几种内存泄露检测工具的比较

    概述 内存泄漏 memory leak 指由于疏忽或错误造成程序未能释放已经不再使用的内存的情况 xff0c 在大型的 复杂的应用程序中 xff0c 内存泄漏是常见的问题 当以前分配的一片内存不再需要使用或无法访问时 xff0c 但是却并没
  • ubuntu查看磁盘占用和分配情况

    1 df hl Filesystem Size Used Avail Use Mounted on udev 978M 0 978M 0 dev tmpfs 200M 3 6M 197M 2 run dev sda5 28G 12G 15G
  • Android Studio主菜单(Main Menu)消失后,恢复显示

    当出现这个情况的时候 xff0c 我按找一般软件的办法找了半天也没找到 xff0c 最后没办法只能用万能的百度了 这里只记录一下当前我个人认为比较不错的方法 在Android Studio软件的右上角找到搜索 xff0c 输入Menu xf
  • github响应时间过长,无法访问此网站[已解决]

    某一天或某个时段总是出现 github 响应时间过长 xff0c 无法访问此网站的问题 获取github可以使用的DNS域名 通过站长工具 下的DNS查询 获取TTL值最小的 修改hosts配置 找到hosts xff08 域名解析文件 x
  • STM32(F407)—— 堆栈

    目录 1 SRAM 2 堆栈的作用 3 堆栈的设置 4 堆栈的实现 5 双堆栈机制 堆栈 是一种数据结构 堆栈都是一种数据项按序排列的数据结构 xff0c 只能在一端 称为栈顶 top 对数据项进行插入和删除 xff0c 相应地 xff0c