嵌入式入门必看:所有 MCU 上电,都不先运行 main 函数
BOOT 启动顺序
芯片的 “启动顺序”,就像我们给电脑开机后,从 “黑屏断电状态” 到 “进入系统能运行软件” 的全过程 ——RP2040 上电(接通电源)或复位后,不会直接运行我们写的程序,而是会先执行芯片自带的 “引导流程”,这个流程分为硬件层面的准备工作和软件层面的引导程序执行两步。而 bootrom(引导 ROM) 是内置在芯片 16kB ROM 中的核心引导代码(之前我们讲过 ROM 是芯片出厂固化的存储,bootrom 就是其中的 “启动工具包”),是整个启动流程的核心执行者。
这里启动可分为以下两个环节:
- 硬件控制 hardware controlled:在 bootrom 引导程序执行前芯片进行的工作,bootrom 引导程序是内置在芯片中的软件,无需软件参与,属于芯片硬件的自我初始化;
- 处理器控制 processor controlled:执行 bootrom 引导程序,属于软件引导程序的执行。
![image.png]()
1.硬件控制的引导顺序
- 芯片通电,运行 RUN 引脚置位:RUN 引脚是芯片的 “电源启动开关”,“置位” 就是把这个开关拨到 “开启” 状态,告诉芯片 “电源已经接上,可以开始启动了”;
- 芯片上电压调压器等待数字芯片电源(DVDD)稳定:
- 电压调压器是给芯片内部 “数字电路” 供电的 “稳压器”(类似手机充电器的稳压功能);DVDD 是数字电路的专用电源;
- 这一步是等 DVDD 的电压稳定在安全值(比如 1.8V),避免电压忽高忽低烧坏芯片内部电路,相当于电脑开机时电源要等输出电压稳定再给主板供电。
- 通电状态机已启动,通电状态机是芯片里负责按顺序完成硬件准备的自动电路,它会依次完成以下工作:
- ROSC(环形振荡器)已启动,为时钟发生器提供一个时钟源,clk_sys 和 clk_ref 现在以相对较低的频率运行(通常为 6.5MHz):
- ROSC 是芯片的 “初始时钟源”(相当于闹钟的 “发条”),启动后会产生基础的 “时钟信号”(芯片工作的 “心跳节奏”);
- clk_sys 是芯片的 “系统主时钟”,clk_ref 是 “参考时钟”,开始用低频(6.5MHz)运行是为了让硬件启动更安全、稳定,后续会根据需求提速。
- 复位控制器、XIP 就地执行硬件、存储器、总线结构和处理器子系统均退出复位:
- 这些硬件模块在断电时处于 “复位状态”(相当于 “休眠锁定”);
- “退出复位” 就是唤醒并解锁这些模块,让它们进入 “可以工作的状态”, 比如存储器准备好存数据、总线准备好传数据、处理器核心准备好执行程序。
- 处理器核心 0 和核心 1 开始执行引导程序:所有硬件准备完成后,两个处理器核心被唤醒,开始执行芯片内置的 bootrom 引导程序,硬件控制的引导流程到此结束。
- ROSC(环形振荡器)已启动,为时钟发生器提供一个时钟源,clk_sys 和 clk_ref 现在以相对较低的频率运行(通常为 6.5MHz):
2.处理器控制的引导顺序
处理器控制的引导顺序,是bootrom 引导程序开始执行后的 “任务分配 + 启动方式选择流程”,此时硬件已经准备好,bootrom(芯片里的 “启动管理员”)会先给两个核心分工,再判断 “从哪里加载用户程序”(要么从外部 Flash 读程序,要么进入 USB 模式等用户烧录程序),整个流程是通过 “判断各种硬件信号 + 执行预设逻辑” 自动完成的。

