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"