【STM32】存储器映射

在【STM32】合集【STM32】总线架构一文中,讨论了STM32的总线架构,说明了不同存储器、外设与内核之间的连接方式,也即确定了芯片的各个单元之间的布局与联系。本文将通过介绍STM32F1系列的存储器系统来进一步说明每个单元的组织与排列形式,由此了解芯片中每个单元的具体访问方式。

Cortex-M3的存储器系统

本文介绍的STM32系列是基于ARM公司的Cortex-M3内核设计的芯片,所谓Cortex-M3内核,是ARM公司设计的一种处理器架构,ARM公司规定了这种处理器的内核组成以及指令集架构,而ST公司基于这种处理器架构设计不同种类和数量的外设部件,组成具有不同应用功能的芯片。Cortex-M3内核本身对存储器系统做出了一系列规定,基于该内核的芯片都在该规定前提下由生产厂商自行落实具体的分配,故要了解STM32的存储器系统,首先要了解Cortex-M3的存储器系统组成。

首先我们了解一下存储器映射的概念:

存储器映射是指将微处理器可访问的整个空间,按照功能和硬件特性,划分为不同用途的区域,并将这些区域与实际的物理存储单元建立一一对应的关系的机制。
即物理存储器在分配地址的过程中,物理存储器本身是没有地址信息的,但是CPU需要通过地址来访问对应存储器单元。故通过一定的编码规则,为存储器分配地址,这一过程就是存储器映射。简单来说就是为每个存储单元分配一个门牌号,使得CPU可以通过访问这个门牌号访问对应的地址单元。通常来说,存储器映射又可以叫内存空间映射,通过这种方法,CPU可以通过地址直接访问所有空间,无需区分操作的是内存还是硬件。

CM3内核对应的32位芯片,可寻址空间为 2 32 = 4 G B 2^{32}=4GB 232=4GB(每个地址对应一个Byte),也即0x00000000~0xFFFFFFFF的范围。ARM公司对这些存储器映射的地址空间作了一个简单的说明,粗略规定了每个地址范围对应的外设内容。

如上图,CM3首先把4GB寻址空间划分为6个区域,对应关系如下

区域名称英文标识寻址范围描述
代码区Code0x0000 0000 ~ 0x1FFF FFFF用于存储程序代码、指令及常量,是处理器执行程序的主要区域
片上SRAM区SRAM0x2000 0000 ~ 0x3FFF FFFF芯片内部的静态随机存取存储器,用于临时存储运行时数据,掉电后数据丢失
片上外设区Peripheral0x4000 0000 ~ 0x5FFF FFFF芯片内部集成的外设(如GPIO、定时器、UART等)的寄存器地址空间
扩展存储器区External RAM0x6000 0000 ~ 0x9FFF FFFF外部扩展的随机存取存储器,用于扩展系统存储容量
扩展外设区External device0xA000 0000 ~ 0xDFFF FFFF外部连接的外设(如外部传感器、显示器等)的地址空间
系统级外设区System Level0xE000 0000 ~ 0xFFFF FFFF包含系统级控制和调试组件(如NVIC、SysTick定时器等)的地址空间

位带操作

在片上SRAM区和片上外设区的低64MB空间中包含有一个位带区(Bit Band Region)和一个位带别名区(Bit Band Alias)。其中,低32MB范围的低1MB地址区域为位带区,高32MB地址区域为位带别名区,通过这两个区域我们可以实现对低1MB空间的直接进行位操作。以片上SRAM区为例,SRAM区取址范围为0x2000 0000 ~ 0x3FFF FFFF,低1MB区域0x2000 0000 ~ 0x200F FFFF为位带区,高32MB区域0x2200 0000 ~ 0x23FF FFFF为位带别名区。1MB位带区共 1 M × 1 B y t e = 1 M × 8 b i t = 8 M b 1M×1Byte=1M×8bit=8Mb 1M×1Byte=1M×8bit=8Mb即8M个位变量,通过把每个bit膨胀成一个32位的字,即8M个bit对应 8 M × 32 b i t = 8 M × 4 B y t e = 32 M B 8M×32bit=8M×4Byte=32MB 8M×32bit=8M×4Byte=32MB得到32MB大小位带别名区。在位带区和位带别名区之间,为其他通用的非位带操作区域。

在非位带区,如果我们需要对某一位(bit)进行访问,通常需要进行以下步骤:

