diff options
Diffstat (limited to 'firmware/target/arm/tcc77x/crt0.S')
-rw-r--r-- | firmware/target/arm/tcc77x/crt0.S | 124 |
1 files changed, 107 insertions, 17 deletions
diff --git a/firmware/target/arm/tcc77x/crt0.S b/firmware/target/arm/tcc77x/crt0.S index e4ecb05a4e..246d02a1d7 100644 --- a/firmware/target/arm/tcc77x/crt0.S +++ b/firmware/target/arm/tcc77x/crt0.S | |||
@@ -29,6 +29,11 @@ | |||
29 | 29 | ||
30 | .section .init.text,"ax",%progbits | 30 | .section .init.text,"ax",%progbits |
31 | 31 | ||
32 | .extern irq | ||
33 | .extern fiq | ||
34 | .extern UIE | ||
35 | .extern main | ||
36 | |||
32 | .global start | 37 | .global start |
33 | 38 | ||
34 | /* Telechips firmware files start with a 32-byte header, as part of the code. */ | 39 | /* Telechips firmware files start with a 32-byte header, as part of the code. */ |
@@ -44,7 +49,8 @@ start: | |||
44 | .word 0 /* Saved entrypoint of original firmware*/ | 49 | .word 0 /* Saved entrypoint of original firmware*/ |
45 | .word 0 /* Location in RAM of the start of our bootloader */ | 50 | .word 0 /* Location in RAM of the start of our bootloader */ |
46 | #else | 51 | #else |
47 | ldr pc, =start_loc /* jump to the main entry point */ | 52 | // ldr pc, =start_loc /* jump to the main entry point */ |
53 | b start_loc | ||
48 | 54 | ||
49 | .word 0xffff0601 /* Unknown magic */ | 55 | .word 0xffff0601 /* Unknown magic */ |
50 | .word 0x3a726556 /* "Ver:" */ | 56 | .word 0x3a726556 /* "Ver:" */ |
@@ -65,21 +71,40 @@ start: | |||
65 | start_loc: | 71 | start_loc: |
66 | 72 | ||
67 | #ifdef BOOTLOADER | 73 | #ifdef BOOTLOADER |
74 | |||
75 | /* | ||
76 | If we are appended to the OF (i.e. dual-booting), do a simple GPIO | ||
77 | button check, and branch to the OF's entry point (saved by mktccboot) | ||
78 | if not active | ||
79 | */ | ||
80 | |||
68 | #ifdef TCCBOOT | 81 | #ifdef TCCBOOT |
69 | #ifdef LOGIK_DAX | ||
70 | mov r0, #0x80000000 | 82 | mov r0, #0x80000000 |
71 | ldr r0, [r0, #0x300] /* Read GPIO A */ | 83 | #ifdef LOGIK_DAX |
84 | ldr r0, [r0, #0x300] /* Hold button is GPIO A, pin 0x2 */ | ||
72 | tst r0, #0x2 | 85 | tst r0, #0x2 |
73 | ldrne pc, [pc, #-28] /* Jump to original firmware if HOLD button not pressed */ | 86 | #elif defined(SANSA_M200) |
87 | ldr r0, [r0, #0x310] /* Hold button is GPIO B, pin 0x200 */ | ||
88 | tst r0, #0x200 | ||
74 | #else | 89 | #else |
75 | #error No bootup key detection implemented for this target | 90 | #error No bootup key detection implemented for this target |
76 | #endif | 91 | #endif |
77 | 92 | ||
78 | /* Copy bootloader to safe area - 0x21000000 (DRAM) */ | 93 | ldrne pc, [pc, #-28] /* Jump to OF if HOLD button not pressed */ |
79 | /* TODO: Adjust this for other targets - DRAM + DRAMSIZE - 0x100000 */ | 94 | #endif /* TCCBOOT */ |
80 | ldr r0, [pc, #-28] | 95 | |
81 | mov r1, #0x20000000 | 96 | /* We are now definitely executing the bootloader, so we relocate to the |
82 | add r1, r1, #0x100000 | 97 | linked address (see boot.lds) - 1MB from the end of DRAM. |
98 | */ | ||
99 | |||
100 | #ifdef TCCBOOT | ||
101 | ldr r0, [pc, #-28] /* mktccboot fills in the load address */ | ||
102 | #else | ||
103 | mov r0, #0x20000000 /* Otherwise, load address is the start of DRAM */ | ||
104 | #endif | ||
105 | mov r1, #0x20000000 /* Destination: 1MB from end of DRAM */ | ||
106 | add r1, r1, #((MEM - 1) * 0x100000) | ||
107 | |||
83 | ldr r2, =_dataend | 108 | ldr r2, =_dataend |
84 | 1: | 109 | 1: |
85 | cmp r2, r1 | 110 | cmp r2, r1 |
@@ -88,16 +113,14 @@ start_loc: | |||
88 | bhi 1b | 113 | bhi 1b |
89 | 114 | ||
90 | ldr pc, =copied_start /* jump to the relocated start_loc: */ | 115 | ldr pc, =copied_start /* jump to the relocated start_loc: */ |
91 | |||
92 | copied_start: | 116 | copied_start: |
93 | #endif | 117 | #endif /* BOOTLOADER */ |
94 | #else | ||
95 | /* We don't use interrupts in the bootloader */ | ||
96 | 118 | ||
97 | /* Set up stack for IRQ mode */ | 119 | /* Set up stack for IRQ mode */ |
98 | mov r0,#0xd2 | 120 | mov r0,#0xd2 |
99 | msr cpsr, r0 | 121 | msr cpsr, r0 |
100 | ldr sp, =irq_stack | 122 | ldr sp, =irq_stack |
123 | |||
101 | /* Set up stack for FIQ mode */ | 124 | /* Set up stack for FIQ mode */ |
102 | mov r0,#0xd1 | 125 | mov r0,#0xd1 |
103 | msr cpsr, r0 | 126 | msr cpsr, r0 |
@@ -110,13 +133,22 @@ copied_start: | |||
110 | mov r0,#0xdb | 133 | mov r0,#0xdb |
111 | msr cpsr, r0 | 134 | msr cpsr, r0 |
112 | ldr sp, =irq_stack | 135 | ldr sp, =irq_stack |
113 | #endif | ||
114 | 136 | ||
115 | /* Switch to supervisor mode */ | 137 | /* Switch to supervisor mode */ |
116 | mov r0,#0xd3 | 138 | mov r0,#0xd3 |
117 | msr cpsr, r0 | 139 | msr cpsr, r0 |
118 | ldr sp, =stackend | 140 | ldr sp, =stackend |
119 | 141 | ||
142 | /* Copy exception handler code to address 0 */ | ||
143 | mov r2, #0x0 | ||
144 | ldr r3, =vectors_start | ||
145 | ldr r4, =vectors_end | ||
146 | 1: | ||
147 | cmp r4, r3 | ||
148 | ldrhi r5, [r3], #4 | ||
149 | strhi r5, [r2], #4 | ||
150 | bhi 1b | ||
151 | |||
120 | /* Initialise bss section to zero */ | 152 | /* Initialise bss section to zero */ |
121 | ldr r2, =_edata | 153 | ldr r2, =_edata |
122 | ldr r3, =_end | 154 | ldr r3, =_end |
@@ -139,9 +171,68 @@ copied_start: | |||
139 | bl main | 171 | bl main |
140 | /* main() should never return */ | 172 | /* main() should never return */ |
141 | 173 | ||
142 | #ifndef BOOTLOADER | 174 | /* Exception handlers. Will be copied to address 0 after memory remapping */ |
143 | /* We don't use interrupts in the bootloader */ | 175 | vectors_start: |
176 | ldr pc, [pc, #24] | ||
177 | ldr pc, [pc, #24] | ||
178 | ldr pc, [pc, #24] | ||
179 | ldr pc, [pc, #24] | ||
180 | ldr pc, [pc, #24] | ||
181 | ldr pc, [pc, #24] | ||
182 | ldr pc, [pc, #24] | ||
183 | ldr pc, [pc, #24] | ||
184 | |||
185 | /* Exception vectors */ | ||
186 | .global vectors | ||
187 | vectors: | ||
188 | .word start | ||
189 | .word undef_instr_handler | ||
190 | .word software_int_handler | ||
191 | .word prefetch_abort_handler | ||
192 | .word data_abort_handler | ||
193 | .word reserved_handler | ||
194 | .word irq_handler | ||
195 | .word fiq_handler | ||
196 | vectors_end: | ||
197 | |||
198 | .text | ||
199 | |||
200 | /* All illegal exceptions call into UIE with exception address as first | ||
201 | parameter. This is calculated differently depending on which exception | ||
202 | we're in. Second parameter is exception number, used for a string lookup | ||
203 | in UIE. | ||
204 | */ | ||
205 | undef_instr_handler: | ||
206 | mov r0, lr | ||
207 | mov r1, #0 | ||
208 | b UIE | ||
144 | 209 | ||
210 | /* We run supervisor mode most of the time, and should never see a software | ||
211 | exception being thrown. Perhaps make it illegal and call UIE? | ||
212 | */ | ||
213 | software_int_handler: | ||
214 | reserved_handler: | ||
215 | movs pc, lr | ||
216 | |||
217 | prefetch_abort_handler: | ||
218 | sub r0, lr, #4 | ||
219 | mov r1, #1 | ||
220 | b UIE | ||
221 | |||
222 | data_abort_handler: | ||
223 | sub r0, lr, #8 | ||
224 | mov r1, #2 | ||
225 | b UIE | ||
226 | |||
227 | irq_handler: | ||
228 | stmfd sp!, {r0-r3, r12, lr} | ||
229 | bl irq | ||
230 | ldmfd sp!, {r0-r3, r12, lr} | ||
231 | subs pc, lr, #4 | ||
232 | |||
233 | /* Align stacks to cache line boundary */ | ||
234 | .balign 16 | ||
235 | |||
145 | /* 256 words of IRQ stack */ | 236 | /* 256 words of IRQ stack */ |
146 | .space 256*4 | 237 | .space 256*4 |
147 | irq_stack: | 238 | irq_stack: |
@@ -150,4 +241,3 @@ irq_stack: | |||
150 | .space 256*4 | 241 | .space 256*4 |
151 | fiq_stack: | 242 | fiq_stack: |
152 | 243 | ||
153 | #endif | ||