🛠 Boot UF2, BOOTSEL et récupération d'une carte « briquée »
Objectives
Understand the atypical boot chain of the RP2040 — no internal flash: after reset, the bootrom (in ROM, uncopyable) loads the firmware either from the external 2 MB QSPI flash (XIP) or via USB if the BOOTSEL pin is held. You will learn how to enter BOOTSEL mode, understand the UF2 format (a "sparse" image in 256-byte blocks), and recover a board whose program crashes immediately at startup — the RP2040 cannot be bricked by software via this path.
Hardware
- 1 × Raspberry Pi Pico + micro-USB data cable
- A backup
.uf2file (e.g., the blink example from your SDK, or the MicroPython firmware) - Optional: SWD adapter (CMSIS-DAP, Pico 2 debugging another Pico) for step-by-step debugging
Complete Code
// canary.c — programme volontairement « méchant » à récupérer
// Écrase le vecteur de reset : au prochain boot, plus rien ne démarre
// (sauf BOOTSEL, qui court-circuite la flash !)
#include "pico/stdlib.h"
int main(void) {
// efface la table des vecteurs en tête de flash (zone 0x10000000)
flash_range_erase(0, 4096);
uint32_t junk[64];
for (int i = 0; i < 64; i++) junk[i] = 0xDEADBEEF;
flash_range_program(0, (const uint8_t *)junk, 256);
while (true) { } // le prochain reset partira dans le vide
}
// Rebuild avec pico_stdlib + hardware/flash, flash, laisse le programme
// tourner une fois, reset : la carte est « morte »… jusqu'au BOOTSEL.
Expected Verification
After running the canary and resetting, the board no longer responds (no REPL, no blink). Hold BOOTSEL and reconnect: the RPI-RP2 drive always reappears — the bootrom is intact. Drop a healthy .uf2 file: the board comes back to life. Note: a misaligned UF2 may be written erratically (RP2040 datasheet errata E14); if the flash appears random, retry with a UF2 generated by the SDK.
Common Errors
- Believing the board is dead: without BOOTSEL, a firmware that crashes at boot only prevents the application from running — the mass-storage mode is in ROM, not in flash.
- Holding BOOTSEL after plugging in: you must hold the button during insertion.
- Dropping a
.bininstead of a.uf2: the ROM drag-and-drop only accepts UF2 (the.binis flashed via SWD/debugprobe). - Never seeing "RPI-RP2": charge-only cable, or a finicky USB hub — try a direct port.
- Confusing "RUN" reset and recovery: after a successful flash, the board restarts on its own and the drive disappears; this is normal.
- In SWD, forgetting that writing to flash freezes XIP: both cores wait, hence the usefulness of
flash_safe_execute(SDK ≥ 1.5.1).
Other tutorials for this board
Code examples for this board
clignotante.pyPythonbouton-interruption.pyPythonpwm-servo.pyPythonlecture-adc.pyPythonneopixel.pyPythonoled-i2c.pyPython