commit 004799eb8e0f07992acb10210fd1aa054a916d56
parent 56f85fac0d8cd2d0effedd6f784264d1b3aa7f6e
Author: Matsuda Kenji <info@mtkn.jp>
Date:   Thu, 28 Aug 2025 09:02:36 +0900
copy ex3_interrupt => ex4_shell, use c code
Diffstat:
5 files changed, 416 insertions(+), 0 deletions(-)
diff --git a/ex4_shell/Makefile b/ex4_shell/Makefile
@@ -0,0 +1,43 @@
+CC = arm-none-eabi-gcc
+AS = arm-none-eabi-as
+LD = arm-none-eabi-ld
+OBJCOPY = arm-none-eabi-objcopy
+BINCRC = ../tools/bincrc
+BIN2UF2 = ../tools/bin2uf2
+
+MCPU = -mcpu=cortex-m0plus
+ASFLAGS = $(MCPU)
+CFLAGS = $(MCPU) -ffreestanding -nostartfiles -O0 -fpic -mthumb -c
+LDFLAGS = --no-relax -nostdlib
+
+OBJS = boot2.o start.o main.o
+
+all: tools a.uf2
+
+clean:
+	rm -f *.o *.elf *.uf2 *.bin
+	cd ../tools && make clean
+
+.s.o:
+	$(AS) $(ASFLAGS) -o $@ $<
+
+.c.o:
+	$(CC) $(CFLAGS) -o $@ $<
+
+a.elf: $(OBJS) memmap.ld
+	$(LD) $(LDFLAGS) -o $@ -T memmap.ld $(OBJS)
+
+a.bin: a.elf
+	$(OBJCOPY) -O binary a.elf $@
+
+a.uf2: a.bin
+	$(BINCRC) a.bin a_crc.bin
+	$(BIN2UF2) a_crc.bin $@
+
+flash: all
+	#mount /dev/disk/by-label/RPI-RP2 /mnt
+	mount /dev/sd2i /mnt
+	cp a.uf2 /mnt
+
+tools:
+	cd ../tools && make
diff --git a/ex4_shell/boot2.s b/ex4_shell/boot2.s
@@ -0,0 +1,29 @@
+.cpu cortex-m0plus
+.thumb
+
+	.section .boot2
+setup_xip:
+	ldr r3, rom_base
+
+	ldrh r0, [r3, #0x14] // rom_func_table
+	ldr r1, =('C' | 'X' << 8) // _flash_enter_cmd_xip()
+	ldrh r2, [r3, #0x18] // rom_table_lookup
+	blx r2
+	blx r0
+
+	ldr r0, =vectors
+	ldr r1, m0plus_vtor 
+	str r0, [r1, #0] // M0PLUS: VTOR
+	ldr r1, [r0, #4] // entry point
+	ldr r0, [r0, #0] // stack pointer
+	mov sp, r0
+	bx r1
+
+	.align 2
+rom_base:
+	.word 0x00000000
+m0plus_vtor:
+	.word 0xe0000000 + 0xed08
+literals:
+	.ltorg
+
diff --git a/ex4_shell/main.c b/ex4_shell/main.c
@@ -0,0 +1,5 @@
+void
+main(void)
+{
+	mains();
+}
diff --git a/ex4_shell/memmap.ld b/ex4_shell/memmap.ld
@@ -0,0 +1,18 @@
+MEMORY
+{
+	FLASH(rx) : ORIGIN = 0x10000000, LENGTH = 2048k
+	SRAM(rwx) : ORIGIN = 0x20000000, LENGTH = 264k
+}
+
+SECTIONS
+{
+	.boot2 : {
+		*(.boot2)
+		. = 0x100;
+	} > FLASH
+
+	.text : {
+		*(.text)
+	} > FLASH
+}
+
diff --git a/ex4_shell/start.s b/ex4_shell/start.s
@@ -0,0 +1,321 @@
+.cpu cortex-m0plus
+.thumb
+
+	.global vectors
+vectors:
+	.word 0x20040000 // initial SP
+	.word (reset+1)  // entry point
+	.word 0xdeadbeef
+	.word 0xdeadbeef
+
+	.word 0xdeadbeef
+	.word 0xdeadbeef
+	.word 0xdeadbeef
+	.word 0xdeadbeef
+
+	.word 0xdeadbeef
+	.word 0xdeadbeef
+	.word 0xdeadbeef
+	.word 0xdeadbeef
+
+	.word 0xdeadbeef
+	.word 0xdeadbeef
+	.word 0xdeadbeef
+	.word 0xdeadbeef
+
+
+	.word 0xdeadbeef
+	.word 0xdeadbeef
+	.word 0xdeadbeef
+	.word 0xdeadbeef
+
+	.word 0xdeadbeef
+	.word 0xdeadbeef
+	.word 0xdeadbeef
+	.word 0xdeadbeef
+
+	.word 0xdeadbeef
+	.word 0xdeadbeef
+	.word 0xdeadbeef
+	.word 0xdeadbeef
+
+	.word 0xdeadbeef
+	.word 0xdeadbeef
+	.word 0xdeadbeef
+	.word 0xdeadbeef
+
+	.word 0xdeadbeef
+	.word 0xdeadbeef
+	.word 0xdeadbeef
+	.word 0xdeadbeef
+
+	.word (uart_interrupt_handler+1) // UART0_IRQ
+
+	.section .text
+reset:
+	bl main
+loop:
+	wfe
+	b loop
+
+	.global mains
+mains:
+	push {lr}
+
+	// unreset gpio, pll_sys, uart0
+	ldr r0, =(1 << 22 | 1 << 12 | 1 << 5) // uart0 | pll_sys | io_bank0
+	ldr r3, resets_base
+	ldr r1, atomic_clr
+	str r0, [r3, r1] // RESETS: RESET
+	mov r1, #1
+	lsl r1, #22
+	bic r0, r1 // uart stays in reset state until clock_peri is enabled
+unreset_chk:
+	ldr r1, [r3, #0x8] // RESETS: RESET_DONE
+	bic r0, r1
+	bne unreset_chk
+
+	// set gpio functions
+	ldr r3, io_bank0_base
+	// set pins 0 and 1 for uart
+	mov r0, #2 // uart0
+	mov r1, #0x4
+	str r0, [r3, r1] // IO_BANK0: GPIO0_CTRL
+	mov r1, #0xc
+	str r0, [r3, r1] // IO_BANK0: GPIO1_CTRL
+	// set pins 24 and 25 to SIO for led blink.
+	mov r0, #5 // sio
+	mov r1, #0xc4
+	str r0, [r3, r1] // IO_BANK0: GPIO24_CTRL
+	mov r1, #0xcc
+	str r0, [r3, r1] // IO_BANK0: GPIO24_CTRL
+
+	// enable sio output
+	ldr r3, sio_base
+	mov r0, #0b11
+	lsl r0, r0, #24
+	str r0, [r3, #0x24] // SIO: GPIO_OE
+
+	// setup xosc
+	ldr r3, xosc_base
+	mov r0, #47 // start up delay for 12MHz rosc (xosc?)
+	str r0, [r3, #0xc] // XOSC: STARTUP
+	ldr r0, =(0xfab << 12 | 0xaa0)
+	str r0, [r3, #0] // XOSC: CTRL
+wait_xosc:
+	ldr r0, [r3, #0x4] // XOSC: STATUS
+	lsr r0, r0, #31 // STABLE bit
+	beq wait_xosc
+
+	// setup pll_sys 133MHz
+	ldr r3, pll_sys_base
+	// set feedback divider
+	mov r0, #133
+	str r0, [r3, #0x8] // PLL: FBDIV_INT
+	// power on pll and vco
+	ldr r0, =(1 << 5 | 1) // VCOPD | PD
+	ldr r1, atomic_clr
+	add r1, r1, #0x4
+	str r0, [r3, r1] // PLL: PWR
+	// wait vco to lock
+wait_vco:
+	ldr r0, [r3, #0] // PLL: CS
+	lsl r0, r0, #31
+	beq wait_vco
+	// setup post dividers
+	ldr r0, =(4 << 16 | 3 << 12)
+	str r0, [r3, #0xc] // PLL: PRIM
+	// power on post divider
+	mov r0, #8 // POSTDIVPD
+	str r0, [r3, r1] // PLL: PWR
+
+	// set system clock clksrc_pll_sys
+	ldr r3, clocks_base
+	ldr r0, =(0x0 << 5 | 0x1)
+	str r0, [r3, #0x3c] // CLOCKS: CLK_SYS_CTRL
+	// enable clk_peri
+	mov r0, #1
+	lsl r0, r0, #11
+	str r0, [r3, #0x48] // CLOCKS: CLK_PERI_CTRL
+
+	// setup uart0
+	ldr r3, uart0_base
+	// set baudrate 115200
+	// BDRI = 72, BDRF = 0.157 (10 / 64)
+	mov r0, #72
+	str r0, [r3, #0x24] // UART: UARTIBRD
+	mov r0, #10
+	str r0, [r3, #0x28] // UART: UARTFBRD
+	// enable uart0
+	mov r0, #1 // UARTEN
+	ldr r1, atomic_set
+	add r1, r1, #0x30
+	str r0, [r3, r1] // UART: UARTCR
+	// enable FIFO and set format
+	ldr r0, =(3 << 5 | 1 << 4) // WLEN = 8, FEN = 1
+	str r0, [r3, #0x2c] // UART: UARTLCR_H
+
+	// enable uart interrupt in cpu
+	ldr r4, ppb_base
+	mov r5, #0xe1
+	lsl r5, #8
+	mov r0, #1
+	lsl r0, #20
+	str r0, [r4, r5] // M0PLUS: NVIC_ISER
+
+	// enable uart interrupt in uart0 subsystem
+	ldr r1, uart0_base
+	mov r2, #(1 << 6 | 1 << 4) // RTIM | RXIM
+	str r2, [r1, #0x38] // UART: UARTIMSC
+	// set fifo level to 0
+	mov r2, #0
+	str r2, [r1, #0x34] // UART: UARTIFLS
+
+	pop {pc}
+
+// functions
+
+	// print r0 in hex for debugging.
+printh:
+	push {r4, r5, r6, r7, lr}
+	mov r4, r0
+	mov r5, #28
+	mov r6, #0xf
+	mov r7, #10
+printh_loop:
+	mov r0, r4
+	lsr r0, r0, r5
+	and r0, r0, r6
+	sub r1, r0, r7
+	blt digi
+	add r0, r0, #('a' - 10)
+	b alpha
+digi:
+	add r0, r0, #'0'
+alpha:
+	bl putbyte
+	sub r5, r5, #4
+	bge printh_loop
+	pop {r4, r5, r6, r7, pc}
+
+	// putbyte sends a byte specified by r0 to uart0.
+	// It busy-waits for the buffer to become available.
+putbyte:
+	ldr r3, uart0_base
+	mov r1, #1
+	lsl r1, r1, #5 // TXFF
+txff:
+	ldr r2, [r3, #0x18] // UART: UARTFR
+	tst r1, r2
+	bne txff
+	mov r1, #0xff
+	and r0, r0, r1
+	str r0, [r3, #0] // UART: UARTDR
+	bx lr
+
+	// getbyte reads a byte from uart0 and returns it on r0
+	// It busy-waits for a data.
+getbyte:
+	ldr r3, uart0_base
+	mov r1, #1
+	lsl r1, r1, #4 // RXFE
+rxfe:
+	ldr r2, [r3, #0x18] // UART: UARTFR
+	tst r1, r2
+	bne rxfe
+	ldr r0, [r3, #0] // UART: UARTDR
+	mov r1, #0xff
+	and r0, r0, r1
+	bx lr
+
+// The following functions make no side effects and
+// can be used anywhare without pushing and popping
+// registers.
+
+	// pled prints register content with 2 leds on the pins 24 and 25, lsb first.
+pled:
+	push {r0, r1, r2, r3, r4, r5, r6, lr}
+	mov r4, r0
+	mov r5, #32
+	mov r6, #1
+pled_loop:
+	tst r4, r6
+	beq pled0
+	bl bled1
+	b pled1
+pled0:
+	bl bled0
+pled1:
+	lsr r4, r4, #1
+	sub r5, r5, #1
+	bne pled_loop
+	pop {r0, r1, r2, r3, r4, r5, r6, pc}
+
+	// bled0 blinks the led on the pin 24 once.
+bled0:
+	push {r0, r1, r2, r3, lr}
+	mov r0, #1
+	lsl r0, r0, #24
+	bl bled
+	pop {r0, r1, r2, r3, pc}
+
+	// bled1 blinks the led on the pin 25 once.
+bled1:
+	push {r0, r1, r2, r3, lr}
+	mov r0, #1
+	lsl r0, r0, #25
+	bl bled
+	pop {r0, r1, r2, r3, pc}
+
+	// bled blinks the led on the pin specified by r0 once.
+bled:
+	push {r0, r1, r2, r3, r4, r5, lr}
+	ldr r4, sio_base
+	mov r5, r0
+	str r5, [r4, #0x10] // SIO: GPIO_OUT_XOR
+	bl delay
+	str r5, [r4, #0x18] // SIO: GPIO_OUT_XOR
+	bl delay
+	pop {r0, r1, r2, r3, r4, r5, pc}
+	
+	// delay delays for a moment by counting down a register.
+delay:
+	push {r0}
+	mov r0, #1
+	lsl r0, r0, #24
+delay_loop:
+	sub r0, r0, #1
+	bne delay_loop
+	pop {r0}
+	bx lr
+
+	// uart_interrupt_handler echos the data arrived at uart0
+uart_interrupt_handler:
+	push {lr}
+	bl getbyte
+	bl putbyte
+	pop {pc}
+
+	.align 2
+literals:
+	.ltorg
+atomic_set:
+	.word 0x00002000
+atomic_clr:
+	.word 0x00003000
+clocks_base:
+	.word 0x40008000
+resets_base:
+	.word 0x4000c000
+io_bank0_base:
+	.word 0x40014000
+xosc_base:
+	.word 0x40024000
+pll_sys_base:
+	.word 0x40028000
+uart0_base:
+	.word 0x40034000
+sio_base:
+	.word 0xd0000000
+ppb_base:
+	.word 0xe0000000