Assembler for the Raspberry Pi Pico and Pico 2

Write Arm and RISC-V, put it on the board and debug it step by step – without OpenOCD, without an SDK.

With .target pico or .target pico2 a program says which board it is for. Asmonite assembles it, checks it against the board, writes it into the RAM or the flash over a debug probe and stops at _start. Then you go through it instruction by instruction and see the registers, the stack and the memory. Asmonite drives the probe itself over USB; you need no OpenOCD, GDB or Pico SDK.

The examples are in the folders examples\pico and examples\pico2 of the ZIP. The full guide is in the source repository as docs/en/riscv-pico2.md.

Two boards, three cores

The Pico has Arm cores, the Pico 2 two kinds of cores; the boot ROM chooses which runs from the program in the flash. Asmonite writes programs for all three and debugs core 0 of each.

PicoPico 2, ArmPico 2, RISC-V
Chip, coreRP2040, Cortex-M0+RP2350, Cortex-M33RP2350, Hazard3
Directives.target pico
.arch thumb
.target pico2
.arch thumb
.target pico2
.arch riscv32
InstructionsThumb (ARMv6-M)Thumb-2 (ARMv8-M)RV32IMA, Zicsr, Zifencei, Zba, Zbb, Zbs, Zbc, Zbkb
RAM, flash264 KB, 2 MB520 KB from 0x20000000, 4 MB from 0x10000000
Start from the flashboot2 block (.boot2) + vector tablevector table + IMAGE_DEF (0x1021)IMAGE_DEF block (0x1101)
Hardware breakpoints4 in the flash, any number in the RAM84
Registers in the debuggerR0…R12, SP, LR, PC, XPSR, flags N Z C Vx0…x31, pc

The Pico (RP2040)

The Cortex-M0+ knows the instructions of the ARMv6-M, and a flash program starts with a boot2 block. File: examples\pico\blink_flash.asm.

.target pico
.arch thumb
.imagebase 0x10000000   ; flash

    .boot2                 ; 256 bytes that set up the flash chip
vectors:                   ; at 0x10000100
    dd 0x20042000          ; stack pointer
    dd _start + 1          ; start address (+1: Thumb code)
_start:
    ldr  r0, resets_clr    ; a 32-bit constant from a word behind the code
    ...

With .target pico the assembler allows the instructions of the ARMv6-M only: 16-bit Thumb, of the 32-bit ones only bl, msr, mrs and the barriers. There is no movw/movt, no cbz and no it; any other instruction is an error with its line. .boot2 puts in the boot2 block of the Pico SDK (BSD-3-Clause, in the ZIP and built into Asmonite), with its CRC-32 that the boot ROM checks. For a board with another flash chip, .boot2 file.bin takes a block of your own.

Connect and debug

  1. Connect the debug probe. The Raspberry Pi Debug Probe or a second Pico with the debugprobe firmware (CMSIS-DAP). Three wires to the debug pins: SWCLK, GND, SWDIO. The board gets its power over its own USB cable. Windows needs no driver.
  2. Choose the target. Under Debug > Debug targets choose Raspberry Pi Pico (RP2040) or Raspberry Pi Pico 2 (RP2350) and press Test the connection. It says whether the board answers and which cores run.
  3. Start. Open an example and press F7: Asmonite assembles, reads the chip id of the board, writes the program and stops at _start. F7 and F8 take a step, F9 runs, F4 runs to the cursor, F5 sets a breakpoint, Debug > Pause stops.
  4. Look and change. On the right are the registers (a double click changes a value) and the stack with notes where a value points into your program. The memory view shows bytes or, switched to Code, the instructions from an address with your labels.

If the program does not fit the board at the probe (a Pico program at a Pico 2, or the other way round), Asmonite refuses it with the name of the board and writes nothing.

RAM, flash and UF2

.imagebase 0x20000000The program goes into the RAM. Quick to try out; it is gone after a power cycle.
.imagebase 0x10000000Asmonite writes the program into the flash through the functions of the boot ROM, only the 4 KB sectors that differ, and reads them back. It is debugged there and starts by itself after power-up.
Project > Save as UF2 fileA file for the BOOTSEL drive, with the family of the chip (RP2040, Arm or RISC-V). Without a debug probe: hold BOOTSEL, plug in, drag the file onto the drive.

Switching between RISC-V and Arm. The RP2350 runs one kind of cores at a time. If you start a flash program for the other kind, Asmonite writes it into the flash with the cores that run, resets the chip, and the boot ROM starts the cores the program is for. This takes about two seconds. A RAM program cannot switch; Asmonite then says which flash program to start first.

Without OpenOCD. Asmonite speaks CMSIS-DAP over USB and through it SWD with the chip: the debug module of the RISC-V cores, the debug registers of the Arm cores, the multidrop bus of the RP2040. If you still want OpenOCD, you can choose it as a backup for the RISC-V cores (host and port of its GDB server).

What is not (yet) there

Next

Syntax

Labels, constants with equ, expressions and directives.

The syntax page →

Instruction reference

Every instruction with its bit encoding and pseudo code, for the Arm and the RISC-V cores.

Thumb / Thumb-2 →
RISC-V (RV32) →

Download

One ZIP with everything; unpack, start, done.

To the download →