Build Cortex-M0+ guest programs from assembly sources to exercise the
minimal Pico boot path, UART0 output, and the Cortex-M0+ MPU. Keep the
vector table at the XIP base so these tests match the initial synthetic
boot stub without depending on boot2 or the later flash controller model.

Signed-off-by: gilles grimaud <[email protected]>
---
 MAINTAINERS                            |  1 +
 tests/tcg/arm/system/meson.build       | 14 +++++++
 tests/tcg/arm/system/rp2040-boot.S     | 30 +++++++++++++++
 tests/tcg/arm/system/rp2040-minimal.ld | 40 +++++++++++++++++++
 tests/tcg/arm/system/rp2040-uart.S     | 53 ++++++++++++++++++++++++++
 tests/tcg/arm/system/rp2040-uart.ref   |  1 +
 6 files changed, 139 insertions(+)
 create mode 100644 tests/tcg/arm/system/rp2040-boot.S
 create mode 100644 tests/tcg/arm/system/rp2040-minimal.ld
 create mode 100644 tests/tcg/arm/system/rp2040-uart.S
 create mode 100644 tests/tcg/arm/system/rp2040-uart.ref

diff --git a/MAINTAINERS b/MAINTAINERS
index caee8aa0cc..a03fb0575c 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1033,6 +1033,7 @@ S: Maintained
 F: hw/*/rp2040*
 F: include/hw/*/rp2040*
 F: hw/arm/raspi_pico.c
+F: tests/tcg/arm/system/rp2040*
 
 Real View
 M: Peter Maydell <[email protected]>
diff --git a/tests/tcg/arm/system/meson.build b/tests/tcg/arm/system/meson.build
index e92a83a8d5..42e7614a11 100644
--- a/tests/tcg/arm/system/meson.build
+++ b/tests/tcg/arm/system/meson.build
@@ -15,6 +15,11 @@ qemu_base_args = ['-display', 'none',
                   '-semihosting-config', 'enable=on',
                   '-kernel']
 qemu_def_args = ['-M', 'virt', '-cpu', 'max', qemu_base_args]
+rp2040_cflags = ['-mcpu=cortex-m0plus', '-mthumb', '-mfloat-abi=soft',
+                 '-nostdlib', '-Wl,--build-id=none',
+                 '-T', files('rp2040-minimal.ld')]
+rp2040_qemu_args = ['-M', 'raspi-pico', '-monitor', 'none',
+                    qemu_base_args]
 
 # Multi arch tests
 multi_src = []
@@ -51,6 +56,15 @@ tests += {
                '-T', files('test-armv6m-undef.ld')],
     'qemu_args': ['-M', 'microbit', qemu_base_args],
   },
+  'rp2040-boot.S': {
+    'cflags': rp2040_cflags,
+    'qemu_args': rp2040_qemu_args,
+  },
+  'rp2040-uart.S': {
+    'cflags': rp2040_cflags,
+    'qemu_args': ['-serial', 'stdio', rp2040_qemu_args],
+    'expected_output': 'rp2040-uart.ref',
+  },
   'semiconsole.c': {
     'cflags': cflags,
     'qemu_args': ['-serial', 'none', '-chardev', 'stdio,mux=on,id=stdio0',
diff --git a/tests/tcg/arm/system/rp2040-boot.S 
b/tests/tcg/arm/system/rp2040-boot.S
new file mode 100644
index 0000000000..0537a54d44
--- /dev/null
+++ b/tests/tcg/arm/system/rp2040-boot.S
@@ -0,0 +1,30 @@
+/*
+ * Raspberry Pi Pico boot smoke test.
+ *
+ * Copyright 2026 Gilles Grimaud
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+.syntax unified
+.cpu cortex-m0plus
+.thumb
+
+#define SRAM_END 0x20042000
+#define SYS_EXIT 0x18
+#define ADP_STOPPED_APPLICATION_EXIT 0x20026
+
+.section .vectors, "a", %progbits
+vector_table:
+    .word SRAM_END
+    .word reset_handler + 1
+
+.section .text, "ax", %progbits
+.thumb_func
+.global reset_handler
+reset_handler:
+    movs r0, SYS_EXIT
+    ldr r1, =ADP_STOPPED_APPLICATION_EXIT
+    bkpt 0xab
+
+1:
+    b 1b
diff --git a/tests/tcg/arm/system/rp2040-minimal.ld 
b/tests/tcg/arm/system/rp2040-minimal.ld
new file mode 100644
index 0000000000..ebfbac8cf2
--- /dev/null
+++ b/tests/tcg/arm/system/rp2040-minimal.ld
@@ -0,0 +1,40 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+ENTRY(reset_handler)
+
+MEMORY
+{
+    FLASH (rx) : ORIGIN = 0x10000000, LENGTH = 2M
+    SRAM (rwx) : ORIGIN = 0x20000000, LENGTH = 264K
+}
+
+SECTIONS
+{
+    .vectors ORIGIN(FLASH) :
+    {
+        KEEP(*(.vectors))
+    } > FLASH
+
+    .text :
+    {
+        *(.text*)
+        *(.rodata*)
+    } > FLASH
+
+    .data :
+    {
+        *(.data*)
+    } > SRAM AT > FLASH
+
+    .bss (NOLOAD) :
+    {
+        *(.bss*)
+        *(COMMON)
+    } > SRAM
+
+    /DISCARD/ :
+    {
+        *(.ARM.attributes)
+        *(.comment)
+    }
+}
diff --git a/tests/tcg/arm/system/rp2040-uart.S 
b/tests/tcg/arm/system/rp2040-uart.S
new file mode 100644
index 0000000000..bdb58cc7f2
--- /dev/null
+++ b/tests/tcg/arm/system/rp2040-uart.S
@@ -0,0 +1,53 @@
+/*
+ * Raspberry Pi Pico UART boot smoke test.
+ *
+ * Copyright 2026 Gilles Grimaud
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+.syntax unified
+.cpu cortex-m0plus
+.thumb
+
+#define SRAM_END 0x20042000
+#define UART0_DR 0x40034000
+#define SYS_EXIT 0x18
+#define ADP_STOPPED_APPLICATION_EXIT 0x20026
+
+.section .vectors, "a", %progbits
+vector_table:
+    .word SRAM_END
+    .word reset_handler + 1
+    .word default_handler + 1
+    .word default_handler + 1
+
+.section .text, "ax", %progbits
+.thumb_func
+.global reset_handler
+reset_handler:
+    ldr r0, =UART0_DR
+    ldr r1, =message
+
+1:
+    ldrb r2, [r1]
+    cmp r2, 0
+    beq 2f
+    str r2, [r0]
+    adds r1, 1
+    b 1b
+
+2:
+    movs r0, SYS_EXIT
+    ldr r1, =ADP_STOPPED_APPLICATION_EXIT
+    bkpt 0xab
+
+3:
+    b 3b
+
+.thumb_func
+default_handler:
+    b default_handler
+
+.section .rodata, "a", %progbits
+message:
+    .asciz "PICO TCG UART OK\n"
diff --git a/tests/tcg/arm/system/rp2040-uart.ref 
b/tests/tcg/arm/system/rp2040-uart.ref
new file mode 100644
index 0000000000..1ef16e8299
--- /dev/null
+++ b/tests/tcg/arm/system/rp2040-uart.ref
@@ -0,0 +1 @@
+PICO TCG UART OK
-- 
2.55.0


Reply via email to