From: gilles grimaud <[email protected]> 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/Makefile.softmmu-target | 24 ++++ tests/tcg/arm/system/rp2040-boot.S | 30 ++++ tests/tcg/arm/system/rp2040-minimal.ld | 40 ++++++ tests/tcg/arm/system/rp2040-mpu.S | 183 +++++++++++++++++++++++++ tests/tcg/arm/system/rp2040-mpu.ref | 5 + tests/tcg/arm/system/rp2040-uart.S | 53 +++++++ tests/tcg/arm/system/rp2040-uart.ref | 1 + 8 files changed, 337 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-mpu.S create mode 100644 tests/tcg/arm/system/rp2040-mpu.ref 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 8fd7385d83..b000b3287d 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1042,6 +1042,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/Makefile.softmmu-target b/tests/tcg/arm/Makefile.softmmu-target index 3e8a9b4073..429416ca58 100644 --- a/tests/tcg/arm/Makefile.softmmu-target +++ b/tests/tcg/arm/Makefile.softmmu-target @@ -20,6 +20,30 @@ run-test-armv6m-undef: QEMU_OPTS=-semihosting-config enable=on,target=native,cha ARM_TESTS+=test-armv6m-undef +RP2040_TESTS=rp2040-boot rp2040-uart rp2040-mpu + +$(RP2040_TESTS): %: %.S rp2040-minimal.ld + $(CC) -mcpu=cortex-m0plus -mthumb -mfloat-abi=soft \ + -Wl,--build-id=none -x assembler-with-cpp \ + $< -o $@ -nostdlib -static \ + -T $(ARM_SRC)/rp2040-minimal.ld + +run-rp2040-boot: QEMU_OPTS=-M raspi-pico \ + -semihosting-config enable=on,target=native -kernel + +run-rp2040-uart run-rp2040-mpu: QEMU_OPTS=-M raspi-pico \ + -serial chardev:output \ + -semihosting-config enable=on,target=native -kernel + +run-rp2040-uart run-rp2040-mpu: run-rp2040-%: rp2040-% + $(call run-test, $<, \ + $(QEMU) -monitor none -display none \ + -chardev file$(COMMA)path=$<.out$(COMMA)id=output \ + $(QEMU_OPTS) $<) + $(call diff-out,$<,$(ARM_SRC)/$<.ref) + +ARM_TESTS+=$(RP2040_TESTS) + # These objects provide the basic boot code and helper functions for all tests CRT_OBJS=boot.o 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-mpu.S b/tests/tcg/arm/system/rp2040-mpu.S new file mode 100644 index 0000000000..a3aef55f5f --- /dev/null +++ b/tests/tcg/arm/system/rp2040-mpu.S @@ -0,0 +1,183 @@ +/* + * Raspberry Pi Pico Cortex-M0+ MPU test. + * + * Copyright 2026 Gilles Grimaud + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +.syntax unified +.cpu cortex-m0plus +.thumb + +#define SRAM_END 0x20042000 +#define TEST_ADDRESS 0x20001000 +#define TEST_VALUE 0x12345678 +#define UART0_DR 0x40034000 +#define MPU_TYPE 0xe000ed90 +#define MPU_CTRL 0xe000ed94 +#define MPU_RNR 0xe000ed98 +#define MPU_RBAR 0xe000ed9c +#define MPU_RASR 0xe000eda0 +#define MPU_TYPE_DREGION_MASK 0x0000ff00 +#define MPU_TYPE_DREGION_SHIFT 8 +#define MPU_CTRL_ENABLE_PRIVDEFENA 0x05 +#define MPU_RASR_SRAM_FULL_ACCESS 0x03000025 +#define MPU_RASR_XIP_READ_ONLY 0x06000039 +#define MPU_RASR_TEST_PRIV_RW 0x0100000f +#define SYS_EXIT 0x18 +#define ADP_STOPPED_APPLICATION_EXIT 0x20026 +#define ADP_STOPPED_RUNTIME_ERROR 0x20023 + +.section .vectors, "a", %progbits +vector_table: + .word SRAM_END + .word reset_handler + 1 + .word default_handler + 1 + .word hardfault_handler + 1 + +.section .text, "ax", %progbits +.thumb_func +.global reset_handler +reset_handler: + ldr r0, =start_message + bl puts + + ldr r0, =MPU_TYPE + ldr r0, [r0] + ldr r1, =MPU_TYPE_DREGION_MASK + ands r0, r1 + lsrs r0, r0, MPU_TYPE_DREGION_SHIFT + cmp r0, 8 + bne fail_type + + ldr r0, =type_message + bl puts + + ldr r4, =TEST_ADDRESS + ldr r5, =TEST_VALUE + str r5, [r4] + ldr r0, [r4] + cmp r0, r5 + bne fail_plain + + ldr r0, =plain_message + bl puts + + movs r0, 0 + ldr r1, =0x20000000 + ldr r2, =MPU_RASR_SRAM_FULL_ACCESS + bl configure_region + + movs r0, 1 + movs r1, 0 + ldr r2, =MPU_RASR_XIP_READ_ONLY + bl configure_region + + movs r0, 2 + ldr r1, =TEST_ADDRESS + ldr r2, =MPU_RASR_TEST_PRIV_RW + bl configure_region + + ldr r0, =MPU_CTRL + movs r1, MPU_CTRL_ENABLE_PRIVDEFENA + str r1, [r0] + dsb + isb + + ldr r0, [r4] + cmp r0, r5 + bne fail_privileged + + ldr r0, =privileged_message + bl puts + + movs r0, 1 + msr control, r0 + isb + + ldr r0, [r4] + ldr r0, =fail_no_fault_message + b test_failed + +.thumb_func +configure_region: + ldr r3, =MPU_RNR + str r0, [r3] + ldr r3, =MPU_RBAR + str r1, [r3] + ldr r3, =MPU_RASR + str r2, [r3] + bx lr + +fail_type: + ldr r0, =fail_type_message + b test_failed + +fail_plain: + ldr r0, =fail_plain_message + b test_failed + +fail_privileged: + ldr r0, =fail_privileged_message + +test_failed: + bl puts + movs r0, SYS_EXIT + ldr r1, =ADP_STOPPED_RUNTIME_ERROR + bkpt 0xab + +1: + b 1b + +.thumb_func +hardfault_handler: + ldr r0, =ok_message + bl puts + movs r0, SYS_EXIT + ldr r1, =ADP_STOPPED_APPLICATION_EXIT + bkpt 0xab + +2: + b 2b + +.thumb_func +default_handler: + ldr r0, =fail_exception_message + b test_failed + +.thumb_func +puts: + ldr r2, =UART0_DR + +3: + ldrb r1, [r0] + cmp r1, 0 + beq 4f + str r1, [r2] + adds r0, 1 + b 3b + +4: + bx lr + +.section .rodata, "a", %progbits +start_message: + .asciz "PICO TCG MPU START\n" +type_message: + .asciz "PICO TCG MPU TYPE\n" +plain_message: + .asciz "PICO TCG MPU PLAIN\n" +privileged_message: + .asciz "PICO TCG MPU PRIV\n" +ok_message: + .asciz "PICO TCG MPU OK\n" +fail_type_message: + .asciz "PICO TCG MPU FAIL: TYPE\n" +fail_plain_message: + .asciz "PICO TCG MPU FAIL: PLAIN\n" +fail_privileged_message: + .asciz "PICO TCG MPU FAIL: PRIV\n" +fail_no_fault_message: + .asciz "PICO TCG MPU FAIL: NOFAULT\n" +fail_exception_message: + .asciz "PICO TCG MPU FAIL: EXCEPTION\n" diff --git a/tests/tcg/arm/system/rp2040-mpu.ref b/tests/tcg/arm/system/rp2040-mpu.ref new file mode 100644 index 0000000000..e55590ea16 --- /dev/null +++ b/tests/tcg/arm/system/rp2040-mpu.ref @@ -0,0 +1,5 @@ +PICO TCG MPU START +PICO TCG MPU TYPE +PICO TCG MPU PLAIN +PICO TCG MPU PRIV +PICO TCG MPU OK 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
