STM32三种BOOT模式下内存地址分配比较

本文目的是通过在stm32最小系统板上练习三种不同的启动模式条件下,C程序编译后在stm32内存中的分配情况。

(一)stm32的三种启动模式

stm32上电或者复位后程序的启动模式根据BOOTT[1:0]引脚选择三种不同启动模式,具体详情如下:
1

  • 在系统上电或者复位后,SYSCLK的第4个上升沿,BOOT引脚的值将被锁存。我们可以通过设置BOOT1和BOOT0引脚的状态,来选择在复位后的启动模式。
  • 从待机模式退出时,BOOT引脚的值将被重新锁存;因此,在待机模式下BOOT引脚应保持为需要的启动配置。在启动延迟之后,CPU从地址0x0000 0000获取堆栈顶的地址,并从启动存储器的0x0000 0004指示的地址开始执行代码。 固定的存储器映像,代码区始终从地址0x0000 0000开始(通过ICode和DCode总线访问),而数据区(SRAM)始终从地址0x2000 0000开始(通过系统总线访问)。Cortex-M3的CPU始终从ICode总线获取复位向量,即启动仅适合于从代码区开始(典型地从Flash启动)。STM32F10xxx微控制器实现了一个特殊的机制,系统可以不仅仅从Flash存储器或系统存储器启动,还可以从内置SRAM启动。

1.主闪存存储器

Flash主存储区从0x0800 0000地址开始,不同系列器件有不同大小,这里存放为用户烧入的代码(CODE)、常量(RO)和已经初始化的全局变量的值(RW)。一般我们使用JTAG、SWD模式下载程序时,就是下载到主闪存存储器,重启后也直接从这启动程序。

2.系统存储器

系统存储器地址为0x1FFF F000 – 0x1FFF F71F,这是生产厂商出厂之前烧入的一段程序,用来使用串口下载程序,实现ISP。系统存储器我们只能使用,不能进行写或擦除操作。一般来说,我们选用这种启动模式时,是为了从串口下载程序,因为在厂家提供的BootLoader中,提供了串口下载程序的固件,可以通过这个BootLoader将程序下载到系统的Flash中。
串口下载的步骤:

  • 首先将BOOT0设置为1,BOOT1设置为0,然后按下复位键,这样才能从系统存储器启动BootLoader
  • 然后在BootLoader的帮助下,通过串口下载程序到Flash中
  • 程序下载完成后,需要将BOOT0设置为GND,手动复位后STM32才可以从Flash中启动下载的程序。但这样比较繁琐,一般直接在串口下载程序中勾选编程后执行选项利用软件直接复位执行程序而不是自己手动复位。

3.内置SRAM

STM32F10xxx内置64KB的静态SRAM。它可以以字节、半字(16位)或全字(32位)访问。SRAM的起始地址是0x2000 0000。既然是SRAM,自然也就没有程序存储的能力了,这个模式一般用于程序调试。当我们程序只修改一小部分时下载程序时需要重新擦除整个Flash,这样做比较费时,因此我们可以考虑从这个模式启动代码(也就是STM32的内存中),用于快速的程序调试,等程序调试完成后再将程序下载到FLASH中。

根据选定的启动模式,主闪存存储器、系统存储器或SRAM可以按照以下方式访问:

  • 从主闪存存储器启动:主闪存存储器被映射到启动空间0x0000 0000,但仍然能够在它原
    有的地址0x0800 0000访问它,即主闪存存储器的内容可以在两个地址区域访问:0x0000 00000x0800 0000
  • 从系统存储器启动:系统存储器被映射到启动空间0x0000 0000,但仍然能够在它原有的
    地址(互联型产品原有地址为0x1FFF B000,其它产品原有地址为0x1FFF F000)访问它。
  • 从内置SRAM启动:只能在0x2000 0000开始的地址区访问SRAM。
    注意: 当从内置SRAM启动,在应用程序的初始化代码中,必须使用NVIC的异常表和偏移寄存器,从
    新映射向量表之SRAM中。

(二)实验验证

