根据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(向下增长)

注意

  1. .data 段在 Flash 里存有初值,但运行时会被复制到 RAM
  2. .bss 段不会占用 Flash,但会在 RAM 里初始化为 0
  3. 栈和堆共享 RAM,栈 Stack 从 高地址→ 低地址方向增长。
  4. 堆 Heap 从 低地址→ 高地址 方向增长。
  5. 当 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,程序奔溃。

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

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

相关文章

软件设计师“测试用例”考点分析——求三连

一、测试用例设计核心要点解析 1. 白盒测试覆盖标准 (1)路径覆盖:需覆盖程序中所有可能的路径。如2018年真题路径覆盖需要3组测试用例(①②、①③、①③④),2020年流程图则需4个用例覆盖ace/abd/abe/acd四…

Linux 用户无法远程连接服务器

前言 昨天深夜一点多接到客户电话,客户说OS用户下午下班前还能正常登录。因为晚上一点半需要关闭所有服务进行迁移,但是用户无法登录了,导致后续流程无法执行。我让他先通过root用户紧急修改了密码,先保证业务正常流转。 问题 …

多模态大语言模型arxiv论文略读(八十八)

MammothModa: Multi-Modal Large Language Model ➡️ 论文标题:MammothModa: Multi-Modal Large Language Model ➡️ 论文作者:Qi She, Junwen Pan, Xin Wan, Rui Zhang, Dawei Lu, Kai Huang ➡️ 研究机构: ByteDance, Beijing, China ➡️ 问题背景…

svn迁移到git保留记录和Python字符串格式化 f-string的进化历程

svn迁移到git保留记录 and Python字符串格式化(二): f-string的进化历程 在将项目从SVN迁移到Git时,保留完整的版本历史记录非常重要。下面是详细的步骤和工具,可以帮助你完成这一过程: 安装Git和SVN工具 首先&#…

springboot配置mysql druid连接池,以及连接池参数解释

文章目录 前置配置方式参数解释 前置 springboot 项目javamysqldruid 连接池 配置方式 在 springboot 的 application.yml 中配置基本方式 # Druid 配置(Spring Boot YAML 格式) spring:datasource:url: jdbc:mysql://localhost:3306/testdb?useSSL…

vue实现高亮文字效果——advanced-mark.js

组件介绍-advanced-mark.js: advanced-mark.js 是一个用于 Vue 的高亮文字组件,它可以帮助你在文本中高亮显示指定的关键词或短语。 组件地址:https://angezid.github.io/advanced-mark.js/doc-v2/getting-started.html 主要功能&#xff1…

DC30V/2.5A同步降压芯片SL1581 输入24V降压5V 12V2A电流

在工业自动化、汽车电子等领域,24V 电源系统向 5V/12V 双轨供电的需求日益增长。针对这一痛点,森利威尔电子重磅推出 DC30V/2.5A 同步降压芯片 SL1581,凭借卓越的性能和创新设计,为工程师提供高可靠性、高性价比的电源解决方案。 …

React 第四十四节Router中 usefetcher的使用详解及注意事项

前言 useFetcher 是 React Router 中一个强大的钩子,用于在不触发页面导航的情况下执行数据加载(GET)或提交(POST)。 一、useFetcher 应用场景: 1、后台数据预加载(如鼠标悬停时加载数据&…

Jmeter(三) - 测试计划(Test Plan)的元件

1.简介 上一篇已经教你如何通过JMeter来创建一个测试计划(Test Plan),那么这一篇我们就将JMeter启动起来,创建一个测试计划(Test plan),给大家介绍一下测试计划(Test Plan&#xff…

应届本科生简历制作指南

一、找一个专业的简历模板 首先,你需要访问 Overleaf 的官方网站,也就是Overleaf, Online LaTeX Editor,进入页面后,点击注册按钮,按照提示填写相关信息来创建一个属于自己的账号,通常需要填写用户名、邮箱…

[Spring Boot]整合Java Mail实现Outlook发送邮件

日常开发过程中,我们经常需要使用到邮件发送任务,比方说验证码的发送、日常信息的通知等。日常比较常用的邮件发送方包括:163、QQ等,本文主要讲解Outlook SMTP的开启方式、OutLook STARTTTL的配置、如何通过JavaMail来实现电子邮件的发送等。 Outlook作为微软提供的企业电子…

【YOLOs-CPP-图像分类部署】03-解决报错

完整项目链接 点击here下载! 上一篇问题 经过上一篇博客,我们得到了一个粗略版(会报错)的项目。如何解决异常报错呢? 我把问题在github上对作者进行了提问,但是2天后,依然没有回复。 怎么办呢?只能自己调试代码了。 修改代码 经过大量调试,修改了YOLO11CLASS.h…

Dockers Compose常用指令介绍

Dockers Compose常用指令 1、常用指令介绍 1.1、version 指令 顶级一级指令,指定 compose 指定文件格式版本 version: "3.8" services: 不同版本支持的功能不同。常用版本有 ‘2’, ‘3’, ‘3.8’ 等。 1.2、services 指令 顶级一级指令&#xff0…

谢飞机的Spring WebFlux面试之旅:从基础到深入

谢飞机的Spring WebFlux面试之旅:从基础到深入 面试场景:谢飞机的WebFlux面试 面试官:你好,谢飞机,请介绍一下你自己。 谢飞机:您好,我是一名有三年开发经验的Java程序员,熟悉Spr…

Mysql增量备份与恢复

1.练习数据增量备份 增量备份:备份上次备份后,新产生的数据。 PERCONA Xtrabackup是一款强大的在线热备份工具,备份过程中不锁库表,适合生产环境。支持完全备份与恢复、增量备份与恢复、差异备份与恢复。 安装Xtrabackup 150、…

GStreamer (三)常⽤插件

常⽤插件 1、Source1.1、filesrc1.2. videotestsrc1.3. v4l2src1.4. rtspsrc和rtspclientsink 2、 Sink2.1. filesink2.2. fakesink2.3. xvimagesink2.4. kmssink2.5. waylandsink2.6. rkximagesink2.7. fpsdisplaysink 3 、视频推流/拉流3.1. 本地推流/拉流3.1.1 USB摄像头3.1…

Spring Boot与Kafka集成实践:实现高效消息队列

Spring Boot与Kafka集成实践 引言 在现代分布式系统中,消息队列是实现异步通信和解耦的重要组件。Apache Kafka作为一种高性能、分布式的消息队列系统,被广泛应用于大数据和实时数据处理场景。本文将介绍如何在Spring Boot项目中集成Kafka,…

Linux PXE批量装机+无人值守技术(自动化装机)

目录 PXE所需条件 服务端所需服务 客户端所需功能 1.准备系统安装rpm仓库 (1)安装vsftpd服务 (2)启动并设置开机自启 (3)准备yum仓库文件 2.安装配置dhcpd服务 (1)安装dhcoo软件包 (2)配置dhcp服务 (3)启动并设置开机自启 3.部署TFTP服务 (1)安装软…

linux_cmake的笔记

include_directories()的使用 今天在运行一个cmakelist.txt如下所示时候,发现一个问题: cmake_minimum_required(VERSION 3.28) project(l_trajectoryError CXX) option(USE_UBUNTU_20 "Set to ON if you are using Ubuntu 20.04" OFF) find…

论文略读:If Multi-Agent Debate is the Answer, What is the Question?

202502 arxiv 1 intro 多智能体辩论(Multi-Agent Debate, MAD):通过让多个智能体在大模型推理时展开多轮辩论,可提升生成内容的事实准确性和推理质量 但论文认为,目前多智能体辩论在大多数情况下不敌简单的单智能体方…