CM3是32位架构,其数据和地址总线都是32位,一次访问32个位区域(即 一个字 = 32 b i t = 4 B y t e 一个字 = 32bit = 4Byte 一个字=32bit=4Byte

  1. 读取位所在字的值到工作寄存器
  2. 向寄存器中向目标位写入值
  3. 把值写回对应字中

总结出来就是一个”读-改-写“的过程。而在支持位带操作的位带区,每个bit都可以直接访问而不用读取bit所在的整个字。简单来说,通过膨胀操作,把8M个bit一一对应位带别名区的8M个字,这样建立起一个映射关系,使得操作位带别名区的一个字,相当于操作位直接带区对应的bit。

那么,一个bit是怎么膨胀为一个字的,它们是如何对应的?其实思路很简单:位带别名区一个字的32个bit中高31位都是无效的,只有最低位(LSB)有效,并对应于位带区中对应bit。所以,当这个字的LSB被设为1时,对应bit也会硬件设定为1,LSB设为0时,对应bit也设为0,从而实现对位带别名区的字赋值0/1即可直接修改位带区中对应位的值(读取时亦然)。这种操作被称为原子操作,是不可被中断的,其一旦开始运行,会连续运行到结束,从而保证多任务/多线程环境下数据的一致性,这有别于一般的位操作(对数据的单个或多个二进制位进行直接操作(如置1、清0、翻转、读取等),操作对象是数据的二进制位)

值得注意的是,通过实现位带操作,位带中每个bit实际上是有2个可访问地址:1个是实际地址,另一个是膨胀映射为一个字后对应字的地址。在使用C语言访问该bit时,编译器并不知道位带别名区中映射字和位带别名区原bit的关系,如果直接操作映射字,相关代码会被编译器优化掉。故需要使用volatile关键字修饰映射字的地址以防止被优化。

Code区

代码区共512MB空间,一般对应于片上非易失性存储器,大多数主流芯片采用片上flash(如STM32)。中断向量表通常被安排在代码区的内部起始地址,占1KB空间(这里说的起始地址并非一定是0x0000 0000,而是程序执行时最开始取址点,比如STM32F103系列程序指针PC从0x0800 0000开始执行代码,其中断向量表地址范围为0x0800 0000 ~ 0x0800 03FF,而在此之前的空间被映射给存储了系统Bootloader的系统存储器,用于支持芯片的ISP下载方式),紧接着通常是启动代码,还有占代码区绝大部分的用户代码部分和调试信息,扩展启动模式等相关区域,这些模块在Code区上的具体分布通常由各个芯片厂商决定。

SRAM区

SRAM区在前面已经介绍过,包括位带区和对应的位带别名区,以及其他不支持位带操作的区域。SRAM中可以细分堆区、栈区、.data段、.bss段,具体分配及总体大小由芯片厂商决定,绝大多数常用芯片的片上SRAM通常都远远不会达到512MB大小。

Peripheral区

CM3架构规定把GPIO、I2C、USART等片上外设的控制寄存器映射到这一内存空间中,使得CPU可以像访问一般内存一样访问片上外设,极大简化了程序编写逻辑,方便CPU对片上外设的读写控制。这里CM3内核同样只规定了片上外设区整体分布以及固定了位带区地址,具体划分为芯片厂商通过针对不同芯片不同外设种类和数量合理设计,并且与SRAM区相同的是,大多数常用芯片的片上外设所占空间大小远远小于片上外设区总容量512MB。

External RAM区 & External device区

CM3架构分别为这两个区域预留了1GB空间并确定了相应地址范围,分别用于扩展外部存储器(数据存储器如SRAM或者程序非易失性只读存储器如flash等)和外部外设(扩展显示屏、传感器、通信接口等设备)。具体分配和使用由厂商和用户决定。

System Level


系统级外设区是内核私有外设和系统控制功能专门划定的地址空间,核心作用是支持中断控制、调试、系统管理等底层功能,为所有CM3架构芯片所共有。这一区域被分配在0xE000 0000 ~ 0xFFFF FFFF最高的512MB空间内,与其他区域严格区分以确保系统组件的独立性,并且在用户模式下禁止访问。该区被分割为3个区域:

区域地址范围描述
内部私有外设区0xE000 0000 ~ 0xE003 FFFF通过AHB私有外设总线实现连接,包含直接和内核交互的核心组件
外部私有外设区0xE004 0000 ~ 0XE00F FFFF通过APB私有外设总线实现连接,用于连接调试和跟踪外设
芯片厂商自定义0xE010 0000 ~ 0xFFFF FFFF容纳厂商自定义外设、扩展调试功能

内部私有外设区

其中,内部私有外设区(Private peripheral bus - Internal)遵循AHB-Lite(Advanced High-performance Bus Lite)总线协议,包括:

分组模块名称地址范围描述
调试组件ITM(指令跟踪宏单元)0xE000 0000 ~ 0xE000 0FFF包含32个Stimulus寄存器(对应端口0-31),用于软件插装调试信息
DWT(数据观察点单元)0xE000 1000 ~ 0xE000 1FFF包含CYCCNT计数器,用于性能分析和时间戳
FPB(闪存断电单元)0xE000 2000 ~ 0xE000 3FFF支持最多8个硬件断点,可设置在闪存或RAM区域
保留0xE000 4000 ~0xE000 DFFF
系统控制空间(SCS)NVIC(嵌套中断向量控制器)0xE000 E000 ~ 0xE000 EFFF中断控制
Interal PPB0xE000 F000 ~ 0xE003 FFFF基于AHB-Lite协议,支持突发传输和流水线操作,与直接与处理器内核交互的高速组件连接,如NVIC、MPU、SysTick(这里把NVIC单列出来了)等

外部私有外设区

外部私有外设(Private peripheral bus - External)遵循APB(Advanced Peripheral Bus)协议,包括:

模块名称地址范围描述
TPIU(跟踪端口接口单元)0xE004 0000 ~ 0xE004 0FFF将跟踪数据转换为串行输出(SWO),支持波特率动态调整
ETM(嵌入式跟踪宏单元)0xE004 1000 ~ 0xE004 1FFF提供指令流跟踪功能,支持最高100MHz跟踪速率
External PPB0xE004 2000 ~ 0xE004 2FFF基于APB协议,与调试组件(如 ETM、TPIU)、ROM 表及厂商自定义外设连接(这里单列了TPIU、ETM和ROM表)
ROM Table(ROM表)0xE00F F000 ~ 0xE00F FFFF存储调试组件的配置信息,供开发工具自动识别硬件特性
芯片厂商自定义0xE010 0000 ~0xFFFF FFFF容纳厂商自定义外设、扩展调试功能

STM32的存储器系统

STM32在CM3内核规定的基础上,针对每个子型号分别落实了外设种类数量以及每个区域的具体分配,这些型号中往往只用到了4GB寻址空间的一小部分(如下图是STM103x8的存储器映射图)。这里仍然以STM32F1系列为例,介绍其存储器映射。

Code区

STM32F1的代码区中分配了有效物理存储器的区域主要分为3个部分:主Flash(Main Flash)、系统存储器(System Memory)以及选项字节(Option Bytes),此外的其他部分为保留部分,未被定义。其中,主Flash区域为片上Flash的映射地址,也就是用户代码区,其起始地址为0x08000000,终止地址由不同型号的片上Flash容量决定,具体如下表:

型号类别典型型号主 Flash 容量地址范围
小容量型号STM32F103C8T664KB0x08000000 ~ 0x0800FFFF
中容量型号STM32F103RBT6128KB0x08000000 ~ 0x0801FFFF
大容量型号STM32F103ZE512KB0x08000000 ~ 0x0807FFFF
超大容量型号STM32F105/1071MB0x08000000 ~ 0x080FFFFF

系统存储器是STM32F1中的一个特殊的ROM,该非易失性只读存储器在出厂时被固化写入Bootloader以实现通过ISP下载程序的逻辑,其容量大小为2KB,地址范围为0x1FFF0000 ~ 0x1FFFF7FF

Code区中选项字节部分仅占16个Byte,地址范围为0x1FFFF800 ~ 0x1FFFF80F,用于配置芯片的硬件特性,这部分内容在复位时被自动加载到 Flash 控制器的专用寄存器中,且掉电不丢失,在下次上电复位后可以通过读取这些寄存器获取配置信息,再次修改时需要特定流程解锁。在这16个字节中,前8个字节为有效字节,后8个字节为互补字节,其内容与前8个字节对应互补,用于校验,防止配置错误,其具体地址及功能如下:

地址偏移名称功能说明
0x1FFFF800OB_USER用户选项字节(配置复位行为、看门狗等)
0x1FFFF801OB_RDP读保护字节(配置 Flash 读保护级别)
0x1FFFF802OB_WRP1_0写保护字节 1(配置低地址 Flash 页的写保护)
0x1FFFF803OB_WRP3_2写保护字节 2(配置中地址 Flash 页的写保护)
0x1FFFF804OB_WRP5_4写保护字节 3(配置高地址 Flash 页的写保护,仅大容量型号有效)
0x1FFFF805OB_WRP7_6写保护字节 4(配置更高地址 Flash 页的写保护,仅超大容量型号有效)
0x1FFFF806OB_STDBY_RST待机模式复位配置(已废弃,F1 系列中无效)
0x1FFFF807OB_STOP_RST停止模式复位配置(已废弃,F1 系列中无效)
0x1FFFF808 ~ 0x1FFFF80F互补字节与前 8 字节按位取反(用于硬件校验,确保配置未被意外篡改)

这里,主存起始地址为0x08000000,地址0x00000000 ~ 0x07FFFFFF范围共128M空间为预留虚拟地址空间,这部分空间本身为对应任何物理存储器。CM3具有一个Boot映射机制,该机制要求芯片在复位后首先会读取Boot引脚值,根据Boot高低电平决定该虚拟地址空间的映射内容,在STM32F1中,Boot引脚值与启动地址对应关系如下表:

启动介质Boot0 引脚Boot1 引脚物理地址范围(典型值)容量范围核心特性与应用场景
主 Flash(用户程序)0X(任意)0x08000000 ~ 0x080FFFFF16KB ~ 1MB存放用户应用程序,断电不丢失,是量产设备的默认启动介质。 不同容量型号的结束地址不同: - 小容量(如 F103C8T6):0x0800FFFF(64KB) - 中容量(如 F103RBT6):0x0801FFFF(128KB) - 大容量(如 F103ZE):0x0807FFFF(512KB) - 超大容量(如 F105VCT6):0x080FFFFF(1MB)
系统存储器(内置 Bootloader)100x1FFF0000 ~ 0x1FFFF7FF固定 2KB存放 ST 出厂固化的 ISP Bootloader,用于通过 UART1、SPI1 或 I2C1 下载程序到主 Flash。 内容不可修改,仅用于固件更新场景。
内部 SRAM110x20000000 ~ 0x2000FFFF2KB ~ 64KB临时存放程序(断电丢失),仅用于调试: - 无需擦写 Flash,适合快速验证代码 - 不同型号容量不同(如 F103C8T6 为 20KB,地址0x20000000 ~ 0x20004FFF

所谓启动地址,就是把该部分对应地址映射到虚拟地址空间中,使得CPU在访问该地址时,可以从0x0000 0000开始,CM3内核复位后,强制从0x0000 0000读取中断向量表。中断向量表是CPU在复位后首先读取的部分,其存储区域跟随芯片启动区域变化,其初始起始地址为启动介质起始地址。

SRAM区

STM32F1的SRAM区同样根据型号不同有不同大小,具体分配如下表(值得注意的是,对于STM32F1,即使是大容量的SRAM,其地址范围也完全在位带区内):

容量等级典型型号SRAM 容量地址范围(起始~结束)备注(核心应用场景)
小容量STM32F103C6T62KB0x20000000 ~ 0x200007FF简单控制场景(如传感器数据采集)
小容量STM32F103C8T620KB0x20000000 ~ 0x20004FFF中小型嵌入式应用(带 UART/SPI 通信)
中容量STM32F103RBT620KB0x20000000 ~ 0x20004FFF同上,封装引脚更多(LQFP64)
中容量STM32F103RCT648KB0x20000000 ~ 0x2000BFFF需较大数据缓存的场景(如波形采集)
大容量STM32F103VET664KB0x20000000 ~ 0x2000FFFF复杂应用(带 RTOS、多任务数据处理)
大容量STM32F103ZET664KB0x20000000 ~ 0x2000FFFF同上,外设更多(如支持 FSMC 外部存储)

片上外设区

片上外设区是对芯片上各功能模块控制寄存器的映射,这些寄存器是操作功能硬件的接口,是实现单片机逻辑和控制功能重要部分。该区域通过AHB总线(连接核心外设)、APB1总线(连接低速外设)、APB2总线(连接高速外设)访问。关于这个区域的地址分配,这里从STM32F10xxx参考手册截取了外设地址分配,详细内容可以查找对应的具体型号参考手册。

posted @ 2025-09-16 23:20  ONGround  阅读(0)  评论(0)    收藏  举报  来源