Keil中内存概念:Flash、SRAM、RO、RW、ZI、.data、.bss、heap、stack、MAP文件

news2026/4/4 14:18:38
此文章转载于微信公众号嵌入式电子学习只作为笔记备忘录使用内存属性理解Keil MDK或ARM编译器中关于程序内存布局的一些基本概念RO、RW、ZI和.data、.bss、heap、stack、Flash、SRAM。这些概念对于理解程序如何被加载和运行以及如何优化内存使用至关重要。1. 基础概念详解1.1 存储介质分类Flash非易失性存储• 特点掉电数据不丢失读取速度快写入速度慢• 存储内容程序代码、常量数据、初始化数据• 访问方式直接读取需要通过特定接口编程RAM易失性存储• 特点掉电数据丢失读写速度快• 存储内容变量、堆栈、运行时数据• 访问方式直接读写1.2 程序段分类RORead Only段•存储位置Flash•包含内容• 程序代码.text段• 只读数据.rodata段• 常量字符串、const变量•特点运行时不可修改RWRead Write段•存储位置Flash中存初始值RAM中存运行时值•包含内容已初始化且非零的全局/静态变量•特点启动时需要从Flash复制到RAMZIZero Initialized段•存储位置RAM•包含内容未初始化或显式初始化为0的全局/静态变量•特点启动时清零初始化1.3 常见段名与内存区域•.text表示代码段Code存放在Flash中。•.constdata 或 .rodata只读数据段RO存放在Flash中。•.data已初始化的全局变量和静态变量RW数据在Flash中保存初始值在RAM中存放运行时值。•.bss未初始化的全局变量和静态变量ZI数据在RAM中程序启动时初始化为0堆和栈属于.bss。• 栈stack用于局部变量、函数调用等由编译器自动管理通常从RAM的高地址向低地址增长。• 堆heap用于动态内存分配由程序员管理malloc/free通常从RAM的低地址向高地址增长。1.4 加载域和执行域1、加载区域表示代码和数据下载到芯片时存储到哪段地址可以存储到片上Flash也可以存储到片外Flash也可以存储到RAM。• 对于代码为只读类型运行时无法更改因此存储在Flash中即加载区域是Flash地址段。• 对于数据其分成几类:• 对于RO只读数据比如const类型、字符串等等其存储在Flash因此加载区域也是Flash地址段• 对于RW读写数据比如.data如果其有初值那么初值要存放在Flash中运行时先从Flash中取出初值对RW数据进行赋值然后运行时RW数据的访问地址是在RAM里也就是RW数据的加载区域是Flash地址段执行区域是RAM地址段• 对于ZI数据比如.bss和stack、heap表示初始化为零的全局变量因此无需在Flash中存放初值也就无所谓加载区域只有执行区域执行区域也就是程序运行时如果要访问这个变量要去哪个地址段寻找。2、执行区域表示上电运行后程序和数据从哪个地址开始执行或访问。• 对于代码也就是从哪个地址开始读取代码语句并执行一般是程序存储在哪里就从哪里执行代码的执行区域和加载区域保持一致。• 对于数据表示程序运行起来后去哪个地址可以访问数据。• 对于RO数据例如const需要存储在Flash中因此其加载区域地址就处在Flash中程序运行起来后也是去Flash地址段访问const变量因此其执行区域也是Flash地址段两个区域保持一致• 对于RW数据如果初值不为零那么初值需要存储到Flash中即使初值为零加载区域似乎也是Flash段则其加载区域是Flash地址段运行时访问RW数据则要去RAM里因此执行区域是RAM地址段。参考文章内存分配基础2简单例子2. 内存区域详细对应关系2.1 编译时段的映射2.2 详细对应表内存区域对应段存储介质初始化方式内容示例.textROFlash编译时确定函数代码、中断向量表.rodataROFlash编译时确定const常量、字符串常量.dataRWFlashRAM启动时从Flash复制int a 100;.bssZIRAM启动时清零int b; 或 int c 0;heapZI(动态)RAM运行时分配malloc()分配的内存stackZI(动态)RAM运行时压栈局部变量、函数参数3. 启动过程分析系统上电后首先从Flash中读取代码和数据进行初始化。具体步骤1. 初始化栈指针SP和程序计数器PC。2. 将RW数据从Flash中复制到RAM中这部分数据在Flash中紧跟在RO数据之后。3. 将ZI数据所在的RAM区域全部清零。4. 跳转到main函数执行。参考文章上电启动3从复位到main()的启动文件详解万字长文整理4. Map文件解析Map文件展示了程序的内存布局包括各个段的大小、地址分配等。通过Map文件我们可以查看• 代码段、RO数据段、RW数据段、ZI数据段的大小和位置。• 各个模块源文件占用的代码和数据空间。4.1 Map文件分析1. 模块摘要 Module Summary: Code (inc. data) RO Data RW Data ZI Data Debug Object Name 1200 200 400 100 500 8000 main.o 800 150 200 50 300 6000 library.o可以看到用户每个源文件所占据内存大小inc表示内联函数和数据。2. 总内存占用 Total RO Size (Code RO Data) 1600 ( 1.56kB) Total RW Size (RW Data ZI Data) 900 ( 0.88kB) Total ROM Size (Code RO Data RW Data) 1700 ( 1.66kB)汇总看到整个工程所占据的Flash和SRAM空间。3. 内存区域分布 Memory Map of the image: Flash区域 Load Region LR_FLASH (Base: 0x08000000, Size: 0x00000800, Max: 0x00080000) Execution Region ER_FLASH (Base: 0x08000000, Size: 0x00000650) Base Addr Size Type Attr Idx E Section Name Object 0x08000000 0x00000200 Code RO 1 .text startup_stm32f10x.o 0x08000200 0x00000400 Data RO 2 .constdata main.o RAM区域 Execution Region RW_IRAM1 (Base: 0x20000000, Size: 0x00000400) Base Addr Size Type Attr Idx E Section Name Object 0x20000000 0x00000100 Data RW 10 .data main.o 0x20000100 0x00000200 Zero RW 11 .bss main.o 0x20000300 0x00000100 Zero RW 12 heap .o可以看到Flash和SRAM中具体的每一段地址存放了哪些数据和代码。4.2 关键指标解读编译信息解读Program Size: Codexxxx RO-dataxxxx RW-dataxxxx ZI-dataxxxx•Code: 实际代码大小存储在Flash中•RO-data: 只读数据大小存储在Flash中•RW-data: 已初始化的读写数据大小在Flash中存储初始值在RAM中占用相同大小的空间•ZI-data: 零初始化数据大小在RAM中占用空间但不在Flash中占用空间除了初始化为0的说明信息但不占用实际数据空间重要计算公式Flash占用 Code RO Data RW Data的初始值 RAM占用 RW Data ZI Data Stack Heap注意RW数据在Flash和RAM中各有一份Flash中存储的是初始值RAM中是运行时的值。5. 内存优化5.1 常见优化方法通过理解这些概念我们可以有针对性地优化程序• 减少全局变量的使用特别是已初始化的全局变量RW数据和未初始化的全局变量ZI数据可以节省RAM空间。• 将常量数据尽量使用const关键字定义为只读数据使其存储在Flash中而不是RAM中。• 优化代码大小减少Flash占用。• 合理设置堆栈大小避免溢出。5.2 优化建议说明int global_var 100;• 定义一个全局变量带有非零初始值属于RW数据在Flash中存储初始值100在RAM中有一个变量占4字节。int global_var2;• 定义一个全局变量零初始值属于ZI数据在RAM中占4字节启动时被初始化为0。const int global_const 200;• 定义一个const数据属于RO数据存储在Flash中不占用RAM。• 堆和栈的大小通常由启动文件startup.s中的设置决定在Map文件中可以查看它们的地址范围。查看MAP文件• 查看各个模块的代码和数据占用找出占用较大的模块进行优化。• 检查RW和ZI数据的大小优化全局变量和静态变量的使用。• 确认堆栈大小是否足够避免堆栈溢出。优化方向• 如果Flash紧张可以优化代码和常量数据例如使用更高效的算法减少常量数据如字符串、数组等。• 如果RAM紧张可以减少全局变量和静态变量使用局部变量栈上分配减少动态内存分配堆等。• 注意栈和堆的增长方向以及边界检查很重要如果堆和栈发生重叠会导致程序崩溃。因此需要合理设置堆栈大小并可能使用内存保护功能。在代码中监控堆栈使用。/*********************************************************************************************************************** * Function Name: StackFillMagic * Description : 初始化阶段调用一次将栈区全部填充幻数 * Arguments : None * Return Value : None ***********************************************************************************************************************/ void StackFillMagic(void) { uint32_t* base __base_sp; //栈顶边界 uint32_t* top (uint32_t*)__get_MSP(); //这里要使用当前栈指针 while(base top) { * base 0xDEADBEEF; //填充幻数 } }/*********************************************************************************************************************** * Function Name: CheckStackOverflow * Description : 程序运行过程中一直调用此函数检测栈空间使用是否溢出 * Arguments : None * Return Value : None ***********************************************************************************************************************/ uint16_t CheckStackOverflow(void) { uint16_t use_size 0; uint32_t* base __base_sp; //栈顶边界 while(*base 0xDEADBEEF base (__initial_sp)) { base; //检查哪些地方的数据不是幻数表示此区域已经使用了 } use_size (base - (__base_sp))*sizeof(uint32_t); //字节个数 return (use_size); }5.3 优化检查项• 检查全局变量是否必要能否改为局部变量• 常量数据使用const修饰确保存储在Flash• 大数组考虑使用动态分配或放在特定内存区域• 定期检查堆栈使用情况避免溢出• 使用合适的编译优化选项-Os, -O2等• 分析Map文件找出内存占用大的模块

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2482474.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SpringBoot-17-MyBatis动态SQL标签之常用标签

文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…

wordpress后台更新后 前端没变化的解决方法

使用siteground主机的wordpress网站,会出现更新了网站内容和修改了php模板文件、js文件、css文件、图片文件后,网站没有变化的情况。 不熟悉siteground主机的新手,遇到这个问题,就很抓狂,明明是哪都没操作错误&#x…

网络编程(Modbus进阶)

思维导图 Modbus RTU(先学一点理论) 概念 Modbus RTU 是工业自动化领域 最广泛应用的串行通信协议,由 Modicon 公司(现施耐德电气)于 1979 年推出。它以 高效率、强健性、易实现的特点成为工业控制系统的通信标准。 包…

UE5 学习系列(二)用户操作界面及介绍

这篇博客是 UE5 学习系列博客的第二篇,在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下: 【Note】:如果你已经完成安装等操作,可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作,重…

IDEA运行Tomcat出现乱码问题解决汇总

最近正值期末周,有很多同学在写期末Java web作业时,运行tomcat出现乱码问题,经过多次解决与研究,我做了如下整理: 原因: IDEA本身编码与tomcat的编码与Windows编码不同导致,Windows 系统控制台…

利用最小二乘法找圆心和半径

#include <iostream> #include <vector> #include <cmath> #include <Eigen/Dense> // 需安装Eigen库用于矩阵运算 // 定义点结构 struct Point { double x, y; Point(double x_, double y_) : x(x_), y(y_) {} }; // 最小二乘法求圆心和半径 …

使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式

一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明&#xff1a;假设每台服务器已…

XML Group端口详解

在XML数据映射过程中&#xff0c;经常需要对数据进行分组聚合操作。例如&#xff0c;当处理包含多个物料明细的XML文件时&#xff0c;可能需要将相同物料号的明细归为一组&#xff0c;或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码&#xff0c;增加了开…

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造&#xff0c;完美适配AGV和无人叉车。同时&#xff0c;集成以太网与语音合成技术&#xff0c;为各类高级系统&#xff08;如MES、调度系统、库位管理、立库等&#xff09;提供高效便捷的语音交互体验。 L…

(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)

题目&#xff1a;3442. 奇偶频次间的最大差值 I 思路 &#xff1a;哈希&#xff0c;时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况&#xff0c;哈希表这里用数组即可实现。 C版本&#xff1a; class Solution { public:int maxDifference(string s) {int a[26]…

【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型

摘要 拍照搜题系统采用“三层管道&#xff08;多模态 OCR → 语义检索 → 答案渲染&#xff09;、两级检索&#xff08;倒排 BM25 向量 HNSW&#xff09;并以大语言模型兜底”的整体框架&#xff1a; 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后&#xff0c;分别用…

【Axure高保真原型】引导弹窗

今天和大家中分享引导弹窗的原型模板&#xff0c;载入页面后&#xff0c;会显示引导弹窗&#xff0c;适用于引导用户使用页面&#xff0c;点击完成后&#xff0c;会显示下一个引导弹窗&#xff0c;直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…

接口测试中缓存处理策略

在接口测试中&#xff0c;缓存处理策略是一个关键环节&#xff0c;直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性&#xff0c;避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明&#xff1a; 一、缓存处理的核…

龙虎榜——20250610

上证指数放量收阴线&#xff0c;个股多数下跌&#xff0c;盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型&#xff0c;指数短线有调整的需求&#xff0c;大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的&#xff1a;御银股份、雄帝科技 驱动…

观成科技:隐蔽隧道工具Ligolo-ng加密流量分析

1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具&#xff0c;该工具基于TUN接口实现其功能&#xff0c;利用反向TCP/TLS连接建立一条隐蔽的通信信道&#xff0c;支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式&#xff0c;适应复杂网…

铭豹扩展坞 USB转网口 突然无法识别解决方法

当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…

未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?

编辑&#xff1a;陈萍萍的公主一点人工一点智能 未来机器人的大脑&#xff1a;如何用神经网络模拟器实现更智能的决策&#xff1f;RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战&#xff0c;在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…

Linux应用开发之网络套接字编程(实例篇)

服务端与客户端单连接 服务端代码 #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <pthread.h> …

华为云AI开发平台ModelArts

华为云ModelArts&#xff1a;重塑AI开发流程的“智能引擎”与“创新加速器”&#xff01; 在人工智能浪潮席卷全球的2025年&#xff0c;企业拥抱AI的意愿空前高涨&#xff0c;但技术门槛高、流程复杂、资源投入巨大的现实&#xff0c;却让许多创新构想止步于实验室。数据科学家…

深度学习在微纳光子学中的应用

深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向&#xff1a; 逆向设计 通过神经网络快速预测微纳结构的光学响应&#xff0c;替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…