实验代码见之前博客C语言程序编译后内存地址的分配

1.主闪存存储器

  • 一般情况下,系统复位或者上电后都是从主闪存存储器FLASH启动的,因此这里的结果和之前的博客的结果基本一致。
  • 实验结果
    FLASH
  • 结果分析
    可以看出,main函数入口地址、常量区及代码区的存储地址都在0x8000000开始的,说明程序成功从FALSH运行;全局和静态变量、栈区的地址也都分配在0x20000000储存地址(高地址)处,堆区的地址分配在0x00000000处。

2.系统存储器

由于系统存储器是生产厂商出厂之前烧入的一段程序,用来使用串口下载程序,实现ISP(In System Program)的,而系统存储器只能进行读取操作,不能进行写入或擦除操作。因此这里就无法演示了。

3.内置SRAM

  • 一般情况下,我们在 MDK 中编写工程应用后,调试时都是把程序下载到芯片的内部FLASH 运行测试的,代码的 CODE 及 RW-data 的内容被写入到内部 FLASH 中存储。但在某些应用场合下却不希望或不能修改内部 FLASH 的内容,这时就可以使用 RAM 调试功能了,它的本质是把原来存储在内部 FLASH 的代码(CODE 及 RW-data 的内容)改为存储到SRAM 中(内部 SRAM 或外部 SDRAM 均可),芯片复位后从 SRAM 中加载代码并运行。
  • STM32内置SRAM调试的方法
    由于野火已经给出了详细的在STM32上进行内置SRAM调试的资料,因此我这里就不在赘述,详细请见《零死角玩转STM32—F103指南者》第44章 在SRAM中调试代码
  • 实验结果
    SRAM
  • 结果分析
    可以看出,main函数入口地址、常量区以及代码区的存储地址都在0x2000000开始的,说明程序成功从STM32内置SRAM运行;而全局和静态变量、栈区和堆区的地址也都分配在0x20000000储存地址(高地址)处。

综合上面FLASH和内置SRAM的结果,我们可以看出:stm32的栈区地址分配是按照高地址到低地址的方式进行分配,而堆区是按照低地址到高地址的方式进行分配,其他的区域基本上都按照从低地址向高地址的方式进行内存分配。

(三)总结

对于STM32来说,不同的启动模式对应着不同的启动位置。这三种启动模式中,主闪存存储器最为常用但擦写次数有限且速度较慢,内置SRAM启动不常用但方便调试且速度较快,系统存储器则能够帮助我们使用串口下载但操作较为麻烦。三种启动模式各有其优缺点,我们应该根据实际需要来选择不同的启动模式,方便我们的嵌入式开发。通过这次的STM32启动模式选择的实验,我对于STM32的了解更加深入,同时对于Keil的仿真调试更加熟悉。

参考文章:
1.STM32三种BOOT模式介绍
2.STM32 的存储器
3.《STM32中文参考手册_V10》
4.《零死角玩转STM32—F103指南者》

