第1章:MTK启动流程解析——从BootROM到Preloader再到LK

大家好,我是老张。做MTK平台开发这些年,我见过不少新手一上来就急着写代码,结果连芯片怎么跑起来的都没搞明白。今天咱们就来聊聊MTK的启动链路,这东西说白了就是芯片的「人生三部曲」。

你想想看,一颗MTK芯片上电后,它怎么知道自己该干什么?谁告诉它从哪里加载代码?嗯,这就是BootROM、Preloader和LK这三个阶段要解决的问题。

1.1 BootROM:芯片的「出厂记忆」

BootROM是固化在芯片内部的一段只读存储器代码。芯片一上电,CPU的第一条指令就从这里开始执行。我刚开始接触MTK时,总觉得BootROM很神秘,后来发现它其实就干三件事:

  • 初始化最基本的硬件:比如时钟、SRAM、看门狗
  • 检测启动介质:看看是从NAND、eMMC还是UFS启动
  • 加载Preloader:把下一阶段的代码从存储介质搬到SRAM里

这里有个关键点——BootROM的大小是固定的,一般只有几十KB。为什么?因为它是掩膜在芯片里的,出厂后就改不了了。我在项目中遇到过一个问题:某款芯片的BootROM里有个小bug,结果整个批次都得重新流片,那叫一个心疼啊。

核心要点:BootROM是芯片的「第一口奶」,它决定了后续所有代码的加载方式。一旦BootROM有缺陷,基本只能换芯片。

1.2 Preloader:承上启下的「二传手」

Preloader是MTK平台特有的一个阶段。它由BootROM加载到SRAM中执行,大小通常在100KB左右。说白了,Preloader就是个「瘦身版」的引导程序。

它的主要任务包括:

  1. 初始化DRAM:这是最核心的工作。没有DRAM,后面的LK和内核都没法跑
  2. 校验镜像签名:检查LK镜像是否被篡改过
  3. 加载LK到DRAM:把LK从存储介质搬到内存里
  4. 设置启动参数:告诉LK一些硬件信息,比如内存大小、时钟频率

我个人习惯在Preloader里加一些调试打印,方便定位启动问题。比如这样:

// Preloader中的调试信息示例
void preloader_main(void) {
    printf("[PL] BootROM跳转成功\n");
    printf("[PL] 检测到DRAM大小: %d MB\n", get_dram_size());
    
    // 初始化DRAM控制器
    dram_init();
    
    printf("[PL] DRAM初始化完成\n");
    
    // 加载LK镜像
    load_lk_to_dram();
    
    printf("[PL] 准备跳转到LK,地址: 0x%08x\n", LK_BASE_ADDR);
    
    // 跳转
    jump_to_lk();
}

经验之谈:我曾经在Preloader里忘记关看门狗,结果每次加载到一半就复位了。排查了整整两天才发现是这个问题。所以,Preloader里第一件事就是关看门狗,切记!

1.3 LK(Little Kernel):真正的「系统管家」

LK是MTK平台使用的轻量级内核,它负责完成从裸机到操作系统的过渡。你想想看,Preloader只是把硬件初始化到能用的程度,而LK要做的是让硬件「好用」。

LK的主要工作:

功能模块 具体职责 我遇到的坑
设备树解析 读取设备树配置,初始化外设 设备树里GPIO复用配置错了,导致屏幕点不亮
显示初始化 点亮屏幕,显示开机logo 时序参数不对,屏幕一直闪
按键检测 检测音量键、电源键状态 按键消抖没做好,误触发了recovery模式
启动内核 加载并跳转到Linux内核 内核地址没对齐,直接卡死

LK的代码量一般在几百KB级别,比Preloader大得多。它运行在DRAM里,所以可以做一些复杂的事情。比如显示开机动画、检测按键组合进入刷机模式等等。

注意事项:LK阶段如果出了问题,手机就会卡在开机logo那里。我建议你在LK里加个「救命按键」——比如按住音量下键就进入fastboot模式,这样即使系统坏了也能救回来。

1.4 三个阶段的关系

这三个阶段的关系,说白了就是「接力赛」:

  • BootROM:起跑,把Preloader拉起来
  • Preloader:第一棒,初始化内存,把LK拉起来
  • LK:第二棒,初始化外设,把内核拉起来

每个阶段都依赖前一个阶段的工作成果。BootROM跑在SRAM里,Preloader跑在SRAM里但会初始化DRAM,LK跑在DRAM里。这个内存使用策略很有意思——先用小内存做简单的事,再用大内存做复杂的事。

我记得有一次调试一个启动失败的问题,发现是Preloader里DRAM时序配置错了,导致LK加载到一半就崩溃。这种问题最难查,因为错误发生在Preloader阶段,但症状却出现在LK阶段。所以,我建议你在每个阶段都加一些状态标记,方便定位问题。

1.5 本章小结

嗯,到这里你应该对MTK的启动流程有个整体认识了。BootROM是硬编码的,Preloader是轻量级的,LK是功能完整的。这三个阶段环环相扣,任何一个环节出问题,手机都开不了机。

下一章我们会深入Preloader的代码细节,看看它到底是怎么初始化DRAM的。到时候我会分享一些我在实际项目中的调试技巧,保证让你少走弯路。

一句话总结:MTK启动就是BootROM叫醒Preloader,Preloader叫醒LK,LK叫醒内核。每一步都踩在前一步的肩膀上。