🛠 Basculer les cœurs de Arm Cortex-M33 à Hazard3 RISC-V avec ARCHSEL
Objectives
Unique feature at this price point: the RP2350 contains two pairs of cores — two Arm Cortex-M33 (Armv8-M, TrustZone-M, DSP, single-precision FPU + double-precision coprocessor) OR two Hazard3 RISC-V (RV32IMAC) — but only one pair runs at a time. The selection is made via the ARCHSEL register, followed by a core reset: this allows switching architectures without re-powering the board (RP2350 datasheet, §1.1 and §3). This tutorial covers compiling the same "hello" program for RISC-V, understanding the role of the boot ROM, and measuring what each architecture offers.
Hardware
- 1 × generic RP2350 board + USB data cable
- pico-sdk 2.x with the riscv32 toolchain from pico-sdk-tools (see the "RISC-V quick start" section in the pico-sdk README)
- The
clignotproject from the previous tutorial (orhello_worldfrom pico-examples)
Full commands
# 1) Toolchain RISC-V dans le PATH
export PATH=$PWD/pico-sdk-tools/bin:$PATH
riscv32-unknown-elf-gcc --version # doit répondre
# 2) Reconfigurer le projet en plateforme RISC-V
cd clignot/build
cmake -DPICO_PLATFORM=rp2350-riscv -DPICO_BOARD=pico2 ..
make -j
# 3) Flash (BOOTSEL ou picotool) puis lire la console
picotool load -x clignot.uf2 # ou drag-and-drop de l'UF2
On the register side, the hot switch is roughly written as:
// archsel.c — demander Hazard3 au prochain reset de cœur
// 1) écrire ARCHSEL=1 (registre de syscfg/PPB selon le datasheet §3)
// 2) déclencher le reset des cœurs : le boot ROM relit ARCHSEL
// et libère la paire RISC-V au lieu de la paire Arm.
//
// à utiliser selon ta version — cherche « ARCHSEL » dans pico-bootrom.
Expected verification
The RISC-V binary blinks and behaves identically: the SDK abstracts the architecture (PIO, GPIO, and USB are the same peripherals, and the 52 interrupt inputs are routed to both architectures). Run a micro-benchmark (dependent integer loop) on both sides: the M33 retains the advantage on standard C code (16/32-bit decoder, FPU), while the Hazard3 RV32IMAC holds its own on code footprint and multiplication (M extension). Switching Arm→RISC-V→Arm happens hot: same power supply, same XIP flash.
Common errors
- Compiling with the ARM toolchain and
PICO_PLATFORM=rp2350-riscv: CMake fails on the compiler — the platform requires the riscv32 toolchain from pico-sdk-tools. - Believing there are 4 cores: it is 2 × 2 cores, one pair at a time — ARCHSEL selects the architecture for the pair, not core by core.
- Forgetting the core reset after writing ARCHSEL: without a reset, the boot ROM does not re-read the register and nothing switches.
- Secure boot and RISC-V are mutually exclusive: signature verification lives on the Cortex-M33 boot path; enabling secure boot forces Arm cores and disables RISC-V (datasheet §10) — decide before signing your images.
- Relying on the FPU on the RISC-V side: Hazard3 is RV32IMAC, without the F extension — soft-float penalizes floating-point benchmarks, keep floating-point calculations on the M33.
- 150 MHz on both sides: changing architecture does not change the clock; do not compare RISC-V@150 MHz to an RP2040 overclocked to 200 MHz without normalizing.
- Pico 2 W in RISC-V: the radio companion is controlled from any architecture, but the SDK's network examples are written for Arm — plan to port them.
- Debugging in RISC-V: PICOBOOT works, but you need an OpenOCD compatible with Hazard3 — check your tool versions before investing time.
Other tutorials for this board
- Flasher MicroPython sur une carte RP2350 générique et faire clignoter la première LED
- Console série sur RP2350 : USB CDC natif et UART0 de secours
- Lire l'ADC 12 bits et le capteur de température interne du RP2350
- Exploiter les 3 blocs PIO et 12 machines d'état du RP2350 (avec IRQ dédiées)
- Pico SDK 2.x sur une carte RP2350 générique : CMake, board header et PICO_BOARD
- Secure boot et TrustZone-M sur RP2350 : signer son firmware sans se faire avoir
Code examples for this board
clignotante.pyPythonbouton-interruption.pyPythonpwm-servo.pyPythonlecture-adc.pyPythonneopixel.pyPythonoled-i2c.pyPython