Add assembly bare metal blink examble for rp2350.

Signed-off-by: jmug <u.g.a.mariano@gmail.com>
This commit is contained in:
Mariano Uvalle 2025-05-18 18:32:42 -07:00
parent 3a571e61b4
commit 1e0a36f7b3
5 changed files with 231 additions and 0 deletions

View file

@ -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"

View file

@ -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

View file

@ -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

View file

@ -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 */
}

View file

@ -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