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 的内存使用,确保程序正确运行。