2、启动流程解析:芯片上电后的那些事

芯片上电后到底发生了什么?这个问题,我当年刚入行时也困惑了很久。说白了,就是一颗芯片从「死」到「活」的过程。今天咱们就把它掰开揉碎了讲清楚。

2.1 上电瞬间:芯片的第一口气

当你给板子通电,电源电压从0V慢慢爬升到额定值。这时候芯片内部其实还没准备好。为什么?因为电压不稳,逻辑电路可能输出错误信号。

芯片内部有个叫 POR(Power-On Reset,上电复位) 的硬件模块,专门处理这个阶段。它会一直监测VDD电压,直到电压稳定在某个阈值以上,才释放复位信号。这个过程通常持续几毫秒到几十毫秒。

关键点: POR释放后,CPU从复位向量(Reset Vector)开始执行第一条指令。这个地址是芯片出厂固化的,一般指向芯片内部的ROM区域。

我记得有一次调试一块新板子,死活起不来。用示波器一看,VDD纹波太大,POR反复触发。嗯,硬件设计的问题,换个滤波电容就好了。

2.2 从ROM到RAM:代码是怎么「搬家」的

芯片上电后,CPU首先执行的是ROM里的代码。但ROM有个致命缺点——读取速度慢。你想想看,如果整个系统都在ROM里跑,性能得多差?

所以,大部分芯片的做法是:先把代码从ROM复制到RAM,然后在RAM里执行。这个过程叫「代码搬运」或「重定位」。

2.2.1 搬运流程

  1. 初始化堆栈指针:设置SP寄存器,为C语言运行做准备。
  2. 初始化全局变量:把.data段从ROM复制到RAM,清零.bss段。
  3. 跳转到main函数:执行用户主程序。

下面是一个典型的启动代码片段(汇编):

; 启动代码示例(ARM Cortex-M)
Reset_Handler:
    LDR     R0, =_estack      ; 设置堆栈指针
    MSR     MSP, R0

    ; 复制.data段
    LDR     R1, =_sdata
    LDR     R2, =_edata
    LDR     R3, =_sidata
    BL      copy_data

    ; 清零.bss段
    LDR     R1, =_sbss
    LDR     R2, =_ebss
    MOVS    R0, #0
    BL      zero_bss

    ; 跳转到main
    BL      main
    B       .

小提示: 链接脚本(Linker Script)里定义了这些段的起始地址和长度。我习惯在链接脚本里加注释,不然半年后自己都看不懂。

2.2.2 为什么不能直接在ROM里跑?

对比项 ROM RAM
读取速度 慢(几十ns) 快(几ns)
可写性 只读 可读可写
掉电保持 保持 丢失
典型用途 存放Bootloader、固件 运行程序、存放变量

说白了,ROM适合存东西,RAM适合跑东西。代码搬运就是把这个「存」和「跑」分开。

2.3 启动模式选择:芯片怎么知道从哪启动?

芯片上电后,它怎么知道该从串口读数据,还是从SD卡加载程序?答案就在启动模式选择引脚(Boot Mode Pins)上。

大部分芯片会采样几个GPIO引脚的电平状态,然后决定启动方式。以STM32为例:

BOOT0 BOOT1 启动模式 说明
0 X 主Flash启动 从内部Flash执行用户程序
1 0 系统存储器启动 从ROM中的Bootloader启动
1 1 SRAM启动 从内部SRAM启动(调试用)

注意: 有些芯片的启动引脚是在复位时采样的,之后引脚可以复用为普通GPIO。我曾经踩过这个坑——复位后把BOOT引脚当普通IO用了,结果下次复位时电平不对,芯片进错了启动模式。

2.3.1 三种常见启动模式详解

串口启动(UART Bootloader)

芯片通过串口接收固件数据,写入内部Flash。适合量产烧录和现场升级。我见过很多产品出厂时先用串口烧录Bootloader,再通过Bootloader烧录应用程序。

SD卡启动

从SD卡读取固件文件(通常是.bin或.hex),加载到RAM或Flash。适合大容量固件升级。我在做工业相机项目时就用过——把固件拷进SD卡,插上板子,上电自动升级。

NAND Flash启动

从NAND Flash读取固件。NAND有坏块问题,所以Bootloader里必须包含ECC校验和坏块管理逻辑。这个我后面会专门讲。

2.4 启动流程全景图

下面这张图把整个启动流程串起来了。我建议你多看几遍,理解每个环节的衔接关系。

芯片上电启动流程全景图 1. 上电 / POR复位 2. 采样Boot Mode引脚 3. 根据引脚选择启动源 串口Bootloader SD卡启动 NAND Flash启动 4. 代码搬运 ROM → RAM 💡 说明 复位向量地址由芯片 厂商固化在ROM中。 用户无法修改。

2.5 避坑指南:我踩过的几个坑

  • 复位引脚毛刺:我曾经遇到过板子偶尔启动失败,查了三天发现是复位引脚上有个100nF电容没焊好,导致复位信号有毛刺。加个施密特触发器就好了。
  • 启动引脚电平冲突:有个项目把BOOT0引脚复用为按键输入,结果按键按下时电平被拉低,芯片进了系统存储器模式。后来加了个二极管隔离。
  • NAND坏块导致启动失败:第一次用NAND Flash做启动介质,没处理坏块,结果第一批板子有3%启动不了。后来在Bootloader里加了坏块跳过逻辑。

我的习惯: 每次画原理图时,我都会在启动引脚旁边加个测试点。调试时用万用表量一下电平,确认芯片确实进入了预期的启动模式。这个习惯帮我省了不少排查时间。

好了,启动流程这部分就讲到这里。你理解了芯片从复位到执行用户代码的完整路径,后面讲Bootloader升级逻辑时就会轻松很多。