图 2.21 RP2040 处理器控制引导顺序流程图
第一部分是双核的初始分工(流程图左侧),两个核心(Core0、Core1)都进入 bootrom 后,先完成 “职责划分”:
- “Which core am I?”(我是哪个核心?):两个核心同时运行,但通过之前讲的 “CPUID 寄存器” 区分身份:
- 如果是 Core1:进入 “Sleep until given entry point”(休眠,等 Core0 给它分配任务);
- 如果是 Core0:继续执行后续的启动逻辑(Core0 是 “主启动核心”)。
- “PoR rescue flag set?”(上电复位救援标志是否开启?):这是芯片的 “故障救援开关”:如果这个标志开了,说明之前启动失败过,Core0 会 “Clear flag and halt”(清除标志并暂停),等待人工排查问题。
- “Watchdog boot-to-SRAM set?”(看门狗是否要求从 SRAM 启动?):看门狗是芯片的 “故障重启工具”:如果看门狗要求从 SRAM 启动,Core0 会 “Set SP and jump to entry point”(设置栈指针 SP,跳转到 SRAM 里的程序入口)这是 “紧急启动模式”,通常用于调试。
- “100us delay (pullup on flash CSn)”(延迟 100 微秒,给 Flash 的 CSn 引脚加上拉电阻): “CSn” 是外部 Flash 的 “片选引脚”(相当于 Flash 的 “开关”),上拉电阻是让这个引脚先处于 “高电平”(默认不选中 Flash),给 Flash 留足启动时间。
- “Read flash CSn”(读取 Flash 的 CSn 引脚电平):通过 CSn 引脚的电平,判断 “有没有外部 Flash”:
- 如果是 High(高电平):说明 Flash 存在,走 “Flash 启动” 的流程(跳转到流程图右侧);
- 如果是Low(低电平):说明没有 Flash,走 “USB 启动” 的流程(后续会进入 USB 模式,等用户通过 USB 烧录程序)。
第二部分是启动方式选择(流程图右侧),Core0 确定 “Flash 存在” 后,开始尝试从 Flash 启动,否则进入 USB 模式:
- 分支 1:尝试 Flash 启动
- “Configure SSI and connect to pads”(配置 SSI 模块,连接到引脚):SSI 是控制 QSPI 接口的模块(之前讲过),这一步是让芯片和外部 Flash 建立通信连接。
- “Load 256 bytes from flash”(从 Flash 读取 256 字节数据):先读 Flash 里的 “启动头数据”,用来验证 Flash 里的程序是否有效。
- “Checksum pass?”(校验和是否通过?):“校验和” 是 Flash 程序的 “身份证”(相当于给程序算个 “数字指纹”):
- 如果通过(Y):说明 Flash 里的程序没问题,进入 “Enter flash second stage”(执行 Flash 里的二级启动程序,最终加载用户程序);
- 如果不通过(N):继续判断 “启动时间是否超过 0.5 秒”。
- “Longer than 0.5s since boot?”(启动时间超过 0.5 秒了吗?):
- 如果没超过:调整 Flash 的通信参数(CPOL/CPHA 是 SPI 的 “时钟极性 / 相位”,相当于 “调整 Flash 的通信协议”),再延迟 100 微秒,重新尝试读 Flash;
- 如果超过:说明 Flash 启动失败,切换到 “USB 启动” 流程。
- 分支 2:USB 启动(Flash 启动失败后)
- “Start crystal oscillator”(启动晶振):晶振是更精准的时钟源,USB 通信需要稳定的时钟,所以先启动晶振。
- “Crystal present?”(晶振存在吗?):
- 如果晶振不存在:Core0 “Halts”(暂停),启动失败;
- 如果晶振存在:继续下一步。
- “Start PLLs. Sys, USB clocked at 48 MHz”(启动锁相环 PLL,把系统时钟、USB 时钟调到 48MHz):PLL 是 “时钟加速器”,把晶振的低频时钟升到 USB 需要的 48MHz(USB 通信的标准时钟)。
- “Enter USB device mode bootcode”(进入 USB 设备模式的引导程序):此时芯片会变成 “USB 设备”(比如电脑识别的 “U 盘”),用户可以通过 USB 把程序烧录到 Flash 或 SRAM 里。

芯片的 “启动顺序”,就像我们给电脑开机后,从 “黑屏断电状态” 到 “进入系统能运行软件” 的全过程 ——RP2040 上电(接通电源)或复位后,不会直接运行我们写的程序,而是会先执行芯片自带的 “引导流程”,这个流程分为硬件层面的准备工作和软件层面的引导程序执行两步。

浙公网安备 33010602011771号