[PICO][Adv]启动引导过程

Raspberry Pi Pico 2 启动引导过程

Raspberry Pi Pico 2 是一款功能强大的微控制器开发板,广泛应用于各种电子项目和原型开发中。要充分利用 Pico 2 的功能,了解其启动引导过程(Boot Process)是非常重要的。本文将详细介绍 Pico 2 的启动引导过程,帮助你理解从硬件上电到程序执行的完整流程,并展示如何在 Arduino 风格和 C/C++ 风格编程中与引导程序交互。


什么是 Pico 2 启动引导过程?

Pico 2 的启动引导过程是指从开发板上电或复位开始,到用户程序(即你编写的代码)开始执行之间的过程。这个过程由 RP2350 芯片内部 ROM 中的引导程序(Boot ROM) 以及外部 Flash 中的二级引导程序(Second-stage Bootloader) 共同控制。引导程序负责初始化硬件、检查启动模式,并加载用户程序。

备注:Pico 2 的引导程序是其能够通过 USB 接口直接拖放 .uf2 文件来烧录程序的关键,无需额外的编程器。


Pico 2 启动引导过程的步骤

Pico 2 的启动引导过程可以分为以下几个主要步骤:

  1. 硬件初始化:当 Pico 2 上电或复位时,RP2350 芯片会首先执行内部的硬件初始化,包括设置时钟、配置电源管理、初始化关键外设等。
  2. 执行 Boot ROM:芯片从内部 ROM 的起始地址执行固化的引导程序代码。
  3. 检查 BOOTSEL 引脚:Boot ROM 会检测 BOOTSEL 按键(连接在特定引脚上)是否被按下。
  4. 选择启动模式
    • 如果 BOOTSEL 被按下:进入 USB 大容量存储模式(UF2 下载模式),模拟为一个 U 盘,等待用户拖放 .uf2 固件文件。
    • 如果 BOOTSEL 未按下:尝试从外部 QSPI Flash 中加载程序。
  5. 加载二级引导程序:从 Flash 的起始地址读取二级引导程序(用于配置 Flash 访问时序),然后执行。
  6. 加载用户程序:二级引导程序从 Flash 中加载用户程序(通常从地址 0x10000000 开始),并跳转执行。

以下是一个简化的流程示意图:

1
2
3
4
5
6
7
8
9
10
11
12
13
上电或复位

硬件初始化 (芯片内部)

执行 Boot ROM

检查 BOOTSEL 引脚
├── 按下 → USB 大容量存储模式 (等待 UF2 文件)
└── 未按下 → 从 Flash 加载二级引导程序

加载用户程序

执行用户代码 (setup() / main())

引导程序的作用

Pico 2 的引导程序(Boot ROM + 二级引导程序)主要提供以下功能:

  • UF2 拖放下载:当 BOOTSEL 按下时,Pico 2 模拟为一个 USB 磁盘,你只需将编译好的 .uf2 文件拖入即可完成烧录,无需驱动或编程器。
  • 程序加载:正常情况下,从外部 Flash 加载上次烧录的用户程序并执行。
  • 故障安全:即使 Flash 中的程序损坏,仍可通过 BOOTSEL 模式重新烧录,不会变砖。
  • 二级引导程序灵活性:允许用户自定义 Flash 的初始化时序,支持不同型号的 Flash 芯片。

提示:Pico 2 的引导程序固化在 ROM 中,不可修改,因此更加安全可靠。与 Arduino Uno 不同,它不占用用户 Flash 空间。


实际案例:与引导程序交互

虽然用户程序通常不直接参与启动过程,但你可以通过代码主动进入引导程序模式(例如实现远程固件更新),或者检测启动原因。以下分别展示 Arduino 风格和 C/C++ 风格的示例。

1. Arduino 风格:主动进入 BOOTSEL 模式

在 Arduino-Pico 核心中,你可以调用 reset_usb_boot() 函数,使 Pico 2 复位并进入 USB 大容量存储模式,等待拖放新的 .uf2 文件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include "pico/bootrom.h"

void setup() {
Serial.begin(115200);
delay(2000);
Serial.println("Entering BOOTSEL mode in 2 seconds...");
delay(2000);

// 调用 SDK 函数进入 USB 烧录模式
reset_usb_boot(0, 0); // 参数为 0 表示不额外拉低引脚
}

void loop() {
// 不会执行到这里
}

2. C/C++ 风格:检测复位原因

使用 Pico SDK 提供的硬件寄存器或函数,可以判断本次启动是上电复位还是软件复位,从而执行不同的初始化逻辑。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include "pico/stdlib.h"
#include "hardware/rosc.h"

