1. STM32MP1启动详解
STM32MP157作为ST推出的首款Cortex-A7 MPU,其启动机制与传统STM32 MCU有着显著差异。这款芯片内部没有供用户使用的Flash,系统程序都存放在外部存储设备中,因此理解其启动流程对嵌入式Linux开发者至关重要。
1.1 STM32MP1启动模式
STM32MP1支持从多种设备启动,包括EMMC、SD、NAND、NOR等Flash设备,以及USB和UART等串行接口。这些启动方式的选择通过BOOT0~BOOT2三个引脚的电平组合来决定。
开发板上通常会设计拨码开关来控制这三个BOOT引脚。当引脚拨到"ON"位置时接3.3V(逻辑1),拨到"OFF"位置时悬空或接地(逻辑0)。三个引脚的不同组合对应不同的启动模式:
| BOOT2 | BOOT1 | BOOT0 | 启动模式 |
|---|---|---|---|
| 0 | 0 | 0 | 从Flash设备启动 |
| 0 | 0 | 1 | 串行启动(UART/USB) |
| 0 | 1 | 0 | 保留 |
| 0 | 1 | 1 | 保留 |
| 1 | 0 | 0 | 工程模式(通过ST-Link调试) |
| 1 | 0 | 1 | 保留 |
| 1 | 1 | 0 | 保留 |
| 1 | 1 | 1 | 保留 |
注意:实际开发中,BOOT引脚的具体配置可能因开发板设计而略有不同,建议参考具体开发板的原理图确认。
1.2 STM32MP1启动流程详解
1.2.1 内部ROM代码
STM32MP1内部有128KB的ROM空间(地址0x00000000),存放ST编写的启动代码。上电后,芯片首先运行这段ROM代码,其主要功能包括:
- 安全启动支持
- 工程模式调试接口
- 多核启动管理
- 低功耗唤醒处理
- 提供安全相关服务
在多核处理方面,ROM代码会确保只有Core0运行启动流程,Core1则处于等待状态。这种设计使得开发者可以暂时忽略多核复杂性,专注于单核开发。
1.2.2 安全启动
安全启动是STM32MP1的重要特性,其流程分为两个阶段:
-
FSBL(First Stage Boot Loader):ROM代码从选定的启动设备加载的第一个用户程序,通常是TF-A或U-Boot SPL。由于此时DDR尚未初始化,FSBL运行在内部的256KB SYSRAM中。
-
SSBL(Second Stage Boot Loader):FSBL初始化DDR后加载的程序,通常是完整的U-Boot,负责最终启动Linux内核。
FSBL镜像有严格的大小限制:必须小于246.75KB(0x30000000 - 0x2FFC2500)。开发者若想运行裸机程序,也需要遵守这一限制。
1.2.3 串行启动
当BOOT引脚设置为串行启动模式时,ROM代码会扫描所有可用的串行接口:
1.2.3.1 USB启动
通过USB OTG接口烧写系统时需注意:
- 需要48M和60M时钟,由HSE生成
- 支持的HSE时钟值:8,10,12,14,16,20,24,25,26,28,32,36,40,48MHz
- 修改OTP中的HSE配置需谨慎,可能导致芯片无法启动
1.2.3.2 UART启动
UART启动时需特别注意:
- 仅支持USART2/3、UART4-8
- 通信参数:1起始位、8数据位、偶校验、1位停止位、115200波特率
- 必须使用ROM代码指定的引脚和复用功能
1.3 Flash设备启动要求
不同Flash设备的启动要求各不相同:
1.3.1 从NAND启动
ROM代码支持并行和串行NAND:
- 并行NAND连接FMC总线
- 串行NAND连接QSPI
- 支持多种块大小和页大小的组合
- 支持多种ECC校验方式
1.3.2 从EMMC启动
EMMC启动特点:
- 使用boot1/boot2分区存放FSBL
- 默认使用SDMMC2接口
- 单bit模式操作
- 分区大小固定(如8GB EMMC的boot分区为4MB)
1.3.3 从SD卡启动
SD卡启动机制:
- 查找GPT分区中的fsbl分区
- 若无GPT分区,则从固定物理地址加载
- 第一个FSBL位于LBA34(0x4400)
- 第二个FSBL位于LBA546(0x44400)
- 默认使用SDMMC1接口
1.4 STM32MP1二进制头部信息
FSBL镜像必须包含特定的头部信息,主要字段包括:
- Magic number(0x53544D32)
- 镜像签名和校验和
- 镜像长度和入口地址
- 加载地址(ROM代码不使用)
- 版本信息
- ECDSA算法和公钥
- 二进制类型标识
头部信息通常由编译工具自动添加,开发者无需手动处理。
2. STM32MP1 Linux系统启动过程
完整的Linux启动流程分为五个阶段:
- ROM代码:芯片固化的启动代码,负责初始硬件环境和加载FSBL
- FSBL:初始化关键外设(如DDR),加载SSBL
- SSBL:完整功能的bootloader(如U-Boot),准备Linux启动环境
- Linux内核:初始化系统外设,挂载根文件系统
- 用户空间:启动init进程,初始化各种服务和应用程序
安全启动贯穿整个流程,每个阶段都会验证下一阶段的完整性和真实性,确保系统安全。
实操心得:在开发过程中,建议先关闭安全启动功能进行调试,待系统稳定后再启用安全验证,可以避免很多初期开发中的验证相关问题。