aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile17
-rw-r--r--blink.s54
-rw-r--r--clocks.s18
-rw-r--r--gpio.s25
-rw-r--r--main.s13
-rw-r--r--pll.s58
-rw-r--r--xosc.s23
7 files changed, 158 insertions, 50 deletions
diff --git a/Makefile b/Makefile
index 3a94707..7873488 100644
--- a/Makefile
+++ b/Makefile
@@ -2,19 +2,16 @@ all: build
build: blink.uf2
-# convert ELF file to UF2 file
blink.uf2: blink.elf
- elf2uf2 blink.elf blink.uf2
+ ./elf2uf2 blink.elf blink.uf2
-# compile
-blink.elf: blink.o
- arm-none-eabi-ld -T pico_ram_only.ld -o blink.elf blink.o
+objects = main.o blink.o clocks.o gpio.o pll.o xosc.o
-blink.o: blink.s
- arm-none-eabi-as -o blink.o blink.s
+blink.elf: $(objects)
+ arm-none-eabi-ld -T pico_ram_only.ld -o blink.elf $(objects)
-# flash: build/blink.uf2
-# cp build/blink.uf2 /Volumes/RPI-RP2
+$(objects): %.o: %.s
+ arm-none-eabi-as -o $@ $<
clean:
- rm blink.elf blink.uf2 blink.o
+ rm blink.elf blink.uf2 *.o
diff --git a/blink.s b/blink.s
index 34c4086..3bda498 100644
--- a/blink.s
+++ b/blink.s
@@ -2,10 +2,6 @@
.cpu cortex-m0plus
.thumb
-.equ RESETS_BASE, 0x4000c000
-.equ RESET_OFST, 0x0
-.equ RESET_DONE_OFST, 0x8
-
.equ IO_BANK0_BASE, 0x40014000
.equ GPIO25_STATUS, (IO_BANK0_BASE + 0x0c8)
.equ GPIO25_CTRL, (IO_BANK0_BASE + 0x0cc)
@@ -16,43 +12,21 @@
.equ ATOMIC_CLEAR, 0x3000
-.type main, %function
-.global main
-main:
-
- // Deassert GPIO reset
- ldr r1, =(RESETS_BASE + ATOMIC_CLEAR)
- movs r0, 0x20 // IO_BANK0 is bit 5
- str r0, [r1, RESET_OFST]
-
- // Wait for GPIO reset to finish
- ldr r1, =RESETS_BASE
-1:
- ldr r2, [r1, RESET_DONE_OFST]
- tst r0, r2
- beq 1b
+.type blink, %function
+.global blink
- // Set GPIO25 function to SIO
+blink:
ldr r1, =GPIO25_CTRL
- movs r0, #5
- str r0, [r1, #0]
-
+ movs r0, 5 // SIO function = 5
+ str r0, [r1, 0]
ldr r1, =SIO_BASE
-
- // Set output enable for GPIO 25
- movs r0, #1
- lsls r0, r0, #25
+ movs r0, 1
+ lsls r0, r0, 25 // GPIO 25 (LED) output enable
str r0, [r1, GPIO_OE_SET_OFST]
-
-loop:
-
- // Toggle output level for GPIO 25
- str r0, [r1, GPIO_OUT_XOR_OFST]
-
- // Delay
- ldr r2, =400000
-1:
- subs r2, r2, #1
- bne 1b
-
- b loop
+toggle_one_second:
+ str r0, [r1, GPIO_OUT_XOR_OFST] // toggle GPIO 25 output level
+ ldr r2, =0x1fca055 // 33.3 * 10^6 (one-third of a second at 100MHz)
+1: // 3 clock cycle loop
+ subs r2, r2, 1 // 1 clock cycle
+ bne 1b // 2 clock cycles when taken
+ b toggle_one_second
diff --git a/clocks.s b/clocks.s
new file mode 100644
index 0000000..09a0f6d
--- /dev/null
+++ b/clocks.s
@@ -0,0 +1,18 @@
+.syntax unified
+.cpu cortex-m0plus
+.thumb
+
+.equ CLOCKS_BASE, 0x40008000
+.equ CLK_REF_CTRL_OFST, 0x30
+.equ CLK_SYS_CTRL_OFST, 0x3c
+
+.type setup_clocks, %function
+.global setup_clocks
+
+setup_clocks:
+ ldr r1, =CLOCKS_BASE
+ movs r0, 2 // use xosc (=0x2) as clk_ref source
+ str r0, [r1, CLK_REF_CTRL_OFST]
+ movs r0, 1 // use auxsrc (default pll_sys, =0x1) as clk_sys source
+ str r0, [r1, CLK_SYS_CTRL_OFST]
+ mov pc, lr
diff --git a/gpio.s b/gpio.s
new file mode 100644
index 0000000..3b98ba0
--- /dev/null
+++ b/gpio.s
@@ -0,0 +1,25 @@
+.syntax unified
+.cpu cortex-m0plus
+.thumb
+
+.equ RESETS_BASE, 0x4000c000
+.equ RESET_OFST, 0x0
+.equ RESET_DONE_OFST, 0x8
+
+.equ ATOMIC_CLEAR, 0x3000
+
+.type setup_gpio, %function
+.global setup_gpio
+
+setup_gpio:
+ // clear reset
+ ldr r1, =(RESETS_BASE + ATOMIC_CLEAR)
+ movs r0, 0x20 // IO_BANK0 is bit 5
+ str r0, [r1, RESET_OFST]
+ ldr r1, =RESETS_BASE
+1:
+ ldr r2, [r1, RESET_DONE_OFST]
+ tst r0, r2 // IO_BANK0 is still bit 5
+ // wait for reset done
+ beq 1b
+ mov pc, lr
diff --git a/main.s b/main.s
new file mode 100644
index 0000000..eb5c8f9
--- /dev/null
+++ b/main.s
@@ -0,0 +1,13 @@
+.syntax unified
+.cpu cortex-m0plus
+.thumb
+
+.type main, %function
+.global main
+
+main:
+ bl start_xosc
+ bl start_pll
+ bl setup_clocks
+ bl setup_gpio
+ b blink
diff --git a/pll.s b/pll.s
new file mode 100644
index 0000000..68a03cc
--- /dev/null
+++ b/pll.s
@@ -0,0 +1,58 @@
+.syntax unified
+.cpu cortex-m0plus
+.thumb
+
+.equ RESETS_BASE, 0x4000c000
+.equ RESET_OFST, 0x0
+.equ RESET_DONE_OFST, 0x8
+
+.equ PLL_SYS_BASE, 0x40028000
+.equ CS_OFST, 0x0
+.equ PWR_OFST, 0x4
+.equ FBDIV_INT_OFST, 0x8
+.equ PRIM_OFST, 0xc
+
+.equ ATOMIC_CLEAR, 0x3000
+
+.type start_pll, %function
+.global start_pll
+
+// configure pll_sys for 100MHz
+start_pll:
+ // clear reset
+ ldr r1, =(RESETS_BASE + ATOMIC_CLEAR)
+ movs r0, 1
+ lsls r0, 12 // pll_sys is bit 12
+ str r0, [r1, RESET_OFST]
+ ldr r1, =RESETS_BASE
+1:
+ ldr r2, [r1, RESET_DONE_OFST]
+ tst r0, r2 // pll_sys is still bit 12
+ // wait for reset done
+ beq 1b
+ // set pls_sys feedback divider to 100
+ ldr r1, =PLL_SYS_BASE
+ movs r0, 100 // FBDIV = 100
+ str r0, [r1, FBDIV_INT_OFST]
+ // set pl_sys post dividers to 12 (6 * 2)
+ ldr r1, =PLL_SYS_BASE
+ movs r0, 6 // POSTDIV1 = 6
+ lsls r0, r0, 4
+ adds r0, r0, 2 // POSTDIV2 = 2
+ lsls r0, r0, 12
+ str r0, [r1, PRIM_OFST]
+ // turn on main power and VCO
+ ldr r1, =(PLL_SYS_BASE + ATOMIC_CLEAR)
+ movs r0, 0x21 // power and VCO (bits 0 and 5)
+ str r0, [r1, PWR_OFST]
+ // wait for VCO to lock
+ ldr r1, =PLL_SYS_BASE
+vco_lock:
+ ldr r2, [r1, CS_OFST]
+ lsrs r2, r2, 31
+ beq vco_lock
+ // turn on post divider power
+ ldr r1, =(PLL_SYS_BASE + ATOMIC_CLEAR)
+ movs r0, 0x8 // postdiv (bit 3)
+ str r0, [r1, PWR_OFST]
+ mov pc, lr
diff --git a/xosc.s b/xosc.s
new file mode 100644
index 0000000..ee58ec0
--- /dev/null
+++ b/xosc.s
@@ -0,0 +1,23 @@
+.syntax unified
+.cpu cortex-m0plus
+.thumb
+
+.equ XOSC_BASE, 0x40024000
+.equ CTRL_OFST, 0x0
+.equ STATUS_OFST, 0x4
+.equ STARTUP_OFST, 0xc
+
+.type start_xosc, %function
+.global start_xosc
+
+start_xosc:
+ ldr r1, =XOSC_BASE
+ movs r0, 47 // startup delay = 47 for 12Mhz crystal
+ str r0, [r1, STARTUP_OFST]
+ ldr r0, =0x00fabaa0 // enable
+ str r0, [r1, CTRL_OFST]
+1:
+ ldr r0, [r1, STATUS_OFST]
+ lsrs r0, r0, 31 // poll status bit
+ beq 1b
+ mov pc, lr