STM32MP235启动失败排查:MPU调试避坑指南

发布时间:2026/8/31 22:08:32
STM32MP235启动失败排查:MPU调试避坑指南 我是做嵌入式Linux开发的这几年经手的板子从MCU到MPU换了好几代但要说调试过程中最让人头疼的还是“上电之后啥反应都没有”这种问题。前阵子手头一块基于STM32MP235的核心板就让我结结实实折腾了两天。板子是新的固件是新的原理图也是照着官方参考设计改的结果上电之后串口一个字符都不打印LED也不闪整块板子跟没通电一样。这篇文章就把这次排查“STM32MP235 fails to boot”的完整过程写出来。包括我从拿到板子到最终定位问题的每一步思路、用到的工具、踩过的坑以及一些常规文档里不会写的经验。如果你也在调STM32MP2系列或者正准备用这颗芯片做产品这篇文章应该能帮你少走不少弯路。尤其是那些第一次从MCU转MPU的朋友MPU的启动流程跟单片机完全是两码事很多坑是MCU时代根本不会遇到的。1. 内容整体设计与思路拆解1.1 先弄清楚MPU和MCU的启动差异很多人拿到STM32MP235这种芯片第一反应是“这不就是个带Linux的STM32嘛”然后按照MCU的思路去调。这是最大的误区。STM32MP235属于MPU微处理器内部有Cortex-A35内核跑的是Linux或者裸机AMP方案。它的启动流程和传统STM32F103那种MCU完全不一样。MCU的启动很简单上电后CPU从固定的地址比如0x08000000取指执行用户代码直接跑起来。而MPU的启动是多级引导芯片内部的ROM Bootloader先运行然后根据Boot引脚的电平状态决定从哪个设备加载下一级程序SD卡、eMMC、NAND、USB、UART等。这一级程序可能是U-Boot SPL或者TF-ATrusted Firmware-A然后由它再加载完整的U-Boot和Linux内核。STM32MP235这颗芯片在ST的产品线里属于新一代MPU相比上一代MP1系列它使用了更小的封装功耗更低而且集成了Cortex-M33实时核主打低功耗边缘计算场景。但这也意味着它的启动链路更复杂DDR初始化、电源时序、时钟配置任何一个环节出问题都会直接表现为“fails to boot”。1.2 启动失败问题的通用排查路径在开始动板子之前我习惯先梳理一个排查路径避免像无头苍蝇一样乱试。对于“上电不启动”这类问题我总结的通用路径是第一步确认电源是否正常供电各路电压是否达到芯片要求的阈值第二步确认时钟系统尤其是外部晶振是否起振第三步确认Boot引脚配置是否正确芯片到底想从哪里启动第四步确认调试串口是否有输出用串口打印来定位卡在哪个阶段第五步确认DDR初始化是否通过DDR不出来后面全是白搭第六步确认FSBLFirst Stage Boot Loader是否被正确加载和执行这次排查STM32MP235就是严格按这个顺序走下来的。事实证明这种思路虽然看起来慢但效率其实最高因为每一步都能排除一批可能的原因。1.3 这次项目的硬件环境和背景先交代一下硬件环境。这次用到的板子是一块自己画的四层核心板主控是STM32MP235KAT7搭配了512MB的DDR3L、一片8GB eMMC、一个Micro SD卡座还有一路调试串口UART4对应PD6/PD9引脚调试口引到了USB转串口模块上。SD卡里面烧的是ST官方提供的OpenSTLinux系统镜像整个SD卡的烧录方式是使用STM32CubeProgrammer。按理说这套组合是ST官方标配SD卡启动模式也是MP1时代最成熟的方式。结果上电后串口完全没反应。一开始我以为是串口接线问题或者USB转串口模块坏了换了好几个模块确认硬件没问题之后才开始认真对待“fails to boot”这个现象。2. 核心细节解析与实操要点2.1 电源树与复位时序MPU启动的第一道关卡STM32MP235对电源的要求比MCU严格得多。它不像STM32F4那样一个3.3V就能跑而是需要多路供电包括VDD_CPU、VDD_GPU、VDD_IO、VDD_MMC等不同的电源域。上电时序也有要求如果各路电压到达的时间差太大芯片内部的POR上电复位电路可能会误判导致芯片一直处于复位状态。我在排查电源的时候一开始用万用表量了各路电压发现都在正常范围内就觉得电源没问题。后来用示波器抓了上电瞬间的波形才发现VDD_CPU和VDD_IO之间差了将近20ms。这个时间差在数据手册里是超标的。虽然芯片没有明显烧毁的迹象但内部逻辑可能因为时序不满足而无法正常启动。这里要特别提醒一下万用表只能量稳态电压上电瞬间的动态过程必须用示波器看。而且至少要抓两路信号的相对时序单个电压看“有电”不代表“按时有电”。调试MPU级别的板子示波器是必备工具没有的话真的会寸步难行。电源问题解决之后串口依然没有输出说明问题不只这一处。但这给我提了个醒STM32MP235这种新芯片第一版板子最好严格按照官方参考设计做电源树不要自己优化哪怕觉得“某个电容没必要放”也别省。经验告诉我MPU的电源噪声容限比MCU小得多滤波电容的位置和数量都会影响稳定性。2.2 Boot引脚配置芯片到底想从哪里干活电源搞定之后我开始怀疑Boot引脚的问题。STM32MP235和STM32MP1一样有一组Boot引脚BOOT0、BOOT1、BOOT2通过它们的电平组合决定启动源。比如全部拉低是从SD卡启动BOOT2拉高是从eMMC启动还有一些组合对应USB/UART烧录模式。我检查了自己的板子BOOT0、BOOT1、BOOT2都通过10K电阻下拉到了地理论上应该是SD卡启动。用万用表量了引脚电平确实是低电平。但问题来了——我用的STM32MP235封装是BGA引脚非常密万用表表笔根本探不到芯片引脚本身只能在过孔或者测试点上量。万用表量到的是低电平不代表芯片引脚真的就是低电平焊接时的桥连、虚焊都有可能导致信号不对。为了排除这个问题我找了一块ST官方的评估板做对照。官方板同样配置下可以正常打印启动信息。这就说明问题出在我自己板子的硬件上而不是芯片型号差异或者镜像版本问题。排除法在硬件调试里是最有用的方法论。后来我把板子放到显微镜下面检查BGA焊接发现有两个焊盘存在轻微的桥连用烙铁拖焊处理完之后Boot引脚的信号就正常了。这里想说的是BGA焊接不良在MPU调试中非常常见特别是手工贴片或者小批量试产的时候。如果你也遇到类似问题最好先检查BGA焊点别急着怀疑芯片坏了。2.3 串口调试输出的判断方法串口没有输出这个问题本身就值得好好分析。在MCU时代程序卡死了可以接上调试器看寄存器但在MPU时代调试器不一定管用尤其当DDR都没初始化的时候JTAG/SWD也不一定能连上。串口是唯一的救命稻草。STM32MP235的启动ROM会执行一段固化在芯片内部的代码这段代码会尝试根据Boot引脚配置去加载外部程序。如果加载失败理论上串口会输出错误信息。但有个前提你接的串口引脚必须正确而且波特率要对得上。我这次用的是UART4对应的引脚是PD6TX和PD9RX。在检查了接线没问题、USB转串口模块确认是好的之后我用示波器量了PD6引脚发现上电后完全没有任何电平跳变。这说明芯片根本没有在串口上输出任何数据——要么ROM没有运行要么运行了但没走到串口初始化这一步要么压根没检测到合法的启动介质。这里有个实操经验排查串口无输出时不要只盯着有没有字符先用示波器看引脚有没有电平变化。如果有数据波形但终端不显示那是波特率或者终端软件设置问题如果一片死水那是芯片根本没干活。这两种问题的排查方向完全不同提前分清可以节省大量时间。我用逻辑分析仪抓了PD6引脚的波形在确认确实没有数据后基本可以断定问题是出在硬件层面的跟软件配置关系不大。因为官方的大多数OpenSTLinux镜像默认是支持UART4打印的不太可能在软件上卡死连一点输出都没有。2.4 DDR初始化的隐性关卡在我几乎要把硬件从头到尾查一遍的时候突然想到一个细节STM32MP235的启动流程中ROM在加载FSBL之前会先执行DDR初始化。这个DDR初始化代码是存放在芯片内部ROM里的但它依赖外部DDR颗粒的硬件连接正确性。如果DDR的布线有问题比如地址线错位、数据线短路、时序不满足就会导致DDR初始化失败。初始化失败的直接表现就是启动卡死串口没有输出。这和Linux系统启动到一半崩溃的表现不一样更像“完全没有反应”的死寂状态。官方SDK里有对应的DDR tuning工具可以通过STM32CubeProgrammer直接往芯片里加载一个测试固件用来验证DDR的读写是否正常。但这里有个前提你得能进入USB或UART烧录模式。我这块板子因为Boot引脚之前有焊接问题USB模式也进不去所以DDR测试工具根本跑不起来。这就是所谓的“死循环”——板子起不来没法用工具诊断而没有诊断又不知道从哪里修起。遇到这种局面我的做法是把可能的问题列一个优先级表然后一个个去排除。从上到下依次是焊接工艺、电源时序、时钟、Boot引脚、DDR连接。好消息是这类问题一旦找到根源解决起来往往很简单坏消息是查找的过程异常煎熬。这也是为什么我一直强调做MPU级别的硬件第一次打板最好直接抄官方的参考设计不要做任何“优化”。3. 实操过程与核心环节实现3.1 硬件检查的操作流程我是严格按照以下步骤来排查的每一步都做了记录。这里把这个流程整理出来你可以直接拿来用。第一步目测检查。把板子放在显微镜下从电源芯片到主控芯片逐个检查焊点。重点看BGA是否有桥连、虚焊、少锡。这一轮我发现了Boot引脚的桥连问题。第二步电源测试。用示波器同时抓取多路电源的上电波形对照数据手册的时序要求一一验证。尤其注意VDD_CPU和VDD_IO的上电顺序以及各路电压是否有过冲或跌落。如果示波器探头数量不够可以分批次抓但要保证每次都有一路参考信号做时间对齐。第三步时钟测试。用示波器探头点测外部晶振引脚看是否有振荡波形。STM32MP235需要外部提供32.768KHz的RTC时钟和24MHz的主时钟任何一个不工作都会导致启动失败。我这次主时钟晶振的波形正常但RTC时钟的振幅偏小换了一颗晶振后波形恢复正常。第四步Boot引脚电平测试。在确认焊接没问题后在靠近芯片引脚的位置量BOOT0到BOOT2的电平。这里要特别小心不要用万用表去量BGA正面的引脚容易短路相邻焊盘。我是在背面的过孔上量的。第五步串口波形测试。在确认前面所有硬件条件正常之后上电瞬间用示波器观察调试串口的TX引脚看有没有数据波形。这个步骤在排查“无输出”问题时极其关键。为了让你更容易理解整个排查过程我做了一张简单的对照表记录每一阶段的现象和结论检查项工具正常状态本次实测结论供电电压万用表VDD_CPU0.8V/1.2VVDD_IO3.3V电压正常通过上电时序示波器各路电压按序到达VDD_CPU滞后20ms异常修复主时钟示波器24MHz晶振起振波形正常通过RTC时钟示波器32.768KHz起振振幅偏小异常更换Boot引脚万用表BOOT0/1/2低电平桥连导致不稳定异常修复串口波形逻辑分析仪上电有数据输出无任何电平变化修复后正常3.2 使用STM32CubeProgrammer验证启动介质硬件检查做完一遍确认没有明显问题之后我重新做了SD卡启动测试。这次我没有直接插上SD卡上电而是先用STM32CubeProgrammer连接芯片确认芯片的ROM Bootloader是否在正常工作。STM32CubeProgrammer可以通过USB或UART与芯片内置的ROM通信读取芯片信息。如果你能在工具里看到芯片的Device ID说明芯片内部的ROM Bootloader是完全正常的问题出在后面的启动介质或者FSBL上。如果连Device ID都读不到那问题可能出在USB/UART接口电路、Boot引脚或芯片本身上。我这块板子在修复完BGA桥连和RTC晶振后再用STM32CubeProgrammer通过UART连接已经能正常读到芯片信息了。这说明ROM运行正常。然后我把SD卡插入重新上电这次串口终于开始输出启动日志了。从打印的内容看U-Boot SPL被成功加载DDR初始化通过然后加载了TF-A接着是U-Boot主程序最后是Linux内核。如果你也遇到了“fails to boot”建议在拿到一块新板子时先不管系统能不能起来第一步就用STM32CubeProgrammer去连接一下芯片确认ROM是活的。这一步相当于给芯片做个“健康检查”能省掉大量无意义的猜测。3.3 从打印日志定位卡死阶段一旦串口能输出日志了定位问题就轻松多了。MPU的启动过程是分阶段的每个阶段都有对应的日志输出。根据日志停在哪一行你就能判断问题出在哪一段。STM32MP235的启动日志大致是这样一个顺序首先是ROM阶段的提示信息也可能是空的然后是FSBL即TF-A或U-Boot SPL的初始化日志包括DDR初始化信息然后是U-Boot主程序的日志包括加载内核、设备树等信息最后是Linux内核的启动日志。如果日志停在DDR初始化说明DDR硬件或配置有问题。我在调试另外一块板子的时候就遇到过一次DDR初始化报错提示“DDR init failed”。后来查下来是DDR的时序参数配置不对板子上的DDR3L颗粒和默认配置的型号不一致通过修改设备树里的DDR参数才解决。如果日志停在U-Boot阶段说明U-Boot环境变量、启动介质、内核镜像有问题。一个常见的坑是SD卡的分区表被破坏了U-Boot找不到boot.scr或者kernel镜像。重新烧录SD卡镜像通常能解决。如果日志停在Linux内核阶段那就要抓内核的启动日志了。可以通过修改内核启动参数加上earlycon来打印早期的串口信息帮助定位内核崩溃的位置。这个过程用到的命令很简单# 在U-Boot环境变量中设置内核启动参数 setenv bootargs consolettySTM0,115200 earlycon saveenv boot不过这些都是后面的事情了。对于最开始那种“串口完全没输出”的情况最关键的就是把硬件层面的问题一个个排除掉。3.4 BootROM阶段的日志获取技巧这里分享一个容易被忽略的技巧STM32MP235的BootROM在某些情况下输出信息不是从高电平开始有数据的而是会有一段很短的波形。如果示波器触发电平设置不对容易漏掉。我一般会把触发电平设为0V到1.8V的中间值并且用单次触发模式这样能抓到上电瞬间的第一个跳变。另外一个技巧是BootROM在找不到合法启动介质时会进入烧录模式USB或者UART此时如果你在电脑上运行STM32CubeProgrammer可以发现一个新设备。即使在串口上没有任何输出只要USB枚举成功就说明ROM还活着。这个现象可以作为“芯片是否在工作”的旁证。我在早期排查时就是用这个方法确认了芯片本身没有损坏。如果你使用的是UART烧录模式还有个小坑默认的UART烧录引脚可能不是你板子上接的那个串口需要查询数据手册确认。比如STM32MP235支持UART4和USART2作为烧录口但具体哪个取决于Boot引脚的电平状态和ROM配置不要想当然地认为“板上只有这一路串口那就是它”。4. 常见问题与排查技巧实录4.1 常见问题速查表把这次调试过程以及之前调试其他MPU板子遇到过的典型问题汇总了一下整理成一张速查表。遇到启动失败时对照这张表可以快速缩小范围。现象可能原因排查方法解决方案上电后串口无任何输出电源时序错误示波器抓上电波形调整电源芯片的使能顺序上电后串口无任何输出Boot引脚焊接问题显微镜检查量电平返修BGA焊点上电后串口无任何输出RTC晶振不工作示波器量波形更换晶振检查负载电容上电后串口无任何输出DDR初始化失败查看SPL日志检查DDR布线、调整参数输出少量乱码后停止波特率不匹配确认串口工具设置固定使用115200-8-N-1停在U-Boot阶段SD卡分区异常重新烧录镜像使用STM32CubeProgrammer烧录停在DDR初始化阶段DDR颗粒型号不匹配修改设备树DDR参数换成与配置一致的DDR颗粒能进U-Boot但进不了内核内核镜像损坏检查SD卡中的内核文件重新烧录或更换SD卡上面这些条目里最容易被忽视的是第二条和第四条。尤其是DDR初始化失败在MCU时代完全不存在这个问题但在MPU领域它是最常见的启动失败原因之一。我见过不少人在这个坑里浪费了好几天如果你第一次调MPU优先怀疑电源和DDR大概率没错。4.2 排查中容易忽略的细节我在这次排查过程中有几个细节是踩了坑才注意到的写在这里给各位提个醒。第一个是示波器探头的接地。测量高频信号时探头的地线夹如果太长会引入噪声导致波形失真。我量RTC晶振的时候一开始用的长地线夹波形看起来乱七八糟还以为是晶振本身的问题。后来换上了短弹簧地波形立刻变得干净了。如果你也在量晶振波形务必使用短地线。第二个是SD卡的质量问题。很多“启动失败”其实是SD卡太杂牌芯片的MMC控制器识别不了。建议使用Class 10或者UHS-I级别的卡闪迪、三星等大厂的卡兼容性最好。我手头有一堆杂牌卡在调试时浪费了不少时间后来换了一张正规卡问题直接消失。第三个是电源纹波。MPU对电源纹波比MCU敏感得多尤其是在高频运行状态下。检查电源时要看纹波而不是只看平均值最好是满载状态下测量。纹波过大会导致芯片内部逻辑误触发出现“时好时坏”的诡异问题。我见过一个案例板子有时候能起来有时候起不来查了一个星期最后发现是DC-DC电感选型不对导致纹波过大。第四个是串口工具的选择。不要用那些杂牌的USB转串口模块很多模块在115200波特率下会出现丢字节的问题让你误以为芯片没有输出。我建议直接用FT232或者CP2102这类成熟方案稳定性和兼容性都有保障。嵌入式调试中工具的好坏直接决定调试效率这一点在今天的场景中体现得淋漓尽致。4.3 梳理启动时序与打印位置的关系MPU的启动过程和代码执行位置是一一对应的。整理清楚这个对应关系能帮你从日志的输出位置反推出问题所在。以STM32MP235为例完整的启动时序是这样的上电芯片内部的ROM代码开始执行。这个阶段没有任何用户可见的输出除非配置了特殊的调试引脚。ROM根据Boot引脚选择启动介质然后从介质中加载FSBLTF-A BL2或U-Boot SPL到内部SRAM。由于SRAM容量有限这个阶段的代码体积必须很小。FSBL执行初始化DDR、时钟等外设然后把下一级镜像U-Boot主程序从启动介质加载到DDR中。U-Boot主程序执行读取环境变量加载内核和设备树到DDR然后跳转到内核入口。Linux内核启动打印内核日志挂载根文件系统最终进入用户空间。如果你在串口上看到了类似“U-Boot SPL”的日志但后续没有内容了说明问题出在DDR初始化或者FSBL跳转阶段。如果看见了“U-Boot”的logo和打印信息但卡住了说明问题出在启动介质读取或环境变量配置。如果内核日志打印到一半停了说明有驱动初始化失败或者硬件不兼容。不同阶段的信息量差异很大有时你可能需要去掉quiet参数来获取更多调试信息。在U-Boot里设置bootargs时加上loglevel8在内核启动时能看到更多调试信息。这些技巧结合起来能让你从一段简单的启动日志中提取出大量问题线索。4.4 如何快速判断芯片是否还活着排查MPU启动失败的时候最核心的问题是芯片到底是不是在运行这里有几个不依赖串口的快速判断方法。第一个方法是看复位引脚的波形。正常启动时复位引脚在上电后应该保持一段时间低电平然后拉高。如果复位引脚一直为低说明芯片一直处于复位状态可能是外部复位电路有问题也可能是内部的POR电路在反复触发。第二个方法是看时钟输出引脚。STM32MP235的MCO引脚可以输出内部时钟信号如果你在硬件上引出了这个引脚可以通过示波器看是否有波形输出。如果没有引出也可以尝试在BootROM阶段使用特定的Boot引脚组合进入USB烧录模式然后观察USB枚举是否成功。枚举成功说明芯片内部在运行。第三个方法是用热成像仪或者手摸芯片表面温度。虽然这个方法不够精确但有时能提供线索。芯片如果完全死机温度通常接近环境温度如果内部时钟在跑但卡在循环里芯片会微微发热。在早期故障排查阶段这个“土办法”有时能快速区分“没供电”和“代码卡死”两种情况。如果以上方法都试过还是无法判断那就只能返回最基础的步骤检查焊接、检查电源、检查时钟。MPU启动失败问题的根源90%以上出在这三个环节。嵌入式系统调试就是这样很多时候不是技术含量不够而是耐心和细心不够。5. 经验总结MPU调试的几条重要心得5.1 开发环境与工具选型很重要这次用STM32MP235调试开发环境是Ubuntu 20.04 STM32CubeProgrammer OpenSTLinux SDKU-Boot源码和内核源码都从ST官方仓库拉取编译。PC端串口工具用的是Minicom示波器是Rigol的DS1054Z逻辑分析仪是Saleae的逻辑16。工具选型看起来都是常规选择实际使用中还是有几点值得说。STM32CubeProgrammer在Linux下的USB驱动偶尔会出问题表现为无法识别设备。这时候通常需要检查一下udev规则或者用UART模式代替USB模式。我在调试过程中有几次USB连不上改用UART模式后立刻就能通信了。另外调试MPU这类复杂系统时我习惯同时开着串口终端和逻辑分析仪。串口负责看日志逻辑分析仪负责抓GPIO信号和协议时序。两者配合很多时候能同时定位软件和硬件问题。比如启动过程中某个GPIO没有按预期翻转通过逻辑分析仪一眼就能看出来。5.2 一块新板子的调试顺序建议基于这次的经验我给正准备调试STM32MP235新板子的朋友一个建议顺序。第一步先不焊DDR和eMMC只焊接最小系统包括电源、时钟、主控、串口。然后上电用STM32CubeProgrammer连接芯片读取Device ID。如果这一步能通过说明芯片活着ROM在跑。第二步焊接DDR再次上电用STM32CubeProgrammer加载DDR测试固件确认DDR读写正常。如果DDR测试通过说明DDR焊接和布线基本没问题。第三步焊接eMMC或接SD卡烧录系统镜像开始正常的启动调试。第四步如果一切正常再逐步加入其他外设比如网口、USB、显示等每个外设单独验证。这种分步上电的思路其实是在芯片原厂的参考流程中提炼出来的。一次把整板焊齐如果启动失败你能排查的范围是整个板子工作量巨大分步焊接每次只增加一个变量出现问题时能快速锁定范围。这个方法最适合开发初期的硬件验证阶段。5.3 一个容易被忽略的启动卡死点最后再分享一个容易忽略但非常重要的问题——eMMC的RST_B引脚。eMMC芯片有一个复位引脚正常情况下应该被拉高或者由主控控制。如果这个引脚悬空或者被错误地拉低eMMC会一直处于复位状态导致主控无法识别eMMC。在SD卡启动模式下如果eMMC的RST_B引脚悬空可能会通过内部上拉电阻保持高电平大部分情况下不影响启动。但在某些芯片组合下悬空引脚受到的干扰可能导致eMMC异常进而影响SD卡启动流程。具体表现为从SD卡启动时FSBL加载正常但U-Boot在读取环境变量时卡死。如果你也遇到类似“不是每次都能启动”或者“特定情况下启动失败”的问题建议检查一下eMMC的RST_B引脚是否有明确接法最好用10K电阻上拉到VCC而不是悬空。多花一颗电阻的成本能省下无数排查的时间。5.4 整体体会这块STM32MP235的板子最终在一个周末的下午成功进入了Linux系统。看到登录提示符的那一刻说实话还是有点成就感的。回头看看问题本身并不复杂无非是BGA焊接和晶振起振两个硬件小问题。但排查过程却花了两天多主要原因是前期没有按照系统性的排查思路走走了不少弯路。我个人的体会是调试“fails to boot”这类问题最大的敌人不是技术难度而是信息不足时的盲目猜测。一个清晰的排查路径、一组靠谱的调试工具、一份完整的排查记录这三样东西能帮你解决90%的启动问题。剩下10%的诡异问题往往也需要回到这三点去寻找突破口。