STM32 堆栈内存以及变量存储分布

news/2024/9/30 4:24:12/

 STM32的程序存储器、数据存储器、寄存器和输入输出端口被组织在同一个4GB的线性地址空间内, 地址范围为0x0000 0000至0xFFFF FFFF。其中FLASH为ROM类型,储存的数据掉电不易失;RAM中存储的数据掉电易失。以STM32F103系列为例,最多有512KB的FLASH空间以及最多64KB的RAM空间,另外还包含一个512字节的用于标准USB和CAN通信的SRAM。如下图所示:

一、FLASH分段


FLASH主要是存放代码和只读数据的,细分图如下:

        如上图所示,Flash又可以细分为文本段、只读数据段、数据复制段。其中文本段包含代码和代码中的常量部分,只读数据区通常存放程序中以const关键字修饰的数据,数据复制段存放的则是程序中初始化不为0的全局变量的数据,在每次单片机复位后要对这些变量重新赋值。

二、RAM分段

RAM主要用来存储数据,如下是STM32的RAM分区:

data段:存放初始化非0的全局变量;

bss段:存放未初始化或初始化为0的全局变量;

Heap(堆)段:由程序员通过malloc/free申请和释放;

Stack(栈)段:存放局部变量和函数的入口地址;

        其中栈的方向是由栈顶自上而下的,堆的方向则是自下而上的,如果RAM空间有限而且一个程序中局部变量较多或申请的堆空间过大,便会造成堆和栈冲突,并造成系统崩溃(自己暂时写的程序较小,暂时没有遇到过类似问题)。

        栈,也叫堆栈,是一种先进后出,插入和删除操作都在栈顶操作的线性表。栈的作用通常是保存函数返回地址及保存局部变量。每个函数在运行时都有自己的栈空间,局部变量越多,占空间占用越大,函数间调用越深,栈空间也越大。CPU将打断前的程序运行到的地址、寄存器的值保存到栈中,即保护现场;当打断执行完以后,又从栈中读取之前保存的值,即恢复现场。

对比keil编译显示的数据

  • Code=127668:这通常指的是程序的机器代码大小,它会被存储在Flash中。Flash是非易失性存储器,用于存储程序在设备断电后不会丢失的指令和数据。在大多数嵌入式系统中,程序代码(即机器指令)是预先编译好并存储在Flash中的。

  • RO-data=18372:只读数据(Read-Only Data)通常也存储在Flash中。它包含了程序中定义的常量值,如字符串字面量和常量变量。由于这些数据在程序运行时不会被修改,所以它们被存储在Flash中以节省SRAM空间。

  • RW-data=568:可读写数据(Read-Write Data)通常包含了程序中定义的初始化过的全局变量和静态变量。在程序启动时,这些数据通常需要从Flash中的某个位置复制到SRAM中,因为在程序运行时,这些变量可能会被修改。因此,RW-data的初始值存储在Flash中,而运行时的工作副本则存储在SRAM中。

  • ZI-data=46712:零初始化数据(Zero-Initialized Data)通常也存储在SRAM中。这部分内存区域在程序启动时会被初始化为零。它用于存储未显式初始化的全局变量和静态变量。由于这些变量在程序开始时没有明确的初始值,所以它们在SRAM中被分配空间,并在启动时自动清零。

总结起来

   CodeRO-data通常存储在Flash中,而RW-dataZI-data则与SRAM相关。RW-data的初始值存储在Flash中,但在运行时,它的工作副本位于SRAM中。而ZI-data仅存在于SRAM中,用于存储未初始化的变量。这样的内存布局有助于优化嵌入式系统的性能,同时确保程序能够正确执行。SRAM其本身其实是不会存储数据的,这些都是在运行状态时,从flash中复制加载过去的,但编译器会提前更具你的SRAM大小判断是否存在内存溢出。


http://www.ppmy.cn/news/1431150.html

相关文章

Git 创建版本库

Git 创建版本库 | CoderMast编程桅杆Git 创建版本库 在 Git 上创建版本库有两种方式,一种是直接拷贝远程 Git 仓库到本地,另外一种是我们自己创建本地的版本库。 拷贝远程仓库 拷贝远程仓库时我们需要知道远程仓库的URL地址,直接使用如下命令…

K8S Pod 常见问题

Pod 常见问题 调试 Pod 查看 Pod 的当前状态和最近的事件 kubectl describe pods php-apache-7d4456444b-rdd4t查看一下 Pod 中的容器所处的状态。这些容器的状态都是 Running 吗?最近有没有重启过? 后面的调试都是要依靠 Pod 的状态的。 Pod 在 Pen…

【车载Android】模拟Android系统的高负载环境

在开发车载Android应用和系统时,我们总会面临着一些挑战,尤其是处理高负载应用。例如,当一款新车型发布后,用户可能会同时运行地图、智能驾驶和爱奇艺等资源密集型应用。在这种情况下,如果用户尝试使用语音唤醒功能&am…

【ChatGPT】【Gemini】-用Python调用google的Gemini API

用Python调用google的Gemini API 以下是Gemini自己给出的具体步骤和代码,我直接参考一次测试通过,大家可以参考。 Goodmao:Python call gemini API Gemini: Absolutely, calling the Gemini API with Python involves a few st…

php时间人性化展示

在PHP中,可以使用date()函数和strtotime()函数来实现时间的人性化展示。下面是一个示例代码: <?php // 获取当前时间戳 $timestamp = time();// 格式化时间 $formattedTime = date(Y年m月d日 H:i:s, $timestamp);echo

Java面试题:什么是Java中的单元测试以及如何编写单元测试?

Java中的单元测试是一种软件开发方法&#xff0c;用于验证代码中的最小可测试单元&#xff08;通常是方法或类&#xff09;是否按预期工作。单元测试的目标是隔离代码的各个部分&#xff0c;并验证每个部分是否都能正确执行其预期的功能。 在Java中&#xff0c;JUnit是最常用的…

Python 中的return语句用法,返回的数据类型

return 语句在 Python 中用于从一个函数中退出&#xff0c;并将表达式的值&#xff08;如果存在&#xff09;传递回给调用者。 1&#xff0c;return 语句的核心用法 1.1 返回值 当你想从函数中得到一个结果并用这个结果继续在其他地方执行时&#xff0c;可以使用 return 后紧…

怎么通过Javascript脚本实现远程控制一路开关

怎么通过Javascript脚本实现远程控制一路开关呢&#xff1f; 本文描述了使用Javascript脚本调用HTTP接口&#xff0c;实现控制一路开关。一路开关可控制一路照明、排风扇等电器。 可选用产品&#xff1a;可根据实际场景需求&#xff0c;选择对应的规格 序号设备名称1智能WiFi…