changing circuitry to disable RTC, update initialization to match
[fw/openalt] / boot.s
1 @
2 @  Sample initialization file 
3 @
4         .extern main
5         .extern exit
6
7         .text
8         .code 32
9
10         .align  0
11
12         .extern __bss_beg__
13         .extern __bss_end__
14         .extern __stack_end__
15         .extern __data_beg__
16         .extern __data_end__
17         .extern __data+beg_src__
18
19         .global start
20         .global endless_loop
21
22
23 @  Stack sizes.  These have been determined empirically.  If your interrupt
24 @  routines become more complex or use a lot of dynamically allocated space,
25 @  the IRQ and/or FIQ stacks may been be grown.  The supervisor stack may 
26 @  overflow into the system/user stack as the system is going any initialization,
27 @  before starting the FreeRTOS scheduler.  The scheduler itself needs a small
28 @  amount of supervisor stack space, once it's running.
29 @
30         .set  UND_STACK_SIZE, 0x00000004
31         .set  ABT_STACK_SIZE, 0x00000004
32         .set  FIQ_STACK_SIZE, 0x00000020
33         .set  IRQ_STACK_SIZE, 0X00000100
34         .set  SVC_STACK_SIZE, 0x00000100
35
36 @
37 @  Standard definitions of Mode bits and Interrupt (I & F) flags in PSRs 
38 @
39         .set  MODE_USR, 0x10            @ User Mode 
40         .set  MODE_FIQ, 0x11            @ FIQ Mode 
41         .set  MODE_IRQ, 0x12            @ IRQ Mode 
42         .set  MODE_SVC, 0x13            @ Supervisor Mode 
43         .set  MODE_ABT, 0x17            @ Abort Mode 
44         .set  MODE_UND, 0x1B            @ Undefined Mode 
45         .set  MODE_SYS, 0x1F            @ System Mode 
46
47         .equ  I_BIT, 0x80               @ when I bit is set, IRQ is disabled 
48         .equ  F_BIT, 0x40               @ when F bit is set, FIQ is disabled 
49         .equ  T_BIT, 0x20               @ when T bit is set, THUMB mode is active
50
51 start:
52 _start:
53 _mainCRTStartup:
54 @
55 @  Clear all of memory to 0xe5e5e5e5.  We use this value later to determine
56 @  stack highwater usage.
57 @
58         ldr     r1, .LC3                @ __data_beg__ is start of RAM 
59         ldr     r3, .LC6                @ __stack_end__ is end of RAM
60         sub     r3, r3, r1              @ Length of RAM to set
61         ldr     r2, =0xe5e5e5e5         @ Fill value
62
63 .init_loop:
64         str     r2, [r1], #4            @ Store fill value, r1 += 4
65         subs    r3, r3, #4              @ Length -= 4
66         bgt     .init_loop              @ >= 0, go again
67
68 .end_init_loop:
69
70 @
71 @  Clear BSS. 
72 @
73         ldr     r1, .LC1                @ Start of memory block 
74         ldr     r3, .LC2                @ End of memory block 
75         subs    r3, r3, r1              @ Calculate length of block 
76         beq     .end_clear_loop         @ If 0, nothing to do
77         mov     r2, #0                  @ Fill value
78
79 .clear_loop:
80         strb    r2, [r1], #1            @ Store byte, r1++
81         subs    r3, r3, #1              @ Decrement counter
82         bgt     .clear_loop             @ >= 0, go again
83
84 .end_clear_loop:
85
86 @
87 @  Initialize data.
88 @
89         ldr     r1, .LC3                @ Destination (.data in RAM)
90         ldr     r2, .LC4                @ Source (.data in FLASH)
91         ldr     r3, .LC5                @ End of .data in RAM
92         subs    r3, r3, r1              @ Calculate length of block 
93         beq     .end_set_loop           @ If 0, nothing to do
94
95 .set_loop:
96         ldrb    r4, [r2], #1            @ Get byte from source, r2++
97         strb    r4, [r1], #1            @ Store byte to destination, r1++
98         subs    r3, r3, #1              @ Decrement loop counter
99         bgt     .set_loop               @ >= 0, go again
100
101 .end_set_loop:
102
103 @
104 @  Setup a stack for each mode - note that this only sets up a usable stack
105 @  for system/user, SWI and IRQ modes.   Also each mode is setup with
106 @  interrupts initially disabled. 
107 @
108         ldr   r1, .LC7                      @ Pointer to various values we update
109         ldr   r0, .LC6                      @ Get top of stack space
110         msr   CPSR_c, #MODE_UND|I_BIT|F_BIT @ Undefined Instruction Mode
111         mov   sp, r0                        @ Set undef mode SP
112         str   r0, [r1, #0]                  @ Store this so 'mem map' knows
113
114         sub   r0, r0, #UND_STACK_SIZE       @ Subtract undef stack size for abort stack start
115         msr   CPSR_c, #MODE_ABT|I_BIT|F_BIT @ Abort Mode 
116         mov   sp, r0                        @ Set abort mode SP
117         str   r0, [r1, #4]                  @ Store this so 'mem map' knows
118         str   r0, [r1, #8]                  @ Store this so 'mem map' knows
119
120         sub   r0, r0, #ABT_STACK_SIZE       @ Subtract abort stack size for FIQ stack start
121         msr   CPSR_c, #MODE_FIQ|I_BIT|F_BIT @ FIQ Mode 
122         mov   sp, r0                        @ Set FIQ mode SP
123         str   r0, [r1, #12]                 @ Store this so 'mem map' knows
124         str   r0, [r1, #16]                 @ Store this so 'mem map' knows
125
126         sub   r0, r0, #FIQ_STACK_SIZE       @ Subtract FIQ stack size for IRQ stack start
127         msr   CPSR_c, #MODE_IRQ|I_BIT|F_BIT @ IRQ Mode 
128         mov   sp, r0                        @ Set IRQ mode SP
129         str   r0, [r1, #20]                 @ Store this so 'mem map' knows
130         str   r0, [r1, #24]                 @ Store this so 'mem map' knows
131
132         sub   r0, r0, #IRQ_STACK_SIZE       @ Subtract IRQ stack size for SVC stack start
133         msr   CPSR_c, #MODE_SVC|I_BIT|F_BIT @ Supervisor Mode 
134         mov   sp, r0                        @ Set supervisor mode SP
135         str   r0, [r1, #28]                 @ Store this so 'mem map' knows
136         str   r0, [r1, #32]                 @ Store this so 'mem map' knows
137         sub   r2, r0, #256                  @ MAGIC! FreeRTOS only uses a few bytes of supervisor stack...
138         str   r2, [r1, #48]                 @ ...so tell _sbrk() where heap ends when FreeRTOS running
139
140         sub   r0, r0, #SVC_STACK_SIZE       @ Subtract supervisor stack size for system/user stack start
141         msr   CPSR_c, #MODE_SYS|I_BIT|F_BIT @ System Mode 
142         mov   sp, r0                        @ Set system/user mode SP
143         str   r0, [r1, #36]                 @ Store this so 'mem map' knows
144         str   r0, [r1, #40]                 @ Store this so 'mem map' knows
145
146 @
147 @  We want to start in supervisor mode (probably always, but FreeRTOS demands it)
148 @
149         msr   CPSR_c, #MODE_SVC|I_BIT|F_BIT
150
151 @
152 @  Set argc & argv, initialize newlib, and jump to main
153 @
154         mov     r0, #0                  @ No arguments  
155         mov     r1, #0                  @ No argv either 
156
157         bl      syscallsInit            @ Initialize ./newlib/syscalls.c
158         bl      main                    @ And call good ol' main()
159         b       .                       @ In case main() ever returns
160
161 @
162 @  Indirect words
163 @
164         .align  0
165 .LC1:   .word   __bss_beg__
166 .LC2:   .word   __bss_end__
167 .LC3:   .word   __data_beg__
168 .LC4:   .word   __data_beg_src__
169 .LC5:   .word   __data_end__
170 .LC6:   .word   __stack_end__
171 .LC7:   .word   __stack_beg_und
172
173 @
174 @  Setup vector table.  
175 @
176 .section .startup,"ax"
177          .code 32
178          .align 0
179
180         b       _start                  @ reset - _start               
181         ldr     pc, _undf               @ undefined - _undf            
182         ldr     pc, _swi                @ SWI - _swi                   
183         ldr     pc, _pabt               @ program abort - _pabt        
184         ldr     pc, _dabt               @ data abort - _dabt           
185         nop                             @ reserved                     
186         ldr     pc, [pc, #-0xff0]       @ IRQ - read the VIC           
187         ldr     pc, _fiq                @ FIQ - _fiq                   
188
189 _undf:  .word   __undf                  @ undefined                    
190 _swi:   .word   swiDispatch             @ SWI                          
191 _pabt:  .word   __pabt                  @ program abort                
192 _dabt:  .word   __dabt                  @ data abort                   
193 _fiq:   .word   fiqISR                  @ FIQ                          
194
195 @
196 @  Handlers for undef, program abort and data abort.  They all update
197 @  their respective registers, then reset the system by timing out
198 @  the watchdog (only apparent way to force a hardware reset)
199 @
200 __undf: 
201         ldr     sp, =(__abort_mem+5*4)  @ Set sp_abt to data array with offset (restore later)
202         stmia   sp, {r0-r12}            @ Save first dataset in r0-r12 to array
203         sub     r0, lr, #4              @ Calculate PC value of undef instruction
204         mov     r1, #0                  @ Abort type
205         b       .abtstore               @ Save info, reset system
206
207 __pabt: 
208         ldr     sp, =(__abort_mem+5*4)  @ Set sp_abt to data array with offset (restore later)
209         stmia   sp, {r0-r12}            @ Save first dataset in r0-r12 to array
210         sub     r0, lr, #4              @ Calculate PC value of undef instruction
211         mov     r1, #1                  @ Abort type
212         b       .abtstore               @ Save info, reset system
213
214 __dabt: 
215         ldr     sp, =(__abort_mem+5*4)  @ Set sp_abt to data array with offset (restore later)
216         stmia   sp, {r0-r12}            @ Save first dataset in r0-r12 to array
217         sub     r0, lr, #8              @ Calculate PC value of undef instruction
218         mov     r1, #2                  @ Abort type
219         b       .abtstore               @ Save info, reset system
220
221 @
222 @  Store the abort type.  Then see if the sigil value is set, and if not,
223 @  reset the abort counter to 0.
224 @
225 .abtstore:
226         ldr     r2, =__abort_typ        @ Abort type
227         str     r1, [r2]                @ Store it
228
229         ldr     r2, =__abort_sig        @ Get the sigil address
230         ldr     r4, =ABORT_SIGIL        @ Load sigil value
231         ldr     r3, [r2]                @ Get sigil contents
232         cmp     r3, r4                  @ Sigil set?
233
234         strne   r4, [r2]                @ No, store sigil value
235         ldrne   r2, =__abort_cnt        @ No, load address of abort counter
236         movne   r4, #0                  @ No, Zero for store
237         strne   r4, [r2]                @ No, Clear counter
238
239 @
240 @  Now build up structure of registers and stack (r0 = abort address, r1 = 
241 @  abort type).  This code is based heavily on the work of Roger Lynx, from 
242 @  http://www.embedded.com/shared/printableArticle.jhtml?articleID=192202641
243 @
244         mrs     r5, cpsr                @ Save current mode to R5 for mode switching
245         mrs     r6, spsr                @ spsr_abt = CPSR of dabt originating mode, save to r6 for mode switching
246         mov     r2, r6                  @ Building second dataset: r2 = CPSR of exception
247         tst     r6, #0x0f               @ Test mode of the raised exception
248         orreq   r6, r6, #0x0f           @ If 0, elevate from user mode to system mode
249         msr     cpsr_c, r6              @ Switch out from mode 0x17 (abort) to ...
250         mov     r3, lr                  @ ... dabt generating mode and state
251         mov     r4, sp                  @ ... Get lr (=r3) and sp (=r4)
252         msr     cpsr_c, r5              @ Switch back to mode 0x17 (abort)
253         cmp     r1, #1                  @ Test for prefetch abort
254         moveq   r1, #0                  @ Can't fetch instruction at the abort address
255         ldrne   r1, [r0]                @ r1 = [pc] (dabt)
256         ldr     sp, =__abort_mem        @ Reset sp to arrays starting address
257         stmia   sp, {r0-r4}             @ Save second dataset from r0 to r4
258
259         ldr     r1, =__abort_stk        @ Space where we'll store abort stack
260         mov     r2,#8                   @ Copy 8 stack entries
261 .abtcopy:
262         ldr     r0, [r4], #4            @ Get byte from source, r4 += 4
263         str     r0, [r1], #4            @ Store byte to destination, r1 += 4
264         subs    r2, r2, #1              @ Decrement loop counter
265         bgt     .abtcopy                @ >= 0, go again
266
267         b       .sysreset               @ And reset
268
269 @
270 @  Force a system reset with ye olde watch dogge
271 @
272         .set    SCB_RSIR_MASK, 0x0000000f
273         .set    SCB_RSIR,      0xe01fc180
274         .set    WD_MOD,        0xe0000000
275         .set    WD_TC,         0xe0000004
276         .set    WD_FEED,       0xe0000008
277         .set    WD_MOD_WDEN,   0x00000001
278         .set    WD_MOD_RESET,  0x00000002
279         .set    WD_MOD_TOF,    0x00000004
280         .set    WD_MOD_INT,    0x00000008
281         .set    WD_MOD_MASK,   0x0000000f
282         .set    WD_FEED_FEED1, 0x000000aa
283         .set    WD_FEED_FEED2, 0x00000055
284         .set    ABORT_SIGIL,   0xdeadc0de
285
286 .sysreset:
287         ldr     r1, =__abort_cnt        @ Get the abort counter address
288         ldr     r0, [r1]                @ Load it
289         add     r0, r0, #1              @ Add 1
290         str     r0, [r1]                @ Store it back
291
292 @
293 @  Now enable the watch dog, and go into a loop waiting for a timeout
294 @
295         ldr     r0, =SCB_RSIR_MASK
296         ldr     r1, =SCB_RSIR
297         str     r0, [r1]
298         ldr     r0, =WD_MOD_WDEN | WD_MOD_RESET
299         ldr     r1, =WD_MOD
300         str     r0, [r1]
301         ldr     r0, =120000
302         ldr     r1, =WD_TC
303         str     r0, [r1]
304         ldr     r0, =WD_FEED_FEED1
305         ldr     r1, =WD_FEED
306         str     r0, [r1]
307         ldr     r0, =WD_FEED_FEED2
308         ldr     r1, =WD_FEED
309         str     r0, [r1]
310         b       .
311
312 @
313 @  These are in the .protected space in RAM to make sure that initialization 
314 @  code doesn't overwrite them.  When a data abort or an undefined instruction
315 @  exception occurs, the handlers update the respective locations below.  ORDER
316 @  IS IMPORTANT, THESE ARE MAPPED INTO THE C STRUCTURE abortDat_t in monitor.c
317 @
318         .global __abort_dat
319         .section .protected
320         .align  0
321
322 __abort_dat:  .word 0                   @ Dummy, not used
323 __abort_sig:  .word 0                   @ Sigil to indicate data validity
324 __abort_cnt:  .word 0                   @ Number of times we've aborted
325 __abort_typ:  .word 0                   @ Type of abort (0=undef,1=pabort,2=dabort)
326 __abort_mem:  .space (18 * 4), 0        @ Registers from abort state
327 __abort_stk:  .space (8 * 4), 0         @ 8 stack entries from abort state
328
329 @
330 @  Define globals so application can figure out what stacks are where.
331 @  Keep these in order!  The stack setup code expects it.
332 @
333         .global __stack_beg_und
334         .global __stack_end_und
335         .global __stack_beg_abt
336         .global __stack_end_abt
337         .global __stack_beg_fiq
338         .global __stack_end_fiq
339         .global __stack_beg_irq
340         .global __stack_end_irq
341         .global __stack_beg_svc
342         .global __stack_end_svc
343         .global __stack_beg_sys
344         .global __stack_end_sys
345         .global __heap_max
346         .global __heap_beg
347         .global __heap_end
348         .data
349         .align  0
350
351 __stack_beg_und: .word 0                @ 0
352 __stack_end_und: .word 0                @ 4
353 __stack_beg_abt: .word 0                @ 8
354 __stack_end_abt: .word 0                @ 12
355 __stack_beg_fiq: .word 0                @ 16
356 __stack_end_fiq: .word 0                @ 20
357 __stack_beg_irq: .word 0                @ 24
358 __stack_end_irq: .word 0                @ 28
359 __stack_beg_svc: .word 0                @ 32
360 __stack_end_svc: .word 0                @ 36
361 __stack_beg_sys: .word 0                @ 40
362 __stack_end_sys: .word 0                @ 44
363 __heap_max:      .word 0                @ 48
364 __heap_beg:      .word __heap_beg__
365 __heap_end:      .word __heap_end__
366
367         .end