2 @ Sample initialization file
17 .extern __data+beg_src__
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.
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
37 @ Standard definitions of Mode bits and Interrupt (I & F) flags in PSRs
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
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
55 @ Clear all of memory to 0xe5e5e5e5. We use this value later to determine
56 @ stack highwater usage.
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
64 str r2, [r1], #4 @ Store fill value, r1 += 4
65 subs r3, r3, #4 @ Length -= 4
66 bgt .init_loop @ >= 0, go again
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
80 strb r2, [r1], #1 @ Store byte, r1++
81 subs r3, r3, #1 @ Decrement counter
82 bgt .clear_loop @ >= 0, go again
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
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
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.
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
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
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
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
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
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
147 @ We want to start in supervisor mode (probably always, but FreeRTOS demands it)
149 msr CPSR_c, #MODE_SVC|I_BIT|F_BIT
152 @ Set argc & argv, initialize newlib, and jump to main
154 mov r0, #0 @ No arguments
155 mov r1, #0 @ No argv either
157 bl syscallsInit @ Initialize ./newlib/syscalls.c
158 bl main @ And call good ol' main()
159 b . @ In case main() ever returns
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
174 @ Setup vector table.
176 .section .startup,"ax"
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
186 ldr pc, [pc, #-0xff0] @ IRQ - read the VIC
187 ldr pc, _fiq @ FIQ - _fiq
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
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)
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
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
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
222 @ Store the abort type. Then see if the sigil value is set, and if not,
223 @ reset the abort counter to 0.
226 ldr r2, =__abort_typ @ Abort type
227 str r1, [r2] @ Store it
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?
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
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
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
259 ldr r1, =__abort_stk @ Space where we'll store abort stack
260 mov r2,#8 @ Copy 8 stack entries
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
267 b .sysreset @ And reset
270 @ Force a system reset with ye olde watch dogge
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
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
293 @ Now enable the watch dog, and go into a loop waiting for a timeout
295 ldr r0, =SCB_RSIR_MASK
298 ldr r0, =WD_MOD_WDEN | WD_MOD_RESET
304 ldr r0, =WD_FEED_FEED1
307 ldr r0, =WD_FEED_FEED2
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
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
330 @ Define globals so application can figure out what stacks are where.
331 @ Keep these in order! The stack setup code expects it.
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
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__