STM32MP235启动失败排查:从硬件到软件完整指南
拿到一块STM32MP235的核心板,接上电源,串口线连好,波特率设置成115200,打开终端,上电——终端里一片空白。这就是“STM32MP235 fails to boot”最经典的开场白。
STM32MP235是ST第二代MPU产品线里的一员,基于Arm Cortex-A35应用处理器和Cortex-M33实时内核的异构架构,面向工业网关、智能显示、物联网边缘设备这些场景。和第一代STM32MP1系列相比,它在安全启动、电源管理、外设隔离上做了不少强化,但也正因为这些强化,启动链路变得更长,排查启动失败的复杂度也跟着上来了。这篇文章围绕我实际调试STM32MP235启动失败的过程,把从硬件检查到软件配置的完整排查思路拆开讲清楚,给正在被这块芯片折腾的工程师一点参考。
1. 启动失败先别慌:把STM32MP235的启动链路拆开看
STM32MP235这类MPU的启动过程和单片机完全是两码事。玩过STM32单片机的朋友都知道,上电之后从Flash的某个固定地址开始执行指令,搞个Bootloader也无非是IAP跳转。但到了MPU这一级,芯片内部没有大容量的可执行Flash,程序运行所依赖的外部DDR内存颗粒在上电的瞬间也还没有完成初始化,CPU连代码都没地方放,所以必须有一个分阶段加载的过程。
1.1 BootROM这一步到底干了什么
芯片出厂时固化了一段不可修改的BootROM代码,上电后CPU的第一条指令就从BootROM开始执行。BootROM的任务是先把最小系统跑起来——内核时钟、基础电源域、启动介质对应的接口控制器——然后根据BOOT引脚的组合电平,或者OTP区域里烧写的配置,从SD卡、eMMC、NOR Flash、NAND Flash、USB、UART这些介质中选择一个启动源,把第一级引导程序FSBL(First Stage Boot Loader)加载到芯片内部的SRAM里,再跳转过去执行。
这里有一个很多人第一次接触时会踩的坑:BootROM不像PC的BIOS那样去理解分区表,更不会去FAT32文件系统里寻找什么引导文件,它是直接到固定偏移地址去读取原始二进制镜像的。你随手拿一张SD卡,格式化成FAT32,把编译好的TF-A镜像文件复制进去,插到板子上,结果一定是什么反应都没有。BootROM要的是镜像被烧写到特定扇区偏移处的原始数据,这个细节后面我会用一整章展开讲。
1.2 TF-A、OP-TEE、U-Boot、内核:谁接谁的班
FSBL在ST的官方方案里通常就是Arm Trusted Firmware-A(TF-A)。TF-A运行后先初始化外部DDR内存控制器,配置电源管理,把外设需要的时钟补齐,然后从同一个启动介质里加载FIP(Firmware Image Package)镜像包。FIP里打包了OP-TEE(BL32)和U-Boot(BL33)这两个后续阶段的镜像。OP-TEE负责提供安全世界运行环境,U-Boot作为第二级引导程序初始化设备树、外设、网络、显示这些硬件功能,设置bootargs,最后把Linux内核加载进内存并跳转执行。
你可以把这条链路理解成接力赛:BootROM把第一棒交给TF-A,TF-A把第二棒交给FIP里的OP-TEE和U-Boot,U-Boot再交给内核。每一棒都有自己明确的职责边界和日志输出,链条上任何一棒出了问题,表现就是系统死在那个阶段,并打印对应的错误日志——或者干脆连日志都没有。
1.3 用串口日志判断“死在哪个环节”
排查boot失败的第一步,永远是先看日志停在哪个阶段。我当时调试这块板卡,串口终端上最后一行打到了TF-A的DDR初始化相关输出,之后就再无动静,那基本可以把问题锁定在DDR配置或者后续FIP加载上。如果日志连TF-A的版本信息都没打出来,问题大概率在更前面:要么BootROM没找到有效的FSBL镜像,要么FSBL在加载阶段就被硬件问题卡住了。
我习惯把日志分成几个区间来看:完全静默、只能看到BootROM早期输出、TF-A开始打印、U-Boot开始打印、内核早期打印。每个区间对应不同的排查方向。用日志分段定位的方法,比闷头去翻原理图高效得多,也更容易向同事或者原厂FAE描述问题现状。
2. 上电后完全没反应:硬件层面的排查顺序
如果遇到的是完全没有任何串口输出的情况,不要急着怀疑软件配置,先老老实实回到硬件上查。嵌入式调试里,相当大比例的“完全不启动”都是由硬件层面的小问题引起的,而且这些问题往往发生在你意想不到的地方。
2.1 电源轨和时序:先从万用表量起
STM32MP235这种MPU的电源轨数量远超单片机,核心供电、DDR供电、IO供电、模拟供电经常是分开的独立电源轨。上电之后第一件事,拿万用表逐路测量各路电压是否正常,特别是DDR供电和核心电压。我遇到过一块板子,核心电压纹波偏大,常温下一切正常,温度一上来就启动失败,最后用示波器盯DDR电源的纹波才发现是滤波电容位置不对导致的。
比电压数值更隐蔽的是电源时序问题。MPU通常要求各路电源按特定顺序上电,比如先给VDD再给核心电压,如果电源管理芯片的配置不对,就会出现上电顺序颠倒。这种问题在厂商做好的核心板上很少见,但在自己画板子的时候是高发区。排查的时候拿示波器同时测几路电源的上电波形和复位信号释放点,和参考手册里的时序图逐项对照,基本能确认是不是时序问题。
2.2 BOOT引脚拨码:开发板上的“启动源选择开关”
很多开发板或者核心板上会有一组拨码开关或者跳线,用来选择启动源。STM32MP235和MP1系列类似,通过BOOT引脚的组合电平来确定是从SD卡、eMMC、USB、UART还是其他介质启动。我犯过一个特别低级的错误:为了用STM32CubeProgrammer烧录镜像,把启动模式切到了USB,烧完之后忘了拨回SD卡启动,上电当然起不来,串口一点输出都没有。排查了半天,最后发现只是拨码开关没拨回去。
这个事听起来蠢,但实际工程中真的很容易发生,因为你永远不知道上一手调试的人把开关留在了什么位置。所以第一步应该做的是对照板子原理图,确认当前BOOT引脚电平对应的实际启动源,同时明确测试目标——我们到底想让板子从哪个介质启动。调试排障期间,每次上电之前都确认一下启动模式拨码的实际档位,这个习惯能替你省下大量的无效排查时间。
2.3 时钟与复位:HSE晶振和NRST的隐蔽问题
MPU启动依赖外部高速时钟(HSE),BootROM要起内部PLL,时钟源如果没起振,后面全免谈。我见过一个案例:晶振虚焊,示波器点上没有波形,BootROM把时钟配置成错误状态,系统直接卡死。对于量产板,贴片晶振的匹配电容值不对也会导致起振困难或者频率偏差,这些问题在低温环境下表现更明显。
复位信号同样值得关注。正常情况下上电时NRST引脚应该有一次拉低再释放的过程,用示波器抓一下,如果复位引脚一直被钳在低电平,说明外部复位电路异常,或者有看门狗在反复复位芯片。反复复位这种情况很有迷惑性,从日志上看像是“每次都启动到同一个位置就死了”,实际上是芯片被复位打断又重新启动,形成了循环。遇到日志反复重演的情况,记得先确认复位信号有没有问题。
2.4 调试串口型号与电平:日志没出来之前先确认通道
串口是MPU调试最重要的通道,但很多人栽在串口本身。首先确认调试串口用的是哪一组UART,STM32MP235的官方开发板一般会把调试串口引到固定的引脚上,但你自己设计的板子可能完全不同,必须看原理图确认。其次确认电平,板上是否有USB转串口芯片,还是直接引出的TTL电平,两种情况接线方式完全不同。再有就是波特率,常见的是115200 8N1,但有些板子在引导阶段可能用更低速率,或者引导程序和内核阶段使用不同波特率,遇到日志中断可以试着换几个波特率看看。
我当时调试的时候,一度以为板子完全没启动,后来发现是USB转串口线坏了,换了一根线马上有日志输出。排查的第一步永远是把串口通道验证好——可以把串口的TX和RX短接做自发自收测试,确认通路没问题再往下查设备。
3. 有日志但卡在初始化:FSBL与信任链的定位方法
硬件排查是“外功”,FSBL及后续阶段的日志分析就是“内功”。接下来专门讲有日志输出但系统初始化不通过的情况,这种情况在启动失败里占比最高,因为硬件问题往往比较直观,而启动链路各阶段的配置问题则需要结合日志逐层定位。
3.1 日志卡在哪个函数,问题就锁定在哪个模块
TF-A启动过程中会在串口输出一系列NOTICE和ERROR信息。比如初始化DDR之前会有对应的内存检测日志,加载FIP之前会有介质读取的信息。如果你的日志停在了DDR初始化相关的位置,那就应该把目光集中在DDR这一块,而不是跑到U-Boot的配置里去找原因。
我当时调试手头这块STM32MP235板卡时,日志停在了TF-A BL2阶段的早期,大概是在初始化DDR的地方。TF-A打印了DDR初始化相关的信息,但后续没有出现正常的FIP加载输出。这说明TF-A认为DDR初始化失败了,或者初始化之后回读校验不过。这类问题多半和DDR颗粒型号、DDR初始化参数、PCB布线质量有关。
3.2 DDR初始化失败的典型日志和排查
DDR初始化是整个启动链路中最容易出问题的环节之一。MPU的外部DRAM不是插上就能用的,要根据颗粒型号、容量、位宽、时序参数做一整套寄存器配置。TF-A里编译进去的DDR配置如果和实际颗粒不匹配,轻则初始化失败,重则初始化流程能过但系统一跑就随机死机。典型的日志长这样:
NOTICE: BL2: v2.10-stm32mp2-r1 (stm32mp235) NOTICE: BL2: Built : 09:30:00, May 20 2025 NOTICE: BL2: DDR memory init... ERROR: DDR memory configuration failed排查DDR问题时,先核对板子上实际使用的DDR颗粒和参考设计是否一致,再核对TF-A里对应DDR初始化文件中的参数:容量、位宽、频率、时序参数。STM32CubeMX在生成工程时会根据选择的板卡自动带入DDR配置,但如果核心板是你自己设计的,这部分必须认真手工核对,尤其是PHY校准相关的参数,很容易因为PCB走线的细微差异导致失败。
3.3 签名与OTP:MP2新增的安全约束
STM32MP2系列比MP1在安全启动上强化了不少。如果OTP区域已经烧写了强制安全启动的配置,那么BootROM只会加载带有效签名的FSBL,任何未签名或者签名校验失败的镜像都会直接拒绝启动。这类问题的特征很明显:BootROM可能有打印,TF-A完全不出现,或者TF-A打印了签名校验失败的ERROR信息。
排查时先确认当前芯片的OTP配置状态,STM32CubeProgrammer可以读取OTP。开发阶段如果不是在联调安全启动,我建议不要把OTP的安全启动使能位提前烧进去。一旦烧进去,之后每次调试都要面对镜像签名问题,严重拖慢开发节奏。而且OTP是一次性可编程的,烧错了不能改回来,这个教训在很多项目里都出现过。
3.4 用STM32CubeMX重建FSBL和FIP
当FSBL相关配置可疑时,重建一套干净的FSBL和FIP通常比在旧配置上猜来猜去更高效。STM32CubeMX支持为STM32MP2系列生成TF-A、OP-TEE、U-Boot的整套工程模板,生成之后编译产出TF-A二进制、FIP镜像,再用ST官方工具烧进启动介质。
这一步的关键是选对CubeMX版本和固件包版本。某些早期的MP2固件包存在已知的启动问题,升级到最新版可能就解决了。我遇到过一次情况:用老版本固件包生成的TF-A在MP235上启动时挂掉,换成新版本固件包重新生成后一次通过。ST在MP2系列上的迭代很快,保持工具链和固件包更新,是降低启动排障成本的重要一环。
4. 启动源和烧录镜像:SD卡、eMMC的分区与偏移真相
有日志、硬件也没问题,但系统就是起不来,这时候十有八九是启动介质里的镜像布局不对。这节专门讲SD卡、eMMC这类启动介质的分区布局和烧录细节,也是STM32MP235启动失败里最容易忽略的一块。
4.1 BootROM找镜像不看分区表,只看偏移
这是嵌入式MPU和PC最大的不同。PC的UEFI固件会去扫描GPT分区表里的ESP分区,寻找bootloader文件;而STM32MP235的BootROM不会解析任何复杂的文件系统,它是直接寻址读取SD卡或eMMC上某个固定偏移处的原始二进制数据。以STM32MP1系列为参考,FSBL镜像位于SD卡的某个固定扇区偏移,随后紧跟的是FIP镜像位置。MP2系列的具体偏移以官方参考手册为准,不同系列、不同版本之间可能有差异。
很多人第一次接触时,把SD卡插到电脑上,格式化成FAT32,把TF-A和FIP文件拷贝进去,再把SD卡插回板子,然后发现启动失败——原因就是BootROM根本不认识FAT32文件系统里的文件,它只去固定位置找原始数据。想验证很简单:用十六进制工具直接查看SD卡对应偏移区间的数据,如果看到的不是二进制镜像内容而是一堆FAT文件系统标记,说明镜像根本没写对地方。
4.2 用STM32CubeProgrammer安全的烧录流程
STM32CubeProgrammer是ST官方的烧录工具,也是处理STM32MP235启动失败时绕不开的利器。它可以烧写SD卡、eMMC、NOR等启动介质,也可以操作OTP、读取芯片信息。
标准烧录流程大致是:准备好一个包含flashlayout文件的工程目录,flashlayout里定义了FSBL、FIP等镜像要写到哪些偏移位置;把目标板BOOT拨码切到USB启动(或UART/ST-LINK模式,取决于开发板设计);用USB线连接PC和目标板;在STM32CubeProgrammer里选择对应接口和配置文件,执行下载。烧录完成后把拨码切回正常启动源,复位板子。
这里容易被忽略的细节是外部加载器(External Loader)的选择。如果板子上用的是eMMC,需要选择对应的eMMC加载器文件;如果加载器选错,烧录工具可能无法正确识别存储介质,或者烧录进去之后BootROM依然无法正常读取。
4.3 PC的“no boot device”和MPU的“启动失败”其实是一回事
前面提到的“no boot device found.press any key to reboot the machine”这类PC启动报错,在MPU世界里对应的就是BootROM把可用的启动源都尝试了一遍,但没找到有效的FSBL镜像。PC上会给出明确的英文提示,而STM32MP235的BootROM通常不会输出这么人性化的话,往往就是安静地失败。
理解这一点对调试很有帮助:如果你把启动介质拔掉,或者介质里FSBL偏移处是空的,板子就处于这种“找不到启动设备”的状态。所以当板子完全静默无日志时,先假设它处于这种状态,然后检查镜像是否真的被写进了正确的介质偏移位置,比反复怀疑硬件更有效。
4.4 烧录后第一次启动失败的常见原因
烧录流程本身显示成功,但启动还是失败,这种情况也经常遇到。我总结过几个高频原因:第一,烧录时选择了错误的flashlayout文件或加载器,导致FSBL实际被写到了错误偏移;第二,烧录后启动模式拨码没有切回正确的启动源;第三,镜像和芯片型号不匹配,比如用了STM32MP1系列或者其他型号的FSBL去启动MP235,相互之间不兼容;第四,eMMC或SD卡的接口电压配置与BootROM的默认配置不一致,导致BootROM无法稳定读取介质。
这些问题的共同特征在于:烧录工具显示编程完成,但启动日志完全静默或者只有极少输出。遇到这种情况先不要反复烧录,停下来核对三件事:镜像对不对、偏移对不对、启动源对不对。
5. 我总结的快速定位清单与避坑经验
前面几章把STM32MP235启动失败的主要排查方向都过了一遍,最后这部分是我个人的总结,整理成了一套可以直接照着做的排查清单,以及一些容易踩的坑。
5.1 五分钟快速定位法
- 确认调试串口通道本身是通的,线缆、电平、波特率都检查一遍;
- 确认启动模式拨码或OTP选中的启动源和预期一致;
- 上电观察是否有任何串口输出,完全没有输出就先测电源、时钟、复位;
- 有早期输出但卡住,把日志定格,对照TF-A各阶段标志信息确认卡点;
- 卡在镜像加载相关阶段,用STM32CubeProgrammer重新烧录正确偏移的镜像;
- 烧录后仍失败,换一套干净的STM32CubeMX生成工程,排除配置污染。
这套顺序基本覆盖了从硬件到软件的完整排查链路,按序执行能在短时间内把问题范围缩小到具体模块。
5.2 容易被忽略的细节
有几个细节是踩过坑之后才格外注意的,列出来给大家提个醒:
- 开发板自带的SD卡可能已经烧录过一套旧镜像,直接使用前先确认镜像版本是否匹配当前板卡;
- 某些核心板是通过电阻配置BOOT引脚,而不是拨码开关,换板子时一定要重新看原理图;
- STM32MP2系列的电源域划分比MP1更细,如果软件里配置了不支持的电源状态,启动可能卡在电源管理初始化;
- 串口调试默认波特率各阶段可能不同,某些情况下需要尝试多个波特率才能看到完整日志;
- OTP配置是不可逆的,开发阶段不要随意烧OTP,尤其是安全相关选项。
5.3 资料查找路线与参考手册用法
STM32MP235的资料查找,我推荐优先看ST官方的Reference Manual中的Boot章节、STM32CubeMP2固件包里的Docs目录,以及ST官方Wiki。很多启动问题在官方Wiki上能找到对应的说明或已知问题记录。另外,ST在Github上的tf-a、u-boot仓库的commit记录里也经常能翻到针对特定启动问题的修复,值得花时间搜一搜。
最后说一个我在实际调试中的体会:遇到启动失败,不要急着怀疑芯片坏了。STM32MP235这种复杂度远超单片机的平台,启动失败几乎总是由可复现的配置问题引起的。按照“串口通道 → 启动源 → 电源时钟复位 → 镜像偏移 → 信任链 → DDR配置”这样的顺序来排查,绝大多数问题都能在半小时内定位到真正的根因。我当时那块板子最后查出来就是FIP镜像里打包的U-Boot版本和TF-A版本不匹配,导致启动链在传递环节崩溃,重新生成一套版本匹配的镜像组合之后,一切恢复正常。
