Cortex-M MCU 默认的分散加载文件分析
你提供的这段代码是一个典型的 ARM Cortex-M MCU 的分散加载文件(Scatter-Loading Description File),通常由 Keil MDK(uVision)自动生成。它定义了程序在 Flash 和 RAM 中的存储布局,用于指导链接器(armlink)如何分配代码和数据段。下面详细解析它的结构和作用:
1. 文件结构解析
(1) 整体结构
LR_IROM1 0x08000000 0x00080000 { ; load region size_regionER_IROM1 0x08000000 0x00080000 { ; load address = execution address*.o (RESET, +First)*(InRoot$$Sections).ANY (+RO).ANY (+XO)}RW_IRAM1 0x20000000 0x00010000 { ; RW data.ANY (+RW +ZI)}
}
LR_IROM1:定义了一个 加载区域(Load Region),表示程序在 Flash 中的存储位置和大小。ER_IROM1:定义了一个 执行区域(Execution Region),表示代码和只读数据在 Flash 中的执行地址。RW_IRAM1:定义了一个 读写数据区域(RW Data Region),表示已初始化和未初始化的全局变量在 RAM 中的存储位置。
(2) 关键部分详解
① LR_IROM1(加载区域)
LR_IROM1 0x08000000 0x00080000 { ; load region size_region
LR_IROM1:加载区域的名称(可自定义)。0x08000000:Flash 的起始地址(STM32F1xx/4xx 的默认 Flash 起始地址)。0x00080000:Flash 的大小(512KB,即0x80000字节)。- 作用:定义整个程序在 Flash 中的存储范围。
② ER_IROM1(执行区域)
ER_IROM1 0x08000000 0x00080000 { ; load address = execution address*.o (RESET, +First)*(InRoot$$Sections).ANY (+RO).ANY (+XO)}
ER_IROM1:执行区域的名称(通常与加载区域同名,表示代码直接在 Flash 执行)。0x08000000 0x00080000:执行地址和大小(与加载区域相同,表示代码在 Flash 中运行)。- 内容:
*.o (RESET, +First):*.o:所有目标文件(.o)。(RESET, +First):确保RESET段(通常是启动文件中的复位向量表)被放在 Flash 的最前面(地址0x08000000)。
*(InRoot$$Sections):- 包含 CMSIS 或 RTOS 等库中的特殊段(如中断向量表、线程局部存储等)。
.ANY (+RO):.ANY:匹配所有目标文件的段。(+RO):将所有只读数据(.text、.rodata)放入此区域。
.ANY (+XO):(+XO):将可执行但不可读的段(如某些 ARM 架构的特殊段)放入此区域(较少使用)。
③ RW_IRAM1(读写数据区域)
RW_IRAM1 0x20000000 0x00010000 { ; RW data.ANY (+RW +ZI)}
RW_IRAM1:读写数据区域的名称。0x20000000 0x00010000:RAM 的起始地址(STM32F1xx/4xx 的默认 RAM 起始地址)和大小(64KB)。.ANY (+RW +ZI):.ANY:匹配所有目标文件的段。(+RW +ZI):将所有已初始化(.data)和未初始化(.bss)的全局变量放入此区域。
2. 该分散加载文件的作用
(1) 代码存储在 Flash(ER_IROM1)
RESET段:确保复位向量表位于 Flash 起始地址(0x08000000),这是 Cortex-M 的硬件要求。.text和.rodata:所有代码和只读数据(如常量字符串)存储在 Flash 中。.data初始值:已初始化的全局变量初始值也存储在 Flash 中(运行时需拷贝到 RAM)。
(2) 数据存储在 RAM(RW_IRAM1)
.data段:已初始化的全局变量在程序启动时从 Flash 拷贝到 RAM。.bss段:未初始化的全局变量在 RAM 中清零。
3. 对比 Keil 默认生成的 .sct 文件
你提供的文件是 Keil MDK 的分散加载描述文件,而之前讨论的 .sct 文件是 ARM-GCC 的分散加载文件。它们的功能类似,但语法不同:
| 特性 | Keil 分散加载描述文件 | ARM-GCC .sct 文件 |
|---|---|---|
| 文件格式 | 文本,但由 Keil 图形界面生成 | 纯文本,手动编辑 |
| 语法 | LR_XXX、ER_XXX、RW_XXX | MEMORY、SECTIONS |
| 适用工具链 | Keil MDK(ARMCC) | ARM-GCC(arm-none-eabi-gcc) |
| 灵活性 | 较简单,适合快速配置 | 更灵活,支持复杂内存布局 |
4. 实际应用中的注意事项
(1) 确保 Flash 和 RAM 地址正确
- Flash 起始地址:STM32F1xx/4xx 通常是
0x08000000,但不同型号可能不同(如 STM32F7 是0x08000000或更高)。 - RAM 起始地址:STM32F1xx/4xx 通常是
0x20000000,大小需与芯片规格一致(如 STM32F407 有 192KB RAM)。
(2) 特殊段的处理
RESET段:必须位于 Flash 起始地址,否则 MCU 无法正常启动。- 中断向量表:通常由启动文件(
startup.s)定义,需确保它在RESET段中。
(3) 调试与验证
- 查看内存映射:使用 Keil 的 Memory Map 功能(
Project -> Options for Target -> Linker -> Map File)生成.map文件,确认各段地址是否符合预期。 - 调试时检查变量地址:在 Keil 调试器中查看全局变量的地址,确认它们是否位于
RW_IRAM1区域。
5. 总结
- Keil 的分散加载描述文件 定义了程序在 Flash 和 RAM 中的存储布局,确保代码和数据正确分配。
- 核心部分:
LR_IROM1:定义 Flash 的存储范围。ER_IROM1:定义代码和只读数据的执行地址(通常直接在 Flash 运行)。RW_IRAM1:定义全局变量和静态变量的 RAM 存储位置。
- 与 GCC 的 .sct 文件对比:功能类似,但语法和工具链不同。
- 关键点:确保
RESET段位于 Flash 起始地址,并正确分配.data和.bss段到 RAM。
通过合理配置分散加载文件,可以优化 MCU 的内存使用,确保程序正确运行。
