rp2040

RP2040 Programming without SDK
Log | Files | Refs

start.s (6712B)


      1 .cpu cortex-m0plus
      2 .thumb
      3 
      4 	.global vectors
      5 vectors:
      6 	.word 0x20040000 // initial SP
      7 	.word (reset+1)  // entry point
      8 	.word 0xdeadbeef
      9 	.word 0xdeadbeef
     10 
     11 	.word 0xdeadbeef
     12 	.word 0xdeadbeef
     13 	.word 0xdeadbeef
     14 	.word 0xdeadbeef
     15 
     16 	.word 0xdeadbeef
     17 	.word 0xdeadbeef
     18 	.word 0xdeadbeef
     19 	.word 0xdeadbeef
     20 
     21 	.word 0xdeadbeef
     22 	.word 0xdeadbeef
     23 	.word 0xdeadbeef
     24 	.word 0xdeadbeef
     25 
     26 
     27 	.word 0xdeadbeef
     28 	.word 0xdeadbeef
     29 	.word 0xdeadbeef
     30 	.word 0xdeadbeef
     31 
     32 	.word 0xdeadbeef
     33 	.word 0xdeadbeef
     34 	.word 0xdeadbeef
     35 	.word 0xdeadbeef
     36 
     37 	.word 0xdeadbeef
     38 	.word 0xdeadbeef
     39 	.word 0xdeadbeef
     40 	.word 0xdeadbeef
     41 
     42 	.word 0xdeadbeef
     43 	.word 0xdeadbeef
     44 	.word 0xdeadbeef
     45 	.word 0xdeadbeef
     46 
     47 	.word 0xdeadbeef
     48 	.word 0xdeadbeef
     49 	.word 0xdeadbeef
     50 	.word 0xdeadbeef
     51 
     52 	.word (uart_interrupt_handler+1) // UART0_IRQ
     53 
     54 	.section .text
     55 reset:
     56 	bl main
     57 loop:
     58 	wfe
     59 	b loop
     60 
     61 	// void init_clock(void);
     62 	// init_clock initialize xosc and set it as the system clock
     63 	// clock freq is 133MHz.
     64 	.global init_xosc
     65 init_xosc:
     66 	// setup xosc
     67 	ldr r3, xosc_base
     68 	mov r0, #47 // start up delay for 12MHz rosc (xosc?)
     69 	str r0, [r3, #0xc] // XOSC: STARTUP
     70 	ldr r0, =(0xfab << 12 | 0xaa0)
     71 	str r0, [r3, #0] // XOSC: CTRL
     72 wait_xosc:
     73 	ldr r0, [r3, #0x4] // XOSC: STATUS
     74 	lsr r0, r0, #31 // STABLE bit
     75 	beq wait_xosc
     76 	bx lr
     77 
     78 	// void init_pll(void);
     79 	// init_pll setups pll_sys in 133MHz.
     80 	.global init_pll
     81 init_pll:
     82 	ldr r3, pll_sys_base
     83 	// set feedback divider
     84 	mov r0, #133
     85 	str r0, [r3, #0x8] // PLL: FBDIV_INT
     86 	// power on pll and vco
     87 	ldr r0, =(1 << 5 | 1) // VCOPD | PD
     88 	ldr r1, atomic_clr
     89 	add r1, r1, #0x4
     90 	str r0, [r3, r1] // PLL: PWR
     91 	// wait vco to lock
     92 wait_vco:
     93 	ldr r0, [r3, #0] // PLL: CS
     94 	lsl r0, r0, #31
     95 	beq wait_vco
     96 	// setup post dividers
     97 	ldr r0, =(4 << 16 | 3 << 12)
     98 	str r0, [r3, #0xc] // PLL: PRIM
     99 	// power on post divider
    100 	mov r0, #8 // POSTDIVPD
    101 	str r0, [r3, r1] // PLL: PWR
    102 	bx lr
    103 
    104 	// void set_system_clock_to_pll_sys(void);
    105 	// set_system_clock_to_pll_sys sets system clock to pll_sys
    106 	.global set_system_clock_to_pll_sys
    107 set_system_clock_to_pll_sys:
    108 	// set system clock clksrc_pll_sys
    109 	ldr r3, clocks_base
    110 	ldr r0, =(0x0 << 5 | 0x1)
    111 	str r0, [r3, #0x3c] // CLOCKS: CLK_SYS_CTRL
    112 	bx lr
    113 
    114 	// void enable_clock_peri(void);
    115 	// enable_clock_peri enables clk_peri and set it to clk_sys
    116 	.global enable_clock_peri
    117 enable_clock_peri:
    118 	mov r0, #1
    119 	lsl r0, r0, #11
    120 	ldr r3, clocks_base
    121 	str r0, [r3, #0x48] // CLOCKS: CLK_PERI_CTRL
    122 	bx lr
    123 
    124 	// void unreset(reset_bit subsystems);
    125 	// unreset unresets subsystems.
    126 	// subsystems is bitwise or.
    127 	// To unreset uart, clk_peri must be enabled beforehand.
    128 	.global unreset
    129 unreset:
    130 	ldr r3, resets_base
    131 	ldr r1, atomic_clr
    132 	str r0, [r3, r1] // RESETS: RESET
    133 unreset_chk:
    134 	ldr r1, [r3, #0x8] // RESETS: RESET_DONE
    135 	bic r0, r1
    136 	bne unreset_chk
    137 	bx lr
    138 
    139 	.global mains
    140 mains:
    141 	push {lr}
    142 
    143 	// set gpio functions
    144 	ldr r3, io_bank0_base
    145 	// set pins 0 and 1 for uart
    146 	mov r0, #2 // uart0
    147 	mov r1, #0x4
    148 	str r0, [r3, r1] // IO_BANK0: GPIO0_CTRL
    149 	mov r1, #0xc
    150 	str r0, [r3, r1] // IO_BANK0: GPIO1_CTRL
    151 	// set pins 24 and 25 to SIO for led blink.
    152 	mov r0, #5 // sio
    153 	mov r1, #0xc4
    154 	str r0, [r3, r1] // IO_BANK0: GPIO24_CTRL
    155 	mov r1, #0xcc
    156 	str r0, [r3, r1] // IO_BANK0: GPIO24_CTRL
    157 
    158 	// enable sio output
    159 	ldr r3, sio_base
    160 	mov r0, #0b11
    161 	lsl r0, r0, #24
    162 	str r0, [r3, #0x24] // SIO: GPIO_OE
    163 
    164 	// setup uart0
    165 	ldr r3, uart0_base
    166 	// set baudrate 115200
    167 	// BDRI = 72, BDRF = 0.157 (10 / 64)
    168 	mov r0, #72
    169 	str r0, [r3, #0x24] // UART: UARTIBRD
    170 	mov r0, #10
    171 	str r0, [r3, #0x28] // UART: UARTFBRD
    172 	// enable uart0
    173 	mov r0, #1 // UARTEN
    174 	ldr r1, atomic_set
    175 	add r1, r1, #0x30
    176 	str r0, [r3, r1] // UART: UARTCR
    177 	// enable FIFO and set format
    178 	ldr r0, =(3 << 5 | 1 << 4) // WLEN = 8, FEN = 1
    179 	str r0, [r3, #0x2c] // UART: UARTLCR_H
    180 
    181 	// enable uart interrupt in cpu
    182 	ldr r4, ppb_base
    183 	mov r5, #0xe1
    184 	lsl r5, #8
    185 	mov r0, #1
    186 	lsl r0, #20
    187 	str r0, [r4, r5] // M0PLUS: NVIC_ISER
    188 
    189 	// enable uart interrupt in uart0 subsystem
    190 	ldr r1, uart0_base
    191 	mov r2, #(1 << 6 | 1 << 4) // RTIM | RXIM
    192 	str r2, [r1, #0x38] // UART: UARTIMSC
    193 	// set fifo level to 0
    194 	mov r2, #0
    195 	str r2, [r1, #0x34] // UART: UARTIFLS
    196 
    197 	pop {pc}
    198 
    199 // functions
    200 
    201 	// print r0 in hex for debugging.
    202 printh:
    203 	push {r4, r5, r6, r7, lr}
    204 	mov r4, r0
    205 	mov r5, #28
    206 	mov r6, #0xf
    207 	mov r7, #10
    208 printh_loop:
    209 	mov r0, r4
    210 	lsr r0, r0, r5
    211 	and r0, r0, r6
    212 	sub r1, r0, r7
    213 	blt digi
    214 	add r0, r0, #('a' - 10)
    215 	b alpha
    216 digi:
    217 	add r0, r0, #'0'
    218 alpha:
    219 	bl putbyte
    220 	sub r5, r5, #4
    221 	bge printh_loop
    222 	pop {r4, r5, r6, r7, pc}
    223 
    224 	// putbyte sends a byte specified by r0 to uart0.
    225 	// It busy-waits for the buffer to become available.
    226 putbyte:
    227 	ldr r3, uart0_base
    228 	mov r1, #1
    229 	lsl r1, r1, #5 // TXFF
    230 txff:
    231 	ldr r2, [r3, #0x18] // UART: UARTFR
    232 	tst r1, r2
    233 	bne txff
    234 	mov r1, #0xff
    235 	and r0, r0, r1
    236 	str r0, [r3, #0] // UART: UARTDR
    237 	bx lr
    238 
    239 	// getbyte reads a byte from uart0 and returns it on r0
    240 	// It busy-waits for a data.
    241 getbyte:
    242 	ldr r3, uart0_base
    243 	mov r1, #1
    244 	lsl r1, r1, #4 // RXFE
    245 rxfe:
    246 	ldr r2, [r3, #0x18] // UART: UARTFR
    247 	tst r1, r2
    248 	bne rxfe
    249 	ldr r0, [r3, #0] // UART: UARTDR
    250 	mov r1, #0xff
    251 	and r0, r0, r1
    252 	bx lr
    253 
    254 // The following functions make no side effects and
    255 // can be used anywhare without pushing and popping
    256 // registers.
    257 
    258 	// pled prints register content with 2 leds on the pins 24 and 25, lsb first.
    259 pled:
    260 	push {r0, r1, r2, r3, r4, r5, r6, lr}
    261 	mov r4, r0
    262 	mov r5, #32
    263 	mov r6, #1
    264 pled_loop:
    265 	tst r4, r6
    266 	beq pled0
    267 	bl bled1
    268 	b pled1
    269 pled0:
    270 	bl bled0
    271 pled1:
    272 	lsr r4, r4, #1
    273 	sub r5, r5, #1
    274 	bne pled_loop
    275 	pop {r0, r1, r2, r3, r4, r5, r6, pc}
    276 
    277 	// bled0 blinks the led on the pin 24 once.
    278 	.global bled0
    279 bled0:
    280 	push {r0, r1, r2, r3, lr}
    281 	mov r0, #1
    282 	lsl r0, r0, #24
    283 	bl bled
    284 	pop {r0, r1, r2, r3, pc}
    285 
    286 	// bled1 blinks the led on the pin 25 once.
    287 bled1:
    288 	push {r0, r1, r2, r3, lr}
    289 	mov r0, #1
    290 	lsl r0, r0, #25
    291 	bl bled
    292 	pop {r0, r1, r2, r3, pc}
    293 
    294 	// bled blinks the led on the pin specified by r0 once.
    295 bled:
    296 	push {r0, r1, r2, r3, r4, r5, lr}
    297 	ldr r4, sio_base
    298 	mov r5, r0
    299 	str r5, [r4, #0x10] // SIO: GPIO_OUT_XOR
    300 	bl delay
    301 	str r5, [r4, #0x18] // SIO: GPIO_OUT_XOR
    302 	bl delay
    303 	pop {r0, r1, r2, r3, r4, r5, pc}
    304 	
    305 	// delay delays for a moment by counting down a register.
    306 delay:
    307 	push {r0}
    308 	mov r0, #1
    309 	lsl r0, r0, #24
    310 delay_loop:
    311 	sub r0, r0, #1
    312 	bne delay_loop
    313 	pop {r0}
    314 	bx lr
    315 
    316 	// uart_interrupt_handler echos the data arrived at uart0
    317 uart_interrupt_handler:
    318 	push {lr}
    319 	bl getbyte
    320 	bl putbyte
    321 	pop {pc}
    322 
    323 	.align 2
    324 literals:
    325 	.ltorg
    326 atomic_set:
    327 	.word 0x00002000
    328 atomic_clr:
    329 	.word 0x00003000
    330 clocks_base:
    331 	.word 0x40008000
    332 resets_base:
    333 	.word 0x4000c000
    334 io_bank0_base:
    335 	.word 0x40014000
    336 xosc_base:
    337 	.word 0x40024000
    338 pll_sys_base:
    339 	.word 0x40028000
    340 uart0_base:
    341 	.word 0x40034000
    342 sio_base:
    343 	.word 0xd0000000
    344 ppb_base:
    345 	.word 0xe0000000