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