rp2040

RP2040 Programming without SDK
Log | Files | Refs

main.s (6370B)


      1 .cpu cortex-m0plus
      2 .thumb
      3 
      4 	.global vectors
      5 vectors:
      6 	.word 0x20040000 // 0 initial SP
      7 	.word reset+1  // 1 entry point
      8 	.word reset+1  // 2
      9 	.word reset+1  // 3
     10 	.word reset+1  // 4
     11 	.word reset+1  // 5
     12 	.word reset+1  // 6
     13 	.word reset+1  // 7
     14 	.word reset+1  // 8
     15 	.word reset+1  // 9
     16 	.word reset+1  // 10
     17 	.word int_svcall+1  // 11 svcall
     18 	.word reset+1  // 12
     19 	.word reset+1  // 13
     20 	.word reset+1  // 14
     21 	.word int_systick+1  // 15 systick
     22 	.word int_alarm+1  // 16 alarm_0
     23 
     24 	.section .text
     25 reset:
     26 	// unreset gpio, pll_sys, timer
     27 	ldr r0, =(1 << 21 | 1 << 12 | 1 << 5) // | timer | pll_sys | io_bank0
     28 	ldr r3, resets_base
     29 	ldr r1, atomic_clr
     30 	str r0, [r3, r1] // RESETS: RESET
     31 unreset_chk:
     32 	ldr r1, [r3, #0x8] // RESETS: RESET_DONE
     33 	bic r0, r1
     34 	bne unreset_chk
     35 
     36 	// set gpio functions
     37 	ldr r3, io_bank0_base
     38 	mov r0, #2 // uart0
     39 	mov r1, #0x4
     40 	str r0, [r3, r1] // IO_BANK0: GPIO0_CTRL
     41 	mov r1, #0xc
     42 	str r0, [r3, r1] // IO_BANK0: GPIO1_CTRL
     43 
     44 	// setup xosc
     45 	ldr r3, xosc_base
     46 	mov r0, #47 // start up delay for 12MHz rosc (xosc?)
     47 	str r0, [r3, #0xc] // XOSC: STARTUP
     48 	ldr r0, =(0xfab << 12 | 0xaa0)
     49 	str r0, [r3, #0] // XOSC: CTRL
     50 wait_xosc:
     51 	ldr r0, [r3, #0x4] // XOSC: STATUS
     52 	lsr r0, r0, #31 // STABLE bit
     53 	beq wait_xosc
     54 
     55 	// setup pll_sys 133MHz
     56 	ldr r3, pll_sys_base
     57 	// set feedback divider
     58 	mov r0, #133
     59 	str r0, [r3, #0x8] // PLL: FBDIV_INT
     60 	// power on pll and vco
     61 	ldr r0, =(1 << 5 | 1) // VCOPD | PD
     62 	ldr r1, atomic_clr
     63 	add r1, r1, #0x4
     64 	str r0, [r3, r1] // PLL: PWR
     65 	// wait vco to lock
     66 wait_vco:
     67 	ldr r0, [r3, #0] // PLL: CS
     68 	lsl r0, r0, #31
     69 	beq wait_vco
     70 	// setup post dividers
     71 	ldr r0, =(4 << 16 | 3 << 12)
     72 	str r0, [r3, #0xc] // PLL: PRIM
     73 	// power on post divider
     74 	mov r0, #8 // POSTDIVPD
     75 	str r0, [r3, r1] // PLL: PWR
     76 
     77 	// setup clock
     78 	ldr r3, clocks_base
     79 	// set system clock clksrc_pll_sys
     80 	ldr r0, =(0x0 << 5 | 0x1)
     81 	str r0, [r3, #0x3c] // CLOCKS: CLK_SYS_CTRL
     82 	// enable clk_peri
     83 	mov r0, #1
     84 	lsl r0, r0, #11
     85 	str r0, [r3, #0x48] // CLOCKS: CLK_PERI_CTRL
     86 	// setup clk_ref
     87 	mov r0, #0x2
     88 	str r0, [r3, #0x30] // CLOCKS: CLK_REF_CTRL
     89 
     90 	// unreset uart0
     91 	ldr r0, =(1 << 22)
     92 	ldr r3, resets_base
     93 	ldr r1, atomic_clr
     94 	str r0, [r3, r1] // RESETS: RESET
     95 unreset_chk1:
     96 	ldr r1, [r3, #0x8] // RESETS: RESET_DONE
     97 	bic r0, r1
     98 	bne unreset_chk1
     99 
    100 	// disable rosc
    101 	ldr r3, rosc_base
    102 	ldr r0, =0xd1e000
    103 	str r0, [r3, #0] // ROSC: CTRL
    104 
    105 	// setup uart0
    106 	ldr r3, uart0_base
    107 	// set baudrate 115200
    108 	// BDRI = 72, BDRF = 0.157 (10 / 64)
    109 	mov r0, #72
    110 	str r0, [r3, #0x24] // UART: UARTIBRD
    111 	mov r0, #10
    112 	str r0, [r3, #0x28] // UART: UARTFBRD
    113 	// enable uart0
    114 	mov r0, #1 // UARTEN
    115 	ldr r1, atomic_set
    116 	add r1, r1, #0x30
    117 	str r0, [r3, r1] // UART: UARTCR
    118 	// enable FIFO and set format
    119 	ldr r0, =(3 << 5 | 1 << 4) // WLEN = 8, FEN = 1
    120 	str r0, [r3, #0x2c] // UART: UARTLCR_H
    121 
    122 	// enable interrupt
    123 	ldr r3, ppb_base
    124 	// enable timer_irq_0
    125 	ldr r1, =0xe100
    126 	mov r0, #1
    127 	str r0, [r3, r1] // M0PLUS: NVIC_ISER
    128 
    129 	// setup timer
    130 	ldr r3, timer_base
    131 	// enable alarm_0 interrupt
    132 	mov r0, #1 // ALARM_0
    133 	str r0, [r3, #0x38] // TIMER: INTE
    134 	// set timer
    135 	ldr r0, =0x20000 // 
    136 	bl set_alarm
    137 
    138 loop:
    139 	ldr r0, =message
    140 	bl puts
    141 	wfi
    142 	b loop
    143 
    144 // functions
    145 
    146 int_svcall:
    147 	push {r4, lr}
    148 	mov r4, lr
    149 	mov r0, #'s'
    150 	bl putbyte
    151 	mov r0, #'v'
    152 	bl putbyte
    153 	mov r0, #'c'
    154 	bl putbyte
    155 	mov r0, #'a'
    156 	bl putbyte
    157 	mov r0, #'l'
    158 	bl putbyte
    159 	mov r0, #'l'
    160 	bl putbyte
    161 	mov r0, r4
    162 	bl printh
    163 	mov r0, #'\r'
    164 	bl putbyte
    165 	mov r0, #'\n'
    166 	bl putbyte
    167 	pop {r4, pc}
    168 
    169 int_systick:
    170 	push {lr}
    171 	mov r0, #'\r'
    172 	bl putbyte
    173 	ldr r1, =0x20000000
    174 	ldr r0, [r1, #0]
    175 	add r0, #1
    176 	str r0, [r1, #0]
    177 	bl printh
    178 	mov r0, #'\n'
    179 	bl putbyte
    180 	pop {pc}
    181 
    182 int_alarm:
    183 	mov r0, sp
    184 	push {lr}
    185 	// clear interrupt
    186 	ldr r3, timer_base
    187 	ldr r2, atomic_clr
    188 	mov r1, #0x34
    189 	add r1, r1, r2
    190 	mov r0, #1
    191 	str r0, [r3, r1] // TIMER: INTR
    192 	// reset timer
    193 	ldr r0, =0x20000 // 1 sec
    194 	bl set_alarm
    195 	pop {pc}
    196 
    197 	// set_alarm sets alarm_0 to fire after r0 us.
    198 set_alarm:
    199 	ldr r3, timer_base
    200 	ldr r1, [r3, #0x28] // TIMER: TIMERAWL
    201 	add r0, r1
    202 	str r0, [r3, #0x10] // TIMER: ALARM0
    203 	bx lr
    204 
    205 	// print r0 in hex for debugging.
    206 printh:
    207 	push {r4, r5, r6, r7, lr}
    208 	mov r4, r0
    209 	mov r5, #28
    210 	mov r6, #0xf
    211 	mov r7, #10
    212 printh_loop:
    213 	mov r0, r4
    214 	lsr r0, r0, r5
    215 	and r0, r0, r6
    216 	sub r1, r0, r7
    217 	blt digi
    218 	add r0, r0, #('a' - 10)
    219 	b alpha
    220 digi:
    221 	add r0, r0, #'0'
    222 alpha:
    223 	bl putbyte
    224 	sub r5, r5, #4
    225 	bge printh_loop
    226 	pop {r4, r5, r6, r7, pc}
    227 
    228 	// puts prints null terminated string starting at r0.
    229 puts:
    230 	push {r4, lr}
    231 	mov r4, r0
    232 puts_loop:
    233 	ldrb r0, [r4, #0]
    234 	cmp r0, #0
    235 	beq puts_end
    236 	bl putbyte
    237 	add r4, #1
    238 	b puts_loop
    239 puts_end:
    240 	pop {r4, pc}
    241 
    242 putbyte:
    243 	ldr r3, uart0_base
    244 	mov r1, #1
    245 	lsl r1, r1, #5 // TXFF
    246 txff:
    247 	ldr r2, [r3, #0x18] // UART: UARTFR
    248 	tst r1, r2
    249 	bne txff
    250 	mov r1, #0xff
    251 	and r0, r0, r1
    252 	str r0, [r3, #0] // UART: UARTDR
    253 	bx lr
    254 
    255 getbyte:
    256 	ldr r3, uart0_base
    257 	mov r1, #1
    258 	lsl r1, r1, #4 // RXFE
    259 rxfe:
    260 	ldr r2, [r3, #0x18] // UART: UARTFR
    261 	tst r1, r2
    262 	bne rxfe
    263 	ldr r0, [r3, #0] // UART: UARTDR
    264 	mov r1, #0xff
    265 	and r0, r0, r1
    266 	bx lr
    267 
    268 // The following functions make no side effects and
    269 // can be used anywhare without pushing and popping
    270 // registers.
    271 
    272 	// Print register content with 2 leds, lsb first.
    273 pled:
    274 	push {r0, r1, r2, r3, r4, r5, r6, lr}
    275 	mov r4, r0
    276 	mov r5, #32
    277 	mov r6, #1
    278 pled_loop:
    279 	tst r4, r6
    280 	beq pled0
    281 	bl bled1
    282 	b pled1
    283 pled0:
    284 	bl bled0
    285 pled1:
    286 	lsr r4, r4, #1
    287 	sub r5, r5, #1
    288 	bne pled_loop
    289 	pop {r0, r1, r2, r3, r4, r5, r6, pc}
    290 
    291 bled0:
    292 	push {r0, r1, r2, r3, lr}
    293 	mov r0, #1
    294 	lsl r0, r0, #24
    295 	bl bled
    296 	pop {r0, r1, r2, r3, pc}
    297 
    298 bled1:
    299 	push {r0, r1, r2, r3, lr}
    300 	mov r0, #1
    301 	lsl r0, r0, #25
    302 	bl bled
    303 	pop {r0, r1, r2, r3, pc}
    304 
    305 bled:
    306 	push {r0, r1, r2, r3, r4, r5, lr}
    307 	ldr r4, sio_base
    308 	mov r5, r0
    309 	str r5, [r4, #0x10] // SIO: GPIO_OUT_XOR
    310 	bl delay
    311 	str r5, [r4, #0x18] // SIO: GPIO_OUT_XOR
    312 	bl delay
    313 	pop {r0, r1, r2, r3, r4, r5, pc}
    314 	
    315 delay:
    316 	push {r0}
    317 	mov r0, #1
    318 	lsl r0, r0, #20
    319 delay_loop:
    320 	sub r0, r0, #1
    321 	bne delay_loop
    322 	pop {r0}
    323 	bx lr
    324 
    325 	.align 2
    326 literals:
    327 	.ltorg
    328 atomic_set:
    329 	.word 0x00002000
    330 atomic_clr:
    331 	.word 0x00003000
    332 syscfg_base:
    333 	.word 0x40004000
    334 clocks_base:
    335 	.word 0x40008000
    336 resets_base:
    337 	.word 0x4000c000
    338 io_bank0_base:
    339 	.word 0x40014000
    340 xosc_base:
    341 	.word 0x40024000
    342 pll_sys_base:
    343 	.word 0x40028000
    344 uart0_base:
    345 	.word 0x40034000
    346 timer_base:
    347 	.word 0x40054000
    348 rosc_base:
    349 	.word 0x40060000
    350 sio_base:
    351 	.word 0xd0000000
    352 ppb_base:
    353 	.word 0xe0000000
    354 message:
    355 	.asciz "Hello, World!\r\n"