根据Cortex-M3(包括STM32F1)权威指南讲解MCU内存架构与如何查看编译器生成的地址具体位置
首先我们先查看官方对于Cortex-M3预定义的存储器映射
1.存储器映射
1.1 Cortex-M3架构的存储器结构
内部私有外设总线:即AHB总线,包括NVIC中断,ITM硬件调试,FPB, DWT。
外部私有外设总线:即APB总线,用于内部“外设”的操作(SPI,IIC,USART)等,也用于些片上APB外设到APB私有总线上(SD卡,LCD显示屏)的访问。
他们的物理地址关系如下图所示:
2.RAM和FLASH的基本概念与作用
从上面的描述可以知道,其实Cortex-M3分配的地址很多都是不允许修改的,能修改的只有代码区的FLASH和上电后代码运行的片上SRAM区的RAM,我们这章就着重讲一下这两个地方。
1.2.1RAM的基本概念与作用
RAM(随机存取存储器)在STM32中主要用于存储运行时的数据和变量。它是易失性存储器,断电后数据会丢失。RAM的作用包括:
- 存储程序运行时的临时数据,如局部变量、堆栈和动态分配的内存。
- 提供快速的数据访问,支持CPU的高效运行。
- 用于存储中断向量表、全局变量和静态变量。
1.2.2 FLASH的基本概念与作用
FLASH存储器在STM32中用于存储程序代码和常量数据。它是非易失性存储器,断电后数据不会丢失。FLASH的作用包括:
- 存储固件程序代码,包括主程序、中断服务程序和库函数。
- 存储常量数据,如查找表、配置参数和字符串。
- 支持程序更新和固件升级,通过编程接口可以擦除和写入数据。
1.2.3 程序的典型内存分布和用途
内存分布:
+------------------+ 0x20005000 (RAM 结束)
| Heap | 动态分配(malloc)
+------------------+
| Stack | 栈(局部变量、返回地址)
+------------------+
| .bss | 未初始化数据(RAM)
+------------------+
| .data | 已初始化全局变量(RAM)
+------------------+ 0x20000000 (RAM 起始)+------------------+ 0x08010000 (Flash 结束)
| .rodata | 只读数据(Flash)
+------------------+
| .text | 代码段(Flash)
+------------------+ 0x08000000 (Flash 起始)
各个区域用途:
存储区域 | 用途 | 存储位置 |
---|---|---|
.text(Code) | 存放编译后的程序指令(代码) | Flash(只读) |
.rodata(RO-data) | 存放只读常量(const 变量等) | Flash(只读) |
.data(RW-data) | 已初始化的全局/静态变量 | Flash + RAM |
.bss(ZI-data) | 未初始化的全局/静态变量,启动时清零 | RAM(自动清零) |
Heap(堆) | malloc() 动态分配的内存 | RAM(向上增长) |
Stack(栈) | 局部变量、函数调用返回地址 | RAM(向下增长) |
注意:
.data
段在 Flash 里存有初值,但运行时会被复制到 RAM。.bss
段不会占用 Flash,但会在 RAM 里初始化为 0。- 栈和堆共享 RAM,栈 Stack 从 高地址→ 低地址方向增长。
- 堆 Heap 从 低地址→ 高地址 方向增长。
- 当 Stack 和 Heap 彼此增长到一个临界点(即二者相遇),就会导致 Stack Overflow(栈溢出)。
下面举一个例子供大家更深入了解代码变量的存储方式:
int a = 0; //全局初始化区
char *p1; //全局未初始化区
main()
{ int b;//栈 char s[] = "abc";//栈 char * p2;//栈 char * p3 = "123456";//123456\0在常量区,p3在栈上。 static int c =0;//全局(静态)初始化区 p1 = (char *)malloc(10);//堆 p2 = (char *)malloc(20);//堆
}
3.如何查看自己代码的各个区的地址位置
3.1 为什么要查看各个区的地址
虽然我们在官方文档中知道了Cortex-M3的各个部分的大概范围,但我们使用CUBEMX或者操作系统生成的项目肯定不会规规矩矩的完全按照官方文档的推荐来配置各个区。有时候推荐的去大小没占完,你不知道结束地址。比如RT-Thread的内存管理将.data段和.bss段也一起管理起来了,创建各种任务所使用的内存都由RT-Thread统一分配。或者在CUBEMX中你可以自行设计堆区和栈区的大小等等。
而我们在使用内存管理的时候开辟一个专门存放变量的空间,我们需要的不只是简单的知道这个变量的大小,我们还需要知道它的地址(要不然你使用这个变量,还要编译器找这个地址在哪里,这样才能提升项目的管理分配和运行效率,那根我直接开辟一个变量有什么区别?)而我开辟的地方也有讲究,因为只有Heap(堆区)才能给与我们自由分配空间并进行读写的权利。因此找到各个区的地址我认为是有必要的。
那我们应该怎么找到各个区的地址呢?
那就是查看代码编译后生成的.map文件
3.2 解析查找地址的.map文件的代码含义
代码来源:https://www.waveshare.net/w/upload/3/39/E-Paper_code.7z
注意:你要使用了malloc等函数才会存在heap区的开辟,要不然你在.map文件中是找不到heap的创建地址的。
我们得到了下面的关于堆的说明
HEAP 0x200002e0 Section 49152 startup_stm32f103xe.o(HEAP)
STACK 0x2000c2e0 Section 4096 startup_stm32f103xe.o(STACK)
__heap_base 0x200002e0 Data 0 startup_stm32f103xe.o(HEAP)
__heap_limit 0x2000c2e0 Data 0 startup_stm32f103xe.o(HEAP)
__initial_sp 0x2000d2e0 Data 0 startup_stm32f103xe.o(STACK)
HEAP:是堆的基地址
__initial_sp:是栈的起始地址(栈顶)。
__heap_base
:堆的起始地址。
__heap_limit
:堆的结束地址。
示意图如下
4. 总结
如果我们设置了堆的空间大小,但是我们程序中没有进行malloc申请,那么在程序事假运行的时候,我们栈的空间超过本身设置的空间,进入到堆里面,那么程序是不会出错的,但是超过了堆的空间了,进入到全局变量区域,就会出现莫名其妙的错误。
不使用malloc,我们可以将堆设置成0,这是没有问题的,但是栈的空间大小要设置成合适的,不然就会因为栈溢出,进入harderror,程序奔溃。
相关文章:

根据Cortex-M3(包括STM32F1)权威指南讲解MCU内存架构与如何查看编译器生成的地址具体位置
首先我们先查看官方对于Cortex-M3预定义的存储器映射 1.存储器映射 1.1 Cortex-M3架构的存储器结构 内部私有外设总线:即AHB总线,包括NVIC中断,ITM硬件调试,FPB, DWT。 外部私有外设总线:即APB总线,用于…...
vue的h函数(在 Vue 2中也称为 createElement)理解
官方定义 定义: 返回一个“虚拟节点” ,通常缩写为 VNode: 一个普通对象,其中包含向 Vue 描述它应该在页面上呈现哪种节点的信息,包括对任何子节点的描述。用于手动编写render h函数格式说明及使用 h 接收三个参数 type: 必需,…...

MCP入门实战(极简案例)
MCP简介 MCP(Model Context Protocol,模型上下文协议)2024年11月底由 Antbropic 推出的一种开放标准,旨在统一大型语言模型(LLM)与外部数据源和工具之间的通信协议。 Function Calling是AI模型调用函数的机制,MCP是一个标准协议,使AI模型与API无缝交互,而Al Agent是一个…...
STM32中,如何理解看门狗
在STM32微控制器中,看门狗(Watchdog)是一种硬件计时器,用于监控系统运行状态,防止软件死锁或跑飞。其核心机制是:系统需定期“喂狗”(复位看门狗计数器),若未及时喂狗&am…...

Cursor从入门到精通实战指南(一):开始使用Cursor
一、简介与核心优势 Cursor是一款基于VSCode开发的AI编程工具,集成了GPT-4、Claude 3.5等先进大语言模型,支持代码补全、生成、重构、调试等功能。其核心优势包括: 高效协作:通过自然语言对话实现代码开发,支持跨文件…...
麒麟v10+信创x86处理器离线搭建k8s集群完整过程
前言 最近为某客户搭建内网的信创环境下的x8s集群,走了一些弯路,客户提供的环境完全与互联网分离,通过yum、apt这些直接拉依赖就别想了,用的操作系统和cpu都是国产版本,好在仍然是x86的,不是其他架构&…...