int main() {
stdio_init_all();
sleep_ms(100);

// 读取复位原因寄存器
uint32_t reset_cause = rosc_hw->status;

if (reset_cause & ROSC_STATUS_ENABLED_BITS) {
printf("Power-on reset detected (cold boot)\n");
} else {
printf("Software or watchdog reset detected (warm boot)\n");
}

// 正常用户代码
while (true) {
tight_loop_contents();
}
return 0;
}

3. 实际应用:实现“长按按钮进入升级模式”

以下示例演示了如何在用户程序运行时检测一个普通 GPIO 按钮的长按,然后主动进入 BOOTSEL 模式,实现类似“恢复模式”的功能。

Arduino 风格

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include "pico/bootrom.h"

const int BOOT_BUTTON = 0; // 普通 GPIO 按钮
const unsigned long LONG_PRESS_MS = 3000;

void setup() {
pinMode(BOOT_BUTTON, INPUT_PULLUP);
Serial.begin(115200);
Serial.println("Hold button for 3 seconds to enter bootloader...");
}

void loop() {
if (digitalRead(BOOT_BUTTON) == LOW) {
unsigned long start = millis();
while (digitalRead(BOOT_BUTTON) == LOW) {
if (millis() - start >= LONG_PRESS_MS) {
Serial.println("Entering BOOTSEL mode...");
delay(100);
reset_usb_boot(0, 0);
}
delay(10);
}
}
// 正常任务...
}

C/C++ 风格

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include "pico/stdlib.h"
#include "pico/bootrom.h"

#define BOOT_BUTTON 0
#define LONG_PRESS_MS 3000

int main() {
stdio_init_all();
gpio_init(BOOT_BUTTON);
gpio_set_dir(BOOT_BUTTON, GPIO_IN);
gpio_pull_up(BOOT_BUTTON);

printf("Hold button for 3 seconds to enter bootloader...\n");

while (true) {
if (gpio_get(BOOT_BUTTON) == 0) {
absolute_time_t start = get_absolute_time();
while (gpio_get(BOOT_BUTTON) == 0) {
if (absolute_time_diff_us(start, get_absolute_time()) >= LONG_PRESS_MS * 1000) {
printf("Entering BOOTSEL mode...\n");
sleep_ms(100);
reset_usb_boot(0, 0);
}
sleep_ms(10);
}
}
// 正常任务...
tight_loop_contents();
}
return 0;
}

与传统 Arduino 启动引导过程的对比

特性 Arduino Uno (ATmega328P) Raspberry Pi Pico 2 (RP2350)
引导程序位置 微控制器 Flash(占用 0.5KB~2KB 用户空间) 芯片内部 ROM(独立,不占用用户空间)
程序烧录方式 通过串口(UART)使用 STK500 协议 USB 拖放 .uf2 文件,或通过 SWD 调试接口
引导程序可修改性 可以被擦除或替换(需要编程器) 不可修改(ROM 固化),更安全
启动速度 较慢(需等待串口检测超时) 极快(直接加载 Flash 程序)
二级引导程序 有(位于 Flash 起始,可自定义)
用户主动进入引导模式 通过软件复位 + 特定握手 调用 reset_usb_boot() 即可

总结

Raspberry Pi Pico 2 的启动引导过程是理解其工作原理的关键部分。通过了解 Boot ROM、二级引导程序以及 BOOTSEL 机制的作用,你可以更好地掌握 Pico 2 的运行机制,并在需要时实现远程固件更新、安全模式等功能。

  • 启动流程:硬件初始化 → Boot ROM → 检查 BOOTSEL → 加载二级引导程序 → 加载用户程序。
  • 核心优势:USB 拖放烧录、固化引导程序安全可靠、不占用用户 Flash。
  • 编程交互:使用 reset_usb_boot() 主动进入引导模式;使用复位原因检测区分冷/热启动。

附加资源与练习

  • 练习 1:编写一个程序,在串口输入特定命令(如 "update")时触发进入 BOOTSEL 模式,实现远程升级。
  • 练习 2:研究 Pico 2 的二级引导程序机制,尝试修改链接脚本,将用户程序放在 Flash 的不同偏移地址。
  • 资源

通过本文的学习,你应该对 Pico 2 的启动引导过程有了更深入的理解。继续探索和实践,你将能够更熟练地使用 Pico 2 进行各种项目开发。


[PICO][Adv]启动引导过程
https://ka5fxt.cn/2026/03/30/PICO-Adv-启动引导过程/
发布于
2026年3月30日
许可协议