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 搬运流程
- 初始化堆栈指针:设置SP寄存器,为C语言运行做准备。
- 初始化全局变量:把.data段从ROM复制到RAM,清零.bss段。
- 跳转到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 启动流程全景图
下面这张图把整个启动流程串起来了。我建议你多看几遍,理解每个环节的衔接关系。
2.5 避坑指南:我踩过的几个坑
- 复位引脚毛刺:我曾经遇到过板子偶尔启动失败,查了三天发现是复位引脚上有个100nF电容没焊好,导致复位信号有毛刺。加个施密特触发器就好了。
- 启动引脚电平冲突:有个项目把BOOT0引脚复用为按键输入,结果按键按下时电平被拉低,芯片进了系统存储器模式。后来加了个二极管隔离。
- NAND坏块导致启动失败:第一次用NAND Flash做启动介质,没处理坏块,结果第一批板子有3%启动不了。后来在Bootloader里加了坏块跳过逻辑。
我的习惯: 每次画原理图时,我都会在启动引脚旁边加个测试点。调试时用万用表量一下电平,确认芯片确实进入了预期的启动模式。这个习惯帮我省了不少排查时间。
好了,启动流程这部分就讲到这里。你理解了芯片从复位到执行用户代码的完整路径,后面讲Bootloader升级逻辑时就会轻松很多。