From 1e0a36f7b36ad99fdee2f087ba42729fe0f9bbc9 Mon Sep 17 00:00:00 2001 From: jmug Date: Sun, 18 May 2025 18:32:42 -0700 Subject: [PATCH] Add assembly bare metal blink examble for rp2350. Signed-off-by: jmug --- bare_metal/rp2350/blink/Makefile | 29 ++++++++ bare_metal/rp2350/blink/hello_world.s | 79 +++++++++++++++++++++ bare_metal/rp2350/blink/min_arm_image_def.s | 37 ++++++++++ bare_metal/rp2350/blink/pico_plus_2.ld | 63 ++++++++++++++++ bare_metal/rp2350/blink/vectors.s | 23 ++++++ 5 files changed, 231 insertions(+) create mode 100644 bare_metal/rp2350/blink/Makefile create mode 100644 bare_metal/rp2350/blink/hello_world.s create mode 100644 bare_metal/rp2350/blink/min_arm_image_def.s create mode 100644 bare_metal/rp2350/blink/pico_plus_2.ld create mode 100644 bare_metal/rp2350/blink/vectors.s diff --git a/bare_metal/rp2350/blink/Makefile b/bare_metal/rp2350/blink/Makefile new file mode 100644 index 0000000..82a4a14 --- /dev/null +++ b/bare_metal/rp2350/blink/Makefile @@ -0,0 +1,29 @@ +CC=arm-none-eabi-gcc +MACH=cortex-m33 +CFLAGS= -c -mcpu=$(MACH) -mthumb -std=gnu11 -Wall -O0 +LFLAGS= -nostdlib -T pico_plus_2.ld -Wl,-Map=final.map + +assemble: vectors.o hello_world.o min_arm_image_def.o + +vectors.o: vectors.s + $(CC) $(CFLAGS) -o $@ $^ + +hello_world.o: hello_world.s + $(CC) $(CFLAGS) -o $@ $^ + +min_arm_image_def.o: min_arm_image_def.s + $(CC) $(CFLAGS) -o $@ $^ + +hello_world.elf: vectors.o hello_world.o min_arm_image_def.o + $(CC) $(LFLAGS) -o $@ $^ + +clean: + - rm -rf $(wildcard *.o) + - rm -rf $(wildcard *.elf) + - rm -rf $(wildcard *.map) + +link: hello_world.elf + +PHONY: flash +flash: + sudo openocd -s tcl -f interface/cmsis-dap.cfg -f target/rp2350.cfg -c "adapter speed 5000" -c "program hello_world.elf verify reset exit" diff --git a/bare_metal/rp2350/blink/hello_world.s b/bare_metal/rp2350/blink/hello_world.s new file mode 100644 index 0000000..4dcb596 --- /dev/null +++ b/bare_metal/rp2350/blink/hello_world.s @@ -0,0 +1,79 @@ +.section .text + +.equ rst_base, 0x40020000 // Subsystems reset reg base 7.5.3 +.equ rst_clr, 0x40023000 // Adding 0x3000 according 2.1.3 +.equ io_bank, 0x40028000 +.equ io_bank_gp25, 0x400280cc +.equ sio_base, 0xd0000000 +.equ big_num, 0x00f00000 // For the delay. +.equ pads_base, 0x40038000 // Pad control registers base. +.equ pads_set, 0x4003a000 +.equ pads_clr, 0x4003b000 +.equ resets_wrd, 0b100001001000000 // Bits 14 (PLL_SYS), 9 (PADS_BANK0) and 6 (IO_BANK0) + +.thumb_func // This makes sure that the address of start has its LSB set to signal thumb mode. +.global hello_start +hello_start: +// Bring PLL, PADS and IO out of reset + ldr r0, =rst_clr + ldr r2, =resets_wrd + str r2, [r0, #0] +check_rst: + ldr r0, =rst_base + ldr r1, [r0, #0x8] // Offset to RESET_DONE from rst_base + and r1, r1, r2 // Check bit 14, 9 and 6 to ensure the subsystems we care about are out of reset. + cmp r1, r2 + bne check_rst +clocks_setup: +// TODO: Configure the crystal oscilator and set it as the reference clock. +// TODO: Configure the PLL and wait for it to lock. +// TODO: Change the sys clock source to the PLL. +configure_peripheral: + // See: https://github.com/raspberrypi/pico-sdk/blob/ee68c78d0afae2b69c03ae1a72bf5cc267a2d94c/src/rp2_common/hardware_gpio/gpio.c#L38 + // Set pad input and output enabled. + ldr r0, =pads_set + mov r2, #0b1000000 // Set bit 6 to enable input. + str r2, [r0, #0x68] + ldr r0, =pads_clr + mov r2, #0b10000000 // Clear bit 7 to enable output. + str r2, [r0, #0x68] + // Set function 5 (SIO) to GPIO25 + ldr r0, =io_bank_gp25 + mov r1, #5 // FSEL 5 (SIO) + str r1, [r0] + // Remove isolation control on the pad control now that it's connected to its peripheral (SIO). + ldr r0, =pads_clr + mov r2, #1 // Clear bit 8 to remove isolation control. + lsl r2, r2, #8 + str r2, [r0, #0x68] + // Enable the output + ldr r0, =sio_base + mov r1, #1 + lsl r1, r1, #25 // Only enable gpio25 + str r1, [r0, #0x38] // GPIO_OE_SET offset +blink: + ldr r0, =sio_base + mov r1, #1 + lsl r1, r1, #25 +led_loop: + str r1, [r0, #0x18] // GPIO_OUT_SET + ldr r3, =big_num + bl delay + + str r1, [r0, #0x20] // GPIO_OUT_CLR + ldr r3, =big_num + bl delay + + b led_loop + +delay: + sub r3, #1 + bne delay + bx lr + +// An interrupt handler that just spins. +.thumb_func +.global isr_default +isr_default: + b isr_default + diff --git a/bare_metal/rp2350/blink/min_arm_image_def.s b/bare_metal/rp2350/blink/min_arm_image_def.s new file mode 100644 index 0000000..62e2bf7 --- /dev/null +++ b/bare_metal/rp2350/blink/min_arm_image_def.s @@ -0,0 +1,37 @@ +// SPDX-FileCopyrightText: 2024 Mete Balci +// +// SPDX-License-Identifier: GPL-3.0-or-later + +// ref: RP2350 datasheet 5.9.5.1. Minimum Arm IMAGE_DEF + +// this is a single block with two items (IMAGE_TYPE and LAST) in it + +// include this section in linker description in the first 4K of a flash image +.section .picobin_block, "a" + +.word 0xffffded3 // PICOBIN_BLOCK_MARKER_START + +// item 0 IMAGE_TYPE + +.byte 0x42 // PICOBIN_BLOCK_ITEM_1BS_IMAGE_TYPE +.byte 0x1 // item is 1 word +// Try Before You Buy - 0 (not set) +// Chip - b001 (RP2350) +// reserved - 0b0 +// CPU - b000 (ARM) +// reserved - 0b00 +// EXE Security - 0b10 (Secure mode) +// Image Type - 0b0001 (EXE) +.hword 0b0001000000100001 + +// item 1 LAST + +.byte 0xff // PICOBIN_BLOCK_ITEM_2BS_LAST +.hword 0x0001 // item is 1 word +.byte 0 // pad + +// relative pointer to next block in loop +// 0 means a link to itself, meaning there is no other block +.word 0 + +.word 0xab123579 // PICOBIN_BLOCK_MARKER_END diff --git a/bare_metal/rp2350/blink/pico_plus_2.ld b/bare_metal/rp2350/blink/pico_plus_2.ld new file mode 100644 index 0000000..e759ce8 --- /dev/null +++ b/bare_metal/rp2350/blink/pico_plus_2.ld @@ -0,0 +1,63 @@ +/* + * Minimal version of: + * - https://github.com/raspberrypi/pico-sdk/blob/ee68c78d0afae2b69c03ae1a72bf5cc267a2d94c/src/rp2_common/pico_crt0/rp2350/memmap_default.ld + * - https://github.com/raspberrypi/pico-sdk/blob/ee68c78d0afae2b69c03ae1a72bf5cc267a2d94c/src/rp2_common/pico_standard_link/pico_flash_region.template.ld + * - https://github.com/raspberrypi/pico-sdk/blob/ee68c78d0afae2b69c03ae1a72bf5cc267a2d94c/src/boards/include/boards/pimoroni_pico_plus2_rp2350.h#L88C1-L88C49 + * + * Provides the following symbols to be used in assembly: + * - __StackTop + */ +__XIP_BASE = 0x10000000; +__XIP_SIZE = 16M; /* 16M is allocated to QSPI flash for the pico 2 plus */ + +__SRAM_BASE = 0x20000000; +__SRAM_SIZE = 512K; + +__SCRATCH_X_BASE = 0x20080000; +__SCRATCH_Y_BASE = 0x20081000; +__SCRATCH_SIZE = 4K; /* Both scratch regions have the same size */ + +/* Memories */ +MEMORY +{ + FLASH (rx) : ORIGIN = __XIP_BASE, LENGTH = __XIP_SIZE + RAM (rwx) : ORIGIN = __SRAM_BASE, LENGTH = __SRAM_SIZE + SCRATCH_X(rwx) : ORIGIN = __SCRATCH_X_BASE, LENGTH = __SCRATCH_SIZE + SCRATCH_Y(rwx) : ORIGIN = __SCRATCH_Y_BASE, LENGTH = __SCRATCH_SIZE +} + +/* this is to eliminate RWX permission error for text segment */ +/* I don't think it's necessary */ +/* PHDRS +{ + text PT_LOAD FLAGS(5); + data PT_LOAD FLAGS(6); + bss PT_LOAD FLAGS(6); +} +*/ + +/* Sections */ +SECTIONS +{ + .text : { + KEEP(*(.vectors)) + . = ALIGN(512); /* See https://forums.raspberrypi.com/viewtopic.php?t=387420 Quote: "So, in the RP2350 Cortex M33 with 16 internal exception vectors and 52 interrupts, the alignment must be 512 bytes. (16+52)x4 = 272, next power of two = 512" */ + KEEP(*(.picobin_block)) + *(.text) + . = ALIGN(4); + } > FLASH + + .data : { + __data_start__ = .; + *(.data*) + . = ALIGN(4); + __data_end__ = .; + } > RAM /* AT > FLASH :data */ /* See: https://stackoverflow.com/questions/28809372/what-does-region1-at-region2-mean-in-an-ld-linker-script */ + + + /* stack limit is poorly named, but historically is maximum heap ptr */ + __StackLimit = ORIGIN(RAM) + LENGTH(RAM); + __StackTop = ORIGIN(SCRATCH_Y) + LENGTH(SCRATCH_Y); /* Used for core 0 */ + __StackOneTop = ORIGIN(SCRATCH_X) + LENGTH(SCRATCH_X); /* Used for core 1 */ + +} diff --git a/bare_metal/rp2350/blink/vectors.s b/bare_metal/rp2350/blink/vectors.s new file mode 100644 index 0000000..38fd88c --- /dev/null +++ b/bare_metal/rp2350/blink/vectors.s @@ -0,0 +1,23 @@ +// Based on https://github.com/raspberrypi/pico-sdk/blob/ee68c78d0afae2b69c03ae1a72bf5cc267a2d94c/src/rp2_common/pico_crt0/crt0.S +.section .vectors, "ax" +.align 2 + +.global __vectors, __VECTOR_TABLE +__VECTOR_TABLE: +__vectors: +.word __StackTop +.word hello_start +.word isr_default +.word isr_default +.word isr_default +.word isr_default +.word isr_default +.word isr_default +.word isr_default +.word isr_default +.word isr_default +.word isr_default +.word isr_default +.word isr_default +.word isr_default +.word isr_default