Arm und RISC-V schreiben, auf das Board bringen und Schritt für Schritt debuggen – ohne OpenOCD, ohne SDK.
Mit .target pico oder .target pico2 sagt ein Programm, für welches Board es ist. Asmonite assembliert es, prüft es gegen das Board, schreibt es über eine Debug-Probe ins RAM oder in den Flash und hält bei _start. Danach gehst du Befehl für Befehl hindurch und siehst Register, Stack und Speicher. Die Probe steuert Asmonite selbst über USB an; OpenOCD, GDB oder das Pico-SDK brauchst du nicht.
Die Beispiele sind in den Ordnern examples\pico und examples\pico2 des ZIPs. Die ausführliche Anleitung steht im Quelltext-Repository unter docs/de/riscv-pico2.md.
Der Pico hat Arm-Kerne, der Pico 2 zwei Sorten von Kernen; welche läuft, entscheidet das Boot-ROM nach dem Programm im Flash. Asmonite schreibt Programme für alle drei und debuggt jeweils Kern 0.
| Pico | Pico 2, Arm | Pico 2, RISC-V | |
|---|---|---|---|
| Chip, Kern | RP2040, Cortex-M0+ | RP2350, Cortex-M33 | RP2350, Hazard3 |
| Direktiven | .target pico.arch thumb | .target pico2.arch thumb | .target pico2.arch riscv32 |
| Befehle | Thumb (ARMv6-M) | Thumb-2 (ARMv8-M) | RV32IMA, Zicsr, Zifencei, Zba, Zbb, Zbs, Zbc, Zbkb |
| RAM, Flash | 264 KB, 2 MB | 520 KB ab 0x20000000, 4 MB ab 0x10000000 | |
| Start aus dem Flash | boot2-Block (.boot2) + Vektortabelle | Vektortabelle + IMAGE_DEF (0x1021) | IMAGE_DEF-Block (0x1101) |
| Hardware-Breakpoints | 4 im Flash, im RAM beliebig viele | 8 | 4 |
| Register im Debugger | R0…R12, SP, LR, PC, XPSR, Flags N Z C V | x0…x31, pc | |
Der Cortex-M0+ kennt die Befehle des ARMv6-M, und ein Flash-Programm beginnt mit einem boot2-Block. Datei: 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 ...
Mit .target pico lässt der Assembler nur die Befehle des ARMv6-M zu: Thumb mit 16 Bit, von den 32-Bit-Befehlen nur bl, msr, mrs und die Barrieren. Es gibt kein movw/movt, kein cbz und kein it; jeder andere Befehl ist ein Fehler mit seiner Zeile. .boot2 setzt den boot2-Block des Pico-SDK ein (BSD-3-Clause, im ZIP und in Asmonite eingebaut), mit seiner CRC-32, die das Boot-ROM prüft. Für ein Board mit einem anderen Flash-Chip nimmt .boot2 datei.bin einen eigenen Block.
Die LED an GPIO 25 blinkt: Ausgang einschalten, dann in einer Schleife umschalten und warten. Dateien: examples\pico2\blink_arm_ram.asm und blink_ram.asm (gekürzt).
.target pico2 .arch thumb .imagebase 0x20000000 ; RAM _start: ... ; pads and GPIO movw r0, #(SIO_BASE & 0xffff) movt r0, #(SIO_BASE >> 16) movw r1, #(LED_MASK & 0xffff) movt r1, #(LED_MASK >> 16) blink_loop: str r1, [r0, #SIO_GPIO_OUT_XOR] movw r2, #(DELAY_COUNT & 0xffff) movt r2, #(DELAY_COUNT >> 16) delay: subs r2, r2, #1 bne delay b blink_loop
.target pico2 .arch riscv32 .imagebase 0x20000000 ; RAM _start: li sp, SRAM_END ... ; pads and GPIO li t0, SIO_BASE li t1, LED_MASK blink_loop: sw t1, SIO_GPIO_OUT_XOR(t0) li t2, DELAY_COUNT delay: addi t2, t2, -1 bnez t2, delay j blink_loop
RISC-V hat keine Flags: bnez vergleicht und verzweigt in einem Befehl, und li setzt eine 32-Bit-Konstante aus lui und addi zusammen. Arm lädt sie in zwei Hälften mit movw und movt, subs setzt die Flags und bne verzweigt danach. Die Peripherie ist auf beiden Kernen dieselbe: Register an festen Adressen, jedes mit Aliasen zum Kippen, Setzen und Löschen von Bits.
debugprobe (CMSIS-DAP). Drei Drähte an die Debug-Pins: SWCLK, GND, SWDIO. Das Board bekommt Strom über sein eigenes USB-Kabel. Windows braucht keinen Treiber._start. F7 und F8 gehen einen Schritt, F9 lässt laufen, F4 läuft bis zum Cursor, F5 setzt einen Breakpoint, Debug > Pause hält an.Passt das Programm nicht zum Board an der Probe (ein Pico-Programm am Pico 2 oder umgekehrt), lehnt Asmonite es mit dem Namen des Boards ab und schreibt nichts.
.imagebase 0x20000000 | Das Programm kommt ins RAM. Schnell zum Ausprobieren; nach dem Ausschalten ist es weg. |
.imagebase 0x10000000 | Asmonite schreibt das Programm über die Funktionen des Boot-ROM in den Flash, nur die 4-KB-Sektoren, die sich unterscheiden, und liest sie zurück. Es wird dort debuggt und startet nach dem Einschalten von selbst. |
| Project > Save as UF2 file | Eine Datei für das BOOTSEL-Laufwerk, mit der Familie des Chips (RP2040, Arm oder RISC-V). Ohne Debug-Probe: BOOTSEL gedrückt halten, einstecken, Datei auf das Laufwerk ziehen. |
Der Wechsel zwischen RISC-V und Arm. Der RP2350 lässt immer nur eine Sorte von Kernen laufen. Startest du ein Flash-Programm für die andere Sorte, schreibt Asmonite es mit den gerade laufenden Kernen in den Flash, setzt den Chip zurück, und das Boot-ROM startet die Kerne, für die das Programm ist. Das dauert etwa zwei Sekunden. Ein RAM-Programm kann nicht umschalten; Asmonite sagt dann, welches Flash-Programm zuerst zu starten ist.
Ohne OpenOCD. Asmonite spricht CMSIS-DAP über USB und darüber SWD mit dem Chip: das Debug-Modul der RISC-V-Kerne, die Debug-Register der Arm-Kerne, beim RP2040 den Multidrop-Bus. Wer OpenOCD trotzdem nutzen will, kann es für die RISC-V-Kerne als Ausweichweg wählen (Host und Port seines GDB-Servers).
c.*); der Disassembler liest sie.Jeder Befehl mit Bitkodierung und Pseudocode, für die Arm- und die RISC-V-Kerne.