
1. 先立框架高通启动链路的整体设计逻辑1.1 为什么高通启动流程值得专门拆一次很多人搞嵌入式三五年单片机、Linux驱动都玩得转但一碰到高通平台的板子就发怵。原因很简单这东西从你按下电源键到系统桌面出现中间经过的固件环节比STM32多出一个数量级而且每个环节都有自己的log、自己的烧录方式、自己的坑。如果你不理解整个链条遇到不开机就只能靠猜效率极低。这篇文章我从复位信号落地那一刻开始拆一路拆到Linux内核把init进程拉起来为止。里面涉及的是我在实际调板过程中反复验证过的细节包括PBL、XBL、TZ、ABL这些固件各自干了什么事串口log里每一行代表什么以及最让人头疼的DDR初始化、安全校验、分区表读取这几个环节。适合正在做高通平台bring-up、Android底层移植或者单纯想搞明白手机开机到底发生了什么的工程师。看完之后你至少能回答这三个问题当前设备卡在哪一步、为什么卡在这、下一步该查哪个信号或哪段log。1.2 五棒接力的完整链路画像高通平台的启动本质上是逐级加载、逐级校验的过程我习惯把它叫五棒接力第一棒PMIC上电时序完成后CPU复位释放Boot ROM里的PBL开始执行。第二棒PBL初始化最小时钟和外设读取启动设备加载SBL或XBL的loader阶段。第三棒XBL loader做DDR初始化与训练加载TZ、hypervisor等安全固件同时读取GPT分区表。第四棒UEFI环境下的ABLAndroid Boot Loader加载Linux内核与DTB把控制权交给kernel。第五棒kernel完成设备初始化、挂载根文件系统启动init进程最终拉起Android系统服务或QNX原生系统。每一棒都由上一棒验证签名形成一条完整的安全启动链。这种设计和PC的BIOS启动有相似之处但高通为了兼顾手机功耗、快速开机以及安全防护做了非常多定制。后续我会逐棒拆开讲但先记住一个核心观念高通启动不是一个文件从头跑到尾而是多段固件按顺序接力每一段都有明确的职责边界和log输出点。2. 固件接力PBL到ABL的每一棒细节2.1 PBL芯片出厂就固化好的第一段代码PBL全称Primary Boot Loader它固化在芯片内部的Boot ROM里出厂就存在不可修改。上电后CPU复位结束第一条指令就是从这段ROM代码开始执行。它的职责非常聚焦初始化最基础的时钟比如XO振荡器、配置启动引脚BOOT_CONFIG、检查eFuse里的熔丝状态然后根据启动设备枚举顺序去读取后续固件。这里有一个容易被忽略的点PBL本身不初始化DDR因为DDR还需要训练PBL没有那么大的代码空间和能力去做这件事。它只能使用芯片内部的少量SRAM所以PBL加载的下一级固件必须足够小小到能塞进内部SRAM里运行。这也是为什么高通平台会有SBL1和XBL loader这种专门负责过渡的固件阶段存在。在实际调板中判断PBL有没有跑起来最直接的办法是看电流。如果板子上电后电流只有几十毫安同时串口完全没有输出那大概率PBL之前就出了问题。这时候要检查的不是软件而是PMIC的输出时序、CPU复位信号、时钟是否稳定。我见过很多新手工程师一上来就怀疑固件结果折腾半天发现是复位电路的一个电容焊错了。2.2 SBL与XBL内存初始化与分区表读取接下来就到了整个启动流程中最容易出问题的环节。在比较新的高通平台比如SM8150之后的芯片上这个环节被拆成了XBL_Loader和XBL_Core两部分。XBL_Loader负责做DDR初始化、DDR训练、UFS/eMMC控制器初始化然后从存储设备读取XBL_Core、TZ、hyp、devcfg等镜像逐段加载到DDR并验证签名。DDR初始化是个技术活。DDR颗粒的型号、容量、位宽、频率、时序参数不同训练结果就完全不同。高通为此引入了CDTCustomer Data Table机制板厂可以把内存参数放到一个独立分区里启动时XBL_Loader读取CDT去配置DDR控制器。这就解释了为什么换了一颗DDR颗粒之后经常开不了机——不是硬件坏了而是CDT里的参数和你新用的颗粒对不上。分区表在这个阶段也会被读取。高通平台的GPT分区表定义在专门的gpt_main分区里包含了boot、system、vendor、dtbo等所有分区的位置和大小。XBL_Loader会根据分区表找到XBL镜像所在的位置。如果分区表被搞乱比如用错了刷机脚本导致GPT损坏最常见的现象就是设备卡在EDL模式或者反复重启。2.3 TZ、hypervisor与安全启动链高通平台和很多消费级芯片最大的区别在于它从启动早期就引入了TrustZone安全世界。TZTrustZone固件加载后芯片就有了安全世界和普通世界两个执行环境。Linux内核跑在普通世界密钥管理、指纹支付、DRM这些敏感操作通过SMC指令陷入安全世界执行。为了支撑多系统场景比如车机平台上既要跑QNX又要跑Android还需要hypervisor先行启动。高通8155这样的车规平台启动链路上PBL之后就会加载hypervisor然后由hypervisor创建虚拟机QNX作为宿主OS率先运行Android则以虚拟机客户OS的方式启动。这也是为什么车机平台上调试启动流程比手机更复杂——你不仅要看XBL的log还要看hypervisor和QNX的启动log。安全启动链是理解整个流程的钥匙。每一级固件在加载下一级之前都会用存储在eFuse或证书链里的公钥校验下一级镜像的签名。一旦校验失败芯片会进入紧急下载模式EDL等待工程师通过USB重新烧录。这意味着你在开发时用的所有镜像必须和你设备的熔丝状态匹配。这就是为什么有人拿了一台手机的解锁bl文件刷了第三方boot就再也开不了机的根本原因。2.4 ABL与kernel的最终交接在Android平台上安全固件加载完毕后控制权交给了ABL。ABL是运行在UEFI环境下的一个小型应用程序它的职责包括初始化显示让你能看到开机logo、读取boot分区里的内核镜像和DTB、设置kernel命令行参数然后通过UEFI的ExitBootServices跳转到Linux内核。ABL阶段经常出现的坑是display相关的问题。UEFI环境下的显示驱动和高通GPU驱动是两套独立的实现如果DPU初始化有问题可能到了内核阶段显示又正常了但开机logo就是不出来。这种问题排查起来很烦躁因为它不影响系统功能只影响用户体验。kernel拿到控制权后先是解压自身、解析DTB然后初始化中断控制器、定时器、串口等基础设备最后挂载根文件系统执行/sbin/init。对于Android来说init进程会解析init.rc启动zygote、surfaceflinger、system_server等关键服务。到这一步从复位到系统加载的完整链条才算真正闭环。日常开发中我们常说的CAF kernel实际上就是指高通基于上游Linux内核维护的、已经适配好自家硬件驱动的内核基线绝大多数Android设备的内核都是从CAF拉分支改出来的。3. 实操拆解从复位到系统加载的复现过程3.1 实验准备硬件、串口与烧录环境纸上谈兵没有意义下面我按自己调板子时的标准流程走一遍如何复现并观察整个启动过程。你需要准备的东西如下一块高通平台的开发板或手机主板确保PMIC供电正常。USB转串口模块连接主板的UART调试口。高通平台的调试串口一般是固定的几个引脚具体位置查硬件原理图。一条能进EDL模式的USB线通常是短接某个测试点或者有专门的key组合。PC端安装QPST或QDL工具用于烧录和抓取log另外准备一个串口工具比如MobaXterm或者minicom。硬件连接完成后给板上电串口工具里应该能看到类似这样的输出B - 165 - PBL, Start B - 344 - PBL, End S - Boot Configure S - Boot Media, UFS S - DDR - Init S - DDR - Training S - DDR - Verify S - Security - Verify S - UFS - Init S - UFS - Read GPT S - UFS - Load XBL S - Boot - Successful这段log基本上就对应了我前面讲的PBL结束、XBL加载器开始工作、DDR初始化、UFS初始化、读取分区表、加载XBL的完整过程。实际平台上tag可能略有差异但结构是相似的。看到Boot - Successful之后紧接着就是XBL_Core和ABL的输出最后kernel的log也会从同一个串口输出。3.2 抓取并读懂一条典型的启动log读启动log最重要的是定位时间线。高通平台的log每一行都有一个字符前缀比如B表示Boot ROM阶段S表示SBL/XBL阶段D表示DDR相关。后面跟着的数字是相对时间戳单位通常是微秒。我之前调一块板子的时候发现PBL到XBL之间有个长达数秒的停顿一开始以为是固件卡死了后来仔细看log发现是UFS设备枚举用了异常长的时间最后确认是UFS线路上的一颗上拉电阻虚焊导致。如果你要观察kernel阶段的启动过程建议打开Linux内核的printk时间戳同时把串口console配置到内核命令行里。这样kernel起来之后你就能看到每个驱动初始化的耗时比如[ 1.234567] msm_dpu: probed successfully [ 1.567890] ufshcd: ufshcd_probe: UFS device ready这类log对定位驱动加载慢、设备探测失败非常有用。要注意的是高通平台的串口log在UEFI阶段和内核阶段是走同一路物理串口的所以只要串口接对了全程的log都能抓到不需要切换线缆。3.3 复位电路设计异步复位同步释放是怎么来的启动的源头是复位而复位电路设计里最经典的问题就是异步复位同步释放。先解释一下概念复位信号通常由PMIC或者外部看门狗产生它是异步于系统时钟的。如果复位信号在时钟上升沿附近刚好释放有可能让寄存器进入亚稳态导致整个系统行为不可预测。解决方案是在复位释放路径上加两级同步触发器复位信号有效时可以异步拉低立刻生效但在释放时必须让信号先经过两级触发器打拍再进入系统时钟域。这种做法兼顾了异步复位的即时性和同步释放的安全性。原理和FPGA设计里的复位同步器一模一样我之前在FPGA上用Verilog写过类似的电路搬到高通平台做硬件检查时逻辑完全通用。另外还有一个容易被忽略的指标——复位电流。板子刚上电时去耦电容充电、DDR初始化、UFS供电瞬间电流可能达到安培级别。如果PMIC的电流限制配置不当或者电源走线太细导致压降过大就可能触发PMIC的欠压保护表现为上电后电流冲到某个值就掉下来然后反复重启。遇到这种情况用示波器抓PMIC各路的电压跌落是最直观的排查手段。4. 踩坑记录启动故障的排查方法与工具4.1 电流与PMIC异常开机第一步就翻车启动故障排查我习惯按电流-时钟-复位-log的顺序来。先看电流表不同的电流区间对应不同的问题。如果电流完全为零说明PMIC都没起来查主电源输入和PMIC的使能引脚。如果电流维持在几十毫安不再上涨大概率是PBL阶段异常查晶振是否起振、BOOT_CONFIG引脚电平是否正确。如果电流能到几百毫安且串口有log说明已经跑到DDR或存储初始化阶段这时候重点看log的停在哪里。PMIC的另一个常见问题是各路电源的上电时序。高通平台对VDD_APC、VDD_MX、VDD_CX这些核心电源的顺序有严格要求顺序不对会造成芯片闩锁甚至损坏。好在PMIC本身会控制时序但如果工程师在硬件设计时绕过了PMIC、用外部LDO给某些引脚供电就容易打破时序。我调试时经常用多通道示波器同时抓几路关键电源观察它们上升沿的相对时间确认符合芯片手册的时序要求。4.2 卡DDR、卡UFS、卡安全校验三类经典log对照我把实际中最常见的三种卡死情况整理成了对照表方便你遇到类似log时快速定位卡死的log片段可能原因排查方向DDR Training Fail / DDR Verify FailDDR颗粒与CDT参数不匹配或硬件焊接问题核对DDR颗粒型号确认CDT参数用示波器抓DDR供电和时钟UFS Init Fail / Read Sector ErrorUFS器件供电异常、信号线问题或分区表损坏检查UFS供电和复位重新进EDL烧录GPT和boot镜像Image hash mismatch / Secure Boot Fail镜像签名与eFuse状态不匹配确认烧录的镜像和芯片熔丝状态一致查询是否误开了secure boot这三类问题我全都踩过。DDR训练失败最容易误导人因为板子看起来一切正常电流也到位了但log就卡在DDR训练。后来发现是开发板的DDR散热带没贴好高温下训练不稳定。UFS的问题则多半出在量产阶段产线烧录时如果断电导致GPT写入不完整整批机器都会卡EDL。安全校验失败通常发生在自己编译了boot镜像但证书链不对的场景解决方法要么用官方签名工具重新签名要么烧写匹配的熔丝配置。4.3 排查工具与对比法排查启动问题我离不开三样东西串口log、电流表、示波器。串口log告诉你程序执行到哪一步电流表告诉你硬件是否正常工作示波器告诉你信号质量到底行不行。三者配合基本能覆盖绝大多数启动故障。还有一个非常实用的方法对比法。如果手头有多块相同的主板保留一块确定能正常开机的板子作为基准出问题时把两块板子的启动log逐行对比差异出现的那一行就是你该重点检查的地方。这个方法说起来简单但真的能省掉大量瞎猜的时间。我遇到过一块板子在PBL之后完全没有输出的情况对比之后发现基准板PBL输出正常问题板没有任何输出于是直接锁定PMIC到CPU的复位信号最后查出是复位信号线上的一个滤波电容容值不对导致复位释放沿被严重拉缓。5. 平台横评高通、MTK与桌面/单片机的启动思路差异5.1 高通与MTK的启动流程对照搞Android底层的人经常要同时面对高通和MTK两家平台这两家的启动思路有相似之处但差异也很明显。MTK平台的启动链路大致是BROM - Preloader - LK - kernel。其中BROM相当于高通的PBLPreloader负责DDR初始化和PMIC配置LKLittle Kernel则类似高通的ABL负责加载Linux内核。和高通相比MTK的Preloader把PMIC初始化、内存初始化都做了而高通的PMIC初始化其实早在PBL阶段就通过PMIC内部的ROM固件完成了XBL更多聚焦在DDR和存储上。另一个明显的区别是下载模式。高通是EDL模式通过QDLoader和firehose协议传输烧录数据MTK则是通过BROM的串口/USB下载模式配合DADownload Agent文件完成烧录。如果你两个平台都调试过会发现MTK的刷机工具链更平易近人一些但高通的EDL模式在量产和售后维修上更成熟稳定。另外MTK平台上更强调Preloader的不变量管理很多机器变砖就是因为Preloader和LK版本不匹配导致的。5.2 从STM32到PC BIOS一条统一的主线把视角拉远一点你会发现从STM32到PC BIOS再到高通平台启动流程的本质是统一的。STM32启动很简单复位后从0x00000000取向量表跳到Reset_Handler初始化时钟和内存然后进main。PC则是BIOS/UEFI先做POST和硬件初始化再从磁盘加载引导程序最后引导操作系统。高通平台不过是把这个过程做了更多分层、加入安全校验和动态加载而已。理解了这个本质你学任何新平台的启动流程都会很快。每次拿到一个新板子我第一件事就是找它的Boot ROM文档搞清楚上电后第一段代码在哪里、做什么、把控制权交给谁。只要这条主线清晰了剩下的都是细节填充。反过来如果你把高通平台的启动链条彻底搞明白了再去接触车机的QNX、服务器上的ARM可信固件都会有举重若轻的感觉。最后说一个我个人的体会调试启动流程最忌讳的就是不看log瞎猜。高通的串口log已经把每个阶段的执行信息都告诉你了你只需要按照PBL、XBL、ABL、kernel这个顺序一段一段去对就能把问题范围快速缩小。保持一块已知良好的基准板养成记录每次改动的好习惯这套方法论在任何平台的bring-up阶段都适用。