计算机组成原理——cache
3.4cache 出自up主Beokayy传送门 1.局部性原理 时间局部性: 在最近的未来要用到的信息,很可能是现在正在使用的信息,因为程序中存在循环。 空间局部性: 在最近的未来要用到的信息,很可能与现在正在使用的信息在存储…...

EasyExcel使用导出模版后设置 CellStyle失效问题解决
EasyExcel使用导出模版后在CellWriteHandler的afterCellDispose方法设置 CellStyle失效问题解决方法 问题描述:excel 模版塞入数据后,需要设置单元格的个性化设置时失效,本文以设置数据格式为例(设置列的数据展示时需要加上千分位…...
关于AWESOME-DIGITAL-HUMAN的部署
AWESOME-DIGITAL-HUMAN是一个开源数字人项目,可以容器化部署,资源占用少,可以对接dify,使用起来也很方便,非常感谢开发者。 容器化部署后,其实是有两个容器,分别启动两个服务,一个前…...
WebAssembly 及 HTML Streaming:重塑前端性能与用户体验
WebAssembly 及 HTML Streaming:重塑前端性能与用户体验 引言 在移动互联网时代,用户对 Web 应用的性能和体验要求日益苛刻。白屏时间、首屏渲染速度、交互流畅度,甚至 SEO 优化,都成为前端工程师必须面对的挑战。传统的前端技术…...
python同步mysql数据
python写了一个简单的mysql数据同步脚本,只作为学习练习,大佬勿喷 # -*- coding: utf-8 -*- """ Time:2025/5/29 14:38 Auth:HEhandsome """ import pymysql from pymysql import Connectclass Mysql:def __init__(self):#源数据库self.sou_hos…...
shell之通配符及正则表达式,grep参数
通配符与正则表达式 通配符(Globbing) 通配符是由 Shell 处理的特殊字符,用于路径或文件名匹配。当 Shell 在命令参数中遇到通配符时,会将其扩展为匹配的文件路径;若没有匹配项,则作为普通字符传递给命令…...
RuoYi前后端分离框架集成手机短信验证码(一)之后端篇
一、背景 本项目基于RuoYi 3.8.9前后端分离框架构建,采用Spring Security实现系统权限管理。作为企业级应用架构的子模块,系统需要与顶层项目实现用户数据无缝对接(以手机号作为统一用户标识),同时承担用户信息采集的重要职能。为此,我们在保留原有账号密码登录方式的基…...

Knife4j框架的使用
文章目录 引入依赖配置Knife4j使用Knife4j 访问 SpringBoot 生成的文档 Knife4j 是基于 Swagger 的增强工具,对 Swagger 进行了拓展和优化,从而有更美观的界面设计和更强的功能 引入依赖 Spring Boot 2.7.18 版本 <dependency> <groupId>c…...

深兰科技陈海波率队考察南京,加速AI医诊大模型区域落地应用
近日,深兰科技创始人、董事长陈海波受邀率队赴南京市,先后考察了南京江宁滨江经济开发区与鼓楼区,就推进深兰AI医诊大模型在南京的落地应用,与当地政府及相关部门进行了深入交流与合作探讨。 此次考察聚焦于深兰科技自主研发的AI医…...

【芯片设计中的交通网络革命:Crossbar与NoC架构的博弈C架构的博弈】
在芯片设计领域,总线架构如同城市交通网,决定了数据流的通行效率。随着AI芯片、车载芯片等复杂场景的爆发式增长,传统总线架构正面临前所未有的挑战。本文将深入解析两大主流互连架构——Crossbar与NoC的优劣,揭示芯片"交通网…...

deepseek告诉您http与https有何区别?
有用户经常问什么是Http , 什么是Https ? 两者有什么区别,下面为大家介绍一下两者的区别 一、什么是HTTP HTTP是一种无状态的应用层协议,用于在客户端浏览器和服务器之间传输网页信息,默认使用80端口 二、HTTP协议的特点 HTTP协议…...

mac将自己网络暴露到公网
安装服务 brew tap probezy/core && brew install cpolar// 安装cpolar sudo cpolar service install // 启动服务 sudo cpolar service start访问管理网站 http://127.0.0.1:9200/#/tunnels/list 菜单“隧道列表” 》 编辑 自定义暴露的端口 再到在线列表中查看公网…...
考研政治资料分享 百度网盘
考研资料分享考研资料合集 百度网盘(仅供参考学习) 通过网盘分享的文件:2026考研英语数学政治最新等3个文件 链接: https://pan.baidu.com/s/1iK2LvbkoreNxHZ7fmOkcyQ?pwd4drt 提取码: 4drt 链接: https://pan.baidu.com/s/1FuNV…...

拓扑排序算法剖析与py/cpp/Java语言实现
拓扑排序算法深度剖析与py/cpp/Java语言实现 一、拓扑排序算法的基本概念1.1 有向无环图(DAG)1.2 拓扑排序的定义1.3 拓扑排序的性质 二、拓扑排序算法的原理与流程2.1 核心原理2.2 算法流程 三、拓扑排序算法的代码实现3.1 Python实现3.2 C实现3.3 Java…...

罗马-华为
SPA应用:single-page application:单页应用SPA是一种网络应用程序或网站的模型,它通过动态重写当前页面来与用户交互,这种方法避免了页面之间切换打断用户体验在单页应用中 集成 ROMA Connect 主要包含四个组件:数据集成( FDI )、服务集成( APIC )、消息集成 ( MQS …...
单例模式的隐秘危机
引言 单例模式作为设计模式中的基石,广泛应用于配置管理、线程池、缓存系统等关键场景。然而,许多开发者误以为“私有构造函数”足以保障其唯一性,却忽视了反射机制、对象克隆、序列化反序列化这三把“隐形利刃”——它们能绕过常规防御&…...
微信小程序常用方法
微信小程序 常用方法 setData() https://developers.weixin.qq.com/miniprogram/dev/reference/api/Page.html#%E7%BB%84%E4%BB%B6%E4%BA%8B%E4%BB%B6%E5%A4%84%E7%90%86%E5%87%BD%E6%95%B0 在微信小程序中,setData 是一个非常重要的方法,主要用于更新…...

切片器导航-大量报告页查看的更好方式
切片器导航-大量报告页查看的更好方式 现在很多报告使用的是按钮导航,即使用书签按钮来制作页面导航的方式。但是当我们的报告有几十页甚至上百页的时候,使用书签按钮来制作页面导航,无论是对于报表制作者还是报告使用者来说都是一种很繁琐的…...
火山引擎声音复刻
首先,我需要确定火山引擎是什么,扣子声音复刻具体指什么。火山引擎是字节跳动旗下的云服务平台,提供各种技术解决方案。声音复刻应该属于他们的AI语音相关服务。 接下来,用户可能想知道这个功能的应用场景。比如,企业用…...
【数据分析】Pandas
目录 🌟 前言🏗️ 技术背景与价值🩹 当前技术痛点🛠️ 解决方案概述👥 目标读者说明 🧠 一、技术原理剖析📊 核心概念图解💡 核心作用讲解🔧 关键技术模块说明⚖️ 技术选…...
【ROS2】Qt Debug日志重定向到ROS2日志管理系统中
1、注册消息处理函数 Qt 利用 qInstallMessageHandler 接口可以 注册消息处理函数; 将QDebug等输出重定向到ROS2的日志管理中,使用 RCLCPP_DEBUG 输出日志 示例: 1)定义消息处理函数 namespace GW {void ros2Logger(QtMsgType type, const QMessageLogContext &cont…...
经典SQL查询问题的练习第一天
首先有三张表,学生表、课程表、成绩表 student:studentId,studentName; course:courseId,courseName,teacher; score:score,studentId,courseId; 接着有以下几道题目: ①查询课程编号为‘0006’的总成绩: 首先总成绩&#x…...

ubuntu 22.04安装k8s高可用集群
文章目录 1.环境准备(所有节点)1.1 关闭无用服务1.2 环境和网络1.3 apt源1.4 系统优化1.5 安装nfs客户端 2. 装containerd(所有节点)3. master的高可用方案(master上操作)3.1 安装以及配置haproxyÿ…...

使用java实现word转pdf,html以及rtf转word,pdf,html
word,rtf的转换有以下方案,想要免费最靠谱的是LibreOffice方案, LibreOffice 是一款 免费、开源、跨平台 的办公软件套件,旨在为用户提供高效、全面的办公工具,适用于个人、企业和教育机构。它支持多种操作系统(Windows、macOS、…...