存储器映射
STM32F1 存储器映射:笔记版

1. 先记住一句话
STM32 把 Flash、SRAM、外设寄存器都统一编上地址,CPU 访问它们就像访问内存一样。
所以 STM32 里常说:
外设寄存器也是“内存地址”
例如 GPIO、USART、TIM、RCC 这些外设,本质上都有固定地址。
一、STM32 的寻址范围
STM32F1 使用 32 位地址总线。
所以最大寻址空间是:
2^32 = 4GB
地址范围:
0x0000 0000 ~ 0xFFFF FFFF
也就是说,STM32 把整个 4GB 空间划分成不同区域。
二、STM32F1 常见存储器映射总表
|
地址范围 |
||
|
区域作用0x0000 0000 开始 |
||
|
启动映射区上电后 CPU 首先访问的区域0x0800 0000 开始 |
||
|
Flash存放程序代码0x2000 0000 开始 |
||
|
SRAM存放运行时变量、栈、堆0x4000 0000 开始 |
||
|
外设寄存器区GPIO、USART、TIM、RCC 等0x6000 0000 开始 |
||
|
外部存储器区外接 SRAM、NOR Flash 等0xE000 0000 开始 |
Cortex-M3 内核外设区NVIC、SysTick、SCB 等
三、几个最重要的地址
1. Flash 程序存储区
Flash 起始地址:0x0800 0000
作用:
存放我们下载进去的程序
比如你在 Keil 里点 Download,程序一般就烧录到这里。
STM32F103ZET6 常见 Flash 大小:
512KB
所以大概范围是:
0x0800 0000 ~ 0x0807 FFFF
重点记忆:
程序代码存在 Flash,Flash 从 0x08000000 开始。
2. SRAM 数据存储区
SRAM 起始地址:0x2000 0000
作用:
存放变量、数组、栈、堆
例如:
int a = 10;
int arr[100];
这些程序运行时的数据,一般就在 SRAM 里。
STM32F103ZET6 常见 SRAM 大小:
64KB
大概范围:
0x2000 0000 ~ 0x2000 FFFF
重点记忆:
变量运行时主要在 SRAM,SRAM 从 0x20000000 开始。
3. 外设寄存器区
外设寄存器区起始地址:0x4000 0000
GPIO、定时器、串口、RCC 等都在这里。
例如:
|
外设 |
|
|
常见基地址TIM2 |
|
|
0x4000 0000TIM3 |
|
|
0x4000 0400USART1 |
|
|
0x4001 3800GPIOA |
|
|
0x4001 0800GPIOB |
|
|
0x4001 0C00GPIOC |
|
|
0x4001 1000RCC |
0x4002 1000重点记忆:
外设寄存器从 0x40000000 开始。
四、为什么说“外设寄存器也是地址”?
比如 GPIOA 的基地址是:
GPIOA_BASE = 0x40010800
GPIOA 里面有很多寄存器,例如:
|
寄存器 |
|
|
作用CRL |
|
|
配置低 8 个引脚CRH |
|
|
配置高 8 个引脚IDR |
|
|
输入数据寄存器ODR |
|
|
输出数据寄存器BSRR |
置位/复位寄存器这些寄存器本质上就是一些固定地址。
例如:
GPIOA_BASE = 0x40010800
GPIOA_CRL = GPIOA_BASE + 0x00
GPIOA_CRH = GPIOA_BASE + 0x04
GPIOA_IDR = GPIOA_BASE + 0x08
GPIOA_ODR = GPIOA_BASE + 0x0C
GPIOA_BSRR = GPIOA_BASE + 0x10
所以:
外设基地址 + 寄存器偏移地址 = 具体寄存器地址
这就是后面要学的 寄存器映射。
五、存储器映射和寄存器映射的关系
存储器映射
关注的是整个 STM32 地址空间怎么分配。
例如:
Flash 在哪里?
SRAM 在哪里?
外设在哪里?
寄存器映射
关注的是某一个外设内部,每个寄存器具体在哪里。
例如:
GPIOA 的 CRL 在哪里?
GPIOA 的 ODR 在哪里?
RCC 的 APB2ENR 在哪里?
简单理解:
存储器映射:大地图
寄存器映射:某个外设内部的小地图
六、启动地址映射
STM32 上电复位后,CPU 会从:
0x0000 0000
开始取指令。
但是我们程序实际存放在:
0x0800 0000
所以 STM32 会根据 BOOT 引脚,把不同区域映射到 0x00000000。
常见启动方式:
|
BOOT 配置 |
||
|
启动区域作用从 Flash 启动 |
||
|
0x08000000 映射到 0x00000000正常运行用户程序从系统存储器启动 |
||
|
System Memory串口下载程序等从 SRAM 启动 |
0x20000000调试或特殊用途平时我们下载程序运行,基本都是:
从 Flash 启动
也就是:
0x00000000 实际对应 0x08000000
七、程序入口和中断向量表
STM32 程序最前面有一个东西叫:
中断向量表
它通常放在 Flash 起始位置:
0x0800 0000
上电后 CPU 会先读两个重要内容:
|
地址 |
|
|
内容0x08000000 |
|
|
栈顶地址 MSP0x08000004 |
复位入口 Reset_Handler所以启动流程可以简单理解为:
上电
↓
读取 0x08000000,设置栈顶
↓
读取 0x08000004,找到复位函数
↓
进入 Reset_Handler
↓
进入 main 函数
八、代码里为什么能直接操作外设?
比如库函数里经常看到:
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
它背后本质是操作 RCC 的某个寄存器。
RCC 的基地址:
0x40021000
通过修改 RCC 里的时钟控制寄存器,就能打开 GPIOA 的时钟。
所以我们写:
GPIO_SetBits(GPIOA, GPIO_Pin_0);
本质上也是修改 GPIOA 相关寄存器。
底层逻辑是:
CPU 写某个地址
↓
这个地址对应 GPIOA 的寄存器
↓
GPIOA 引脚电平发生变化
九、常见地址速记
这个表很重要,建议记住:
|
内容 |
|
|
地址Flash 起始地址 |
|
|
0x08000000SRAM 起始地址 |
|
|
0x20000000外设起始地址 |
|
|
0x40000000GPIOA 基地址 |
|
|
0x40010800GPIOB 基地址 |
|
|
0x40010C00RCC 基地址 |
|
|
0x40021000USART1 基地址 |
|
|
0x40013800TIM2 基地址 |
|
|
0x40000000TIM3 基地址 |
|
|
0x40000400Cortex-M3 内核外设 |
0xE0000000
十、学习时重点掌握什么?
这一节不用死背所有地址,重点掌握这几个:
1. STM32 是 32 位寻址,地址范围 4GB
2. Flash 从 0x08000000 开始
3. SRAM 从 0x20000000 开始
4. 外设寄存器从 0x40000000 开始
5. GPIO、USART、TIM、RCC 都是通过地址访问的
6. 外设基地址 + 寄存器偏移 = 具体寄存器地址
7. 启动时 0x00000000 会映射到不同启动区域
十一、最简单理解
可以把 STM32 想成一栋大楼:
0x08000000:程序办公室,放代码
0x20000000:临时仓库,放变量
0x40000000:设备控制室,控制 GPIO、串口、定时器
0xE0000000:内核管理室,控制 NVIC、SysTick
CPU 想干什么,就去对应地址读写数据。
例如:
想点亮 LED
↓
找到 GPIO 地址
↓
修改 GPIO 输出寄存器
↓
引脚输出高/低电平
↓
LED 亮/灭
十二、一句话总结
存储器映射就是:STM32 把 Flash、SRAM、外设寄存器、内核外设等资源统一放到 4GB 地址空间中,CPU 通过访问不同地址来读取数据、运行程序和控制外设。
更多推荐

所有评论(0)