<think>好的,用户想了解STM32内存地址架构,我需要详细解释这个问题。首先,我得回忆一下STM32的内存结构,结合之前看到的引用内容。 记得引用[1]提到,STM32存储器结构与Cortex-M3相似,但加入了FlashSRAM等实际组件。所以应该从Cortex-M3的架构说起,然后过渡到STM32的具体实现。 首先,Cortex-M3的地址空间是4GB,分为不同的区域,比如代码区、SRAM区、外设等。STM32在此基础上划分了Flash、SRAM、外设寄存器等部分。需要详细说明每个区域的地址范围,比如Flash通常从0x08000000开始,SRAM从0x20000000开始。 然后,启动配置也很重要。STM32的启动模式选择不同会影响初始地址,比如从Flash启动时,0x08000000会被映射到0x00000000。这一点在启动文件里可能有设置,引用[2]提到启动文件.s中设置了堆栈,堆栈是在RAM分配给RWZI数据之后分配的。需要解释堆栈的位置如何影响内存布局。 内存分配方面,用户可能想知道编译后的程序如何占用内存。代码段放在Flash,已初始化的全局变量在RW-data,未初始化的在ZI-data,堆栈在RAM末尾。需要结合引用[2]的内容,说明堆栈的分配位置以及如何调整。 外设寄存器部分,地址固定,比如APBAHB总线对应的外设地址范围。引用[3]虽然要讲ADC,但提到外设集成,可以举例说明外设寄存器的访问方式。 内存映射方面,可能需要提到别名区域,比如通过不同地址访问同一物理内存,用于位带操作,这在Cortex-M3中支持,STM32是否也有?需要确认并解释其作用。 最后,实际应用中的注意事项,如地址越界、堆栈溢出,以及如何通过分散加载文件调整内存分配。这部分可以引用启动文件的内容,如引用[2]提到的堆栈设置。 用户可能还想知道如何查看内存映射,或者如何优化内存使用,但根据问题,重点在架构详解,所以需要覆盖结构、启动配置、分配、外设映射等内容,确保每个部分都有引用支持,并自然添加引用标识。</think>### STM32内存地址架构详解 STM32内存地址架构基于**Cortex-M系列处理器的统一存储器映射**,其设计遵循ARM架构规范,同时结合了芯片实际硬件资源(如Flash、SRAM、外设寄存器等)。以下是具体分析: --- #### 1. **内存地址空间划分** STM32的4GB地址空间(32系统)分为以下要区域: - **代码区(Code Area)** 地址范围:$0x00000000$ - $0x1FFFFFFF$ 用途:存放程序代码(Flash),例如Flash通常从$0x08000000$开始[^1]。 - **SRAM区(SRAM Area)** 地址范围:$0x20000000$ - $0x3FFFFFFF$ 用途:运行时数据存储,例如STM32F4的SRAM起始地址为$0x20000000$,大小因型号而异(如192KB或更多)。 - **外设寄存器区(Peripheral Registers)** 地址范围:$0x40000000$ - $0x5FFFFFFF$ 用途:映射所有片上外设(如GPIO、ADC、USART)的控制寄存器[^3]。 - **其他区域** 包括位带别名区($0x42000000$)、系统控制区($0xE0000000$)等,用于特殊操作(如位操作、调试)。 --- #### 2. **启动配置与地址映射** STM32支持多种启动模式,通过BOOT引脚配置: - **Flash启动**(默认):Flash起始地址$0x08000000$映射到$0x00000000$,CPU从此读取初始堆栈指针复位向量[^2]。 - **系统存储器启动**:用于内置Bootloader,地址由芯片厂商定义。 - **SRAM启动**:调试时临时使用,直接运行RAM中的代码。 --- #### 3. **内存分配与堆栈管理** - **编译后的内存占用**: 代码段(`.text`)存储在Flash中; 已初始化全局变量(`.data`)加载到RAM; 未初始化变量(`.bss`)占用RAM的ZI-data区域。 - **堆栈分配**: 堆(Heap)栈(Stack)位于RAM末尾,由启动文件(`.s`)定义大小。例如: ```c Stack_Size EQU 0x00000400 // 1KB栈 Heap_Size EQU 0x00000200 // 512B堆 ``` --- #### 4. **外设寄存器的地址固定性** 每个外设的寄存器地址在芯片设计时已固定。例如: - **GPIOA**的寄存器基址为$0x40020000$; - **ADC1**的寄存器基址为$0x40012000$(不同型号可能不同)[^3]。 --- #### 5. **内存映射的灵活性** STM32支持**别名区(Bit-Band)**操作,允许通过位带别名地址直接操作单个比特。例如: - 原始地址:$0x20000000$的某比特; - 别名地址:$0x22000000 + (0x20000000 - 基址) \times 32 + 比特序号 \times 4$。 --- #### 6. **实际应用注意事项** - **地址越界**:访问未分配区域会触发硬件错误(HardFault)。 - **堆栈溢出**:需合理设置栈大小,避免覆盖其他数据。 - **分散加载文件(Scatter File)**:可自定义代码数据的存储位置。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值