1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
|
/* Sample initialization file */
.extern main
.extern exit
.extern AT91F_LowLevelInit
.extern pio_irq_isr_value
.extern ssc_tx_pending
.text
.code 32
.align 0
.extern __stack_end__
.extern __bss_beg__
.extern __bss_end__
.extern __data_beg__
.extern __data_end__
.extern __data+beg_src__
.global start
.global endless_loop
/* Stack Sizes */
.set UND_STACK_SIZE, 0x00000004
.set ABT_STACK_SIZE, 0x00000004
.set FIQ_STACK_SIZE, 0x00000400
.set IRQ_STACK_SIZE, 0X00000400
.set SVC_STACK_SIZE, 0x00000400
/* Standard definitions of Mode bits and Interrupt (I & F) flags in PSRs */
.set MODE_USR, 0x10 /* User Mode */
.set MODE_FIQ, 0x11 /* FIQ Mode */
.set MODE_IRQ, 0x12 /* IRQ Mode */
.set MODE_SVC, 0x13 /* Supervisor Mode */
.set MODE_ABT, 0x17 /* Abort Mode */
.set MODE_UND, 0x1B /* Undefined Mode */
.set MODE_SYS, 0x1F /* System Mode */
.equ I_BIT, 0x80 /* when I bit is set, IRQ is disabled */
.equ F_BIT, 0x40 /* when F bit is set, FIQ is disabled */
.equ AT91C_BASE_AIC, (0xFFFFF000)
.equ AT91C_BASE_MC, (0xFFFFFF00)
.equ AT91C_BASE_PIOA, 0xFFFFF400
.equ AT91C_BASE_TC0, 0xFFFA0000
.equ AT91C_BASE_SSC, 0xFFFD4000
.equ SSC_CR, 0x0
.equ SSC_RCMR, 0x10
.equ SSC_CR_TXEN, 0x100
.equ AT91C_TC_SWTRG, (1 << 2)
.equ AT91C_TC_CLKEN, (1 << 0)
.equ PIO_DATA, (1 << 27)
.equ PIO_SSC_TF, (1 << 15)
.equ PIOA_SODR, 0x30
.equ PIOA_CODR, 0x34
.equ PIOA_PDSR, 0x3c
.equ PIOA_IDR, 0x44
.equ PIOA_ISR, 0x4c
.equ TC_CCR, 0x00
.equ AIC_EOICR, (304)
.equ PIO_LED1, (1 << 25)
.equ PIO_LED2, (1 << 12)
.equ MC_RCR, 0xFFFFFF00
.equ AIC_ISCR, (0x12C)
.equ PIO_SECONDARY_IRQ, 31
.equ PIO_SECONDARY_IRQ_BIT, (1 << PIO_SECONDARY_IRQ)
/* FIQ latency is approx 1us. At 13.56 MHz carrier frequency this means that
* 13.56 cycles of the carrier have passed when the FIQ kicks in and this is
* the amount that CV0 should be loaded to. (Round up) */
.equ TC0_FRAME_OFFSET, 9
start:
_start:
_mainCRTStartup:
/* Setup a stack for each mode - note that this only sets up a usable stack
for system/user, SWI and IRQ modes. Also each mode is setup with
interrupts initially disabled. */
ldr r0, .LC6
msr CPSR_c, #MODE_UND|I_BIT|F_BIT /* Undefined Instruction Mode */
mov sp, r0
sub r0, r0, #UND_STACK_SIZE
msr CPSR_c, #MODE_ABT|I_BIT|F_BIT /* Abort Mode */
mov sp, r0
sub r0, r0, #ABT_STACK_SIZE
msr CPSR_c, #MODE_FIQ|I_BIT|F_BIT /* FIQ Mode */
/* Preload registers for FIQ handler */
ldr r10, =AT91C_BASE_PIOA
ldr r12, =AT91C_BASE_TC0
ldr r8, =AT91C_BASE_AIC
mov r9, #AT91C_TC_SWTRG
/*ldr r9, =AT91C_BASE_SSC*/
mov sp, r0
sub r0, r0, #FIQ_STACK_SIZE
msr CPSR_c, #MODE_IRQ|I_BIT|F_BIT /* IRQ Mode */
mov sp, r0
sub r0, r0, #IRQ_STACK_SIZE
msr CPSR_c, #MODE_SVC|I_BIT|F_BIT /* Supervisor Mode */
mov sp, r0
sub r0, r0, #SVC_STACK_SIZE
msr CPSR_c, #MODE_SYS|I_BIT|F_BIT /* System Mode */
mov sp, r0
/* We want to start in supervisor mode. Operation will switch to system
mode when the first task starts. */
msr CPSR_c, #MODE_SVC|I_BIT|F_BIT
bl AT91F_LowLevelInit
/* Clear BSS. */
mov a2, #0 /* Fill value */
mov fp, a2 /* Null frame pointer */
mov r7, a2 /* Null frame pointer for Thumb */
ldr r1, .LC1 /* Start of memory block */
ldr r3, .LC2 /* End of memory block */
subs r3, r3, r1 /* Length of block */
beq .end_clear_loop
mov r2, #0
.clear_loop:
strb r2, [r1], #1
subs r3, r3, #1
bgt .clear_loop
.end_clear_loop:
/* Initialise data. */
ldr r1, .LC3 /* Start of memory block */
ldr r2, .LC4 /* End of memory block */
ldr r3, .LC5
subs r3, r3, r1 /* Length of block */
beq .end_set_loop
.set_loop:
ldrb r4, [r2], #1
strb r4, [r1], #1
subs r3, r3, #1
bgt .set_loop
.end_set_loop:
/* call main */
mov r0, #0 /* no arguments */
mov r1, #0 /* no argv either */
ldr lr, =main
bx lr
endless_loop:
b endless_loop
.align 0
.LC1:
.word __bss_beg__
.LC2:
.word __bss_end__
.LC3:
.word __data_beg__
.LC4:
.word __data_beg_src__
.LC5:
.word __data_end__
.LC6:
.word __stack_end__
/* Setup vector table. Note that undf, pabt, dabt, fiq just execute
a null loop. */
.section .startup,"ax"
.code 32
.align 0
b _start /* reset - _start */
ldr pc, _undf /* undefined - _undf */
ldr pc, _swi /* SWI - _swi */
ldr pc, _pabt /* program abort - _pabt */
ldr pc, _dabt /* data abort - _dabt */
nop /* reserved */
ldr pc, [pc,#-0xF20] /* IRQ - read the AIC */
/* ldr pc, [pc,#-0xF20] /* FIQ - fall through to fiq_handler */
/* Following is modified from openpcd/firmware/src/start/Cstartup_app.S */
#define LED_TRIGGER
.global fiq_handler
.func fiq_handler
my_fiq_handler:
/* code that uses pre-initialized FIQ reg */
/* r8 tmp
r9 AT91C_TC_SWTRG
r10 AT91C_BASE_PIOA
r11 tmp
r12 AT91C_BASE_TC0
r13 stack
r14 lr
*/
#ifdef LED_TRIGGER
mov r11, #PIO_LED1
str r11, [r10, #PIOA_CODR] /* enable LED */
#endif
ldr r8, [r10, #PIOA_ISR]
/* Store the retrieved PIO ISR value into pio_irq_isr_value */
ldr r11, =pio_irq_isr_value
str r8, [r11]
tst r8, #PIO_DATA /* check for PIO_DATA change */
ldrne r11, [r10, #PIOA_PDSR]
tstne r11, #PIO_DATA /* check for PIO_DATA == 1 */
strne r9, [r12, #TC_CCR] /* software trigger */
movne r11, #PIO_DATA
strne r11, [r10, #PIOA_IDR] /* disable further PIO_DATA FIQ */
tst r8, #PIO_SSC_TF /* check for SSC Transmit Frame signal */
ldrne r11, [r10, #PIOA_PDSR]
tstne r11, #PIO_SSC_TF /* check for SSC_TF == 1 */
movne r11, #PIO_SSC_TF
strne r11, [r10, #PIOA_IDR] /* disable further SSC_TF FIQ */
ldrne r11, =ssc_tx_pending
ldrne r8, [r11]
tstne r8, #0x01 /* Check whether a TX is pending */
movne r8, #0x00
strne r8, [r11] /* Set ssc_tx_pending to 0 */
ldrne r11, =AT91C_BASE_SSC
movne r8, #SSC_CR_TXEN
strne r8, [r11, #SSC_CR] /* Write TXEN to SSC_CR, enables tx */
.no_ssc:
/* Trigger PIO_SECONDARY_IRQ */
mov r11, #PIO_SECONDARY_IRQ_BIT
ldr r8, =AT91C_BASE_AIC
str r11, [r8, #AIC_ISCR]
#ifdef LED_TRIGGER
mov r11, #PIO_LED1
str r11, [r10, #PIOA_SODR] /* disable LED */
#endif
/*- Mark the End of Interrupt on the AIC */
ldr r11, =AT91C_BASE_AIC
str r11, [r11, #AIC_EOICR]
/*- Restore the Program Counter using the LR_fiq directly in the PC */
subs pc, lr, #4
.size my_fiq_handler, . - my_fiq_handler
.endfunc
_undf: .word __undf /* undefined */
_swi: .word swi_handler /* SWI */
_pabt: .word __pabt /* program abort */
_dabt: .word __dabt /* data abort */
_fiq: .word __fiq /* FIQ */
__undf: b . /* undefined */
__pabt: b . /* program abort */
__dabt: b . /* data abort */
__fiq: b . /* FIQ */
.end
|