|
2
|
1 /*========================================================================== |
|
|
2 // |
|
|
3 // hal_misc.c |
|
|
4 // |
|
|
5 // HAL miscellaneous functions |
|
|
6 // |
|
|
7 //========================================================================== |
|
|
8 //####COPYRIGHTBEGIN#### |
|
|
9 // |
|
|
10 // ------------------------------------------- |
|
|
11 // The contents of this file are subject to the Cygnus eCos Public License |
|
|
12 // Version 1.0 (the "License"); you may not use this file except in |
|
|
13 // compliance with the License. You may obtain a copy of the License at |
|
|
14 // http://sourceware.cygnus.com/ecos |
|
|
15 // |
|
|
16 // Software distributed under the License is distributed on an "AS IS" |
|
|
17 // basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the |
|
|
18 // License for the specific language governing rights and limitations under |
|
|
19 // the License. |
|
|
20 // |
|
|
21 // The Original Code is eCos - Embedded Cygnus Operating System, released |
|
|
22 // September 30, 1998. |
|
|
23 // |
|
|
24 // The Initial Developer of the Original Code is Cygnus. Portions created |
|
|
25 // by Cygnus are Copyright (C) 1998,1999 Cygnus Solutions. All Rights Reserved. |
|
|
26 // ------------------------------------------- |
|
|
27 // |
|
|
28 //####COPYRIGHTEND#### |
|
|
29 //========================================================================== |
|
|
30 //#####DESCRIPTIONBEGIN#### |
|
|
31 // |
|
|
32 // Author(s): nickg, gthomas |
|
|
33 // Contributors: nickg, gthomas |
|
|
34 // Date: 1999-02-20 |
|
|
35 // Purpose: HAL miscellaneous functions |
|
|
36 // Description: This file contains miscellaneous functions provided by the |
|
|
37 // HAL. |
|
|
38 // |
|
|
39 //####DESCRIPTIONEND#### |
|
|
40 // |
|
|
41 //=========================================================================*/ |
|
|
42 |
|
|
43 #include <pkgconf/hal.h> |
|
|
44 #include <pkgconf/hal_arm.h> |
|
|
45 #ifdef CYGPKG_KERNEL |
|
|
46 #include <pkgconf/kernel.h> |
|
|
47 #endif |
|
|
48 |
|
|
49 #include <cyg/infra/cyg_type.h> |
|
|
50 #include <cyg/infra/cyg_trac.h> // tracing macros |
|
|
51 #include <cyg/infra/cyg_ass.h> // assertion macros |
|
|
52 |
|
|
53 #include <cyg/hal/hal_arch.h> // HAL header |
|
|
54 #include <cyg/hal/hal_intr.h> // HAL header |
|
|
55 |
|
|
56 externC void diag_printf(const char *fmt, ...); |
|
|
57 |
|
|
58 /*------------------------------------------------------------------------*/ |
|
|
59 /* First level C exception handler. */ |
|
|
60 |
|
|
61 externC void __handle_exception (void); |
|
|
62 |
|
|
63 externC HAL_SavedRegisters *_hal_registers; |
|
|
64 extern void *__mem_fault_handler; |
|
|
65 |
|
|
66 #ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS |
|
|
67 /* Force exception handling into the GDB stubs. This is done by taking over |
|
|
68 the exception vectors while executing in the stubs. This allows for the |
|
|
69 debugged program to handle exceptions itself, except while the GDB |
|
|
70 processing is underway. The only vector that can't be handled this way |
|
|
71 is the illegal instruction vector which is used for breakpoint/single-step |
|
|
72 and must be maintained by the stubs at all times. |
|
|
73 */ |
|
|
74 |
|
|
75 #define ARM_VECTORS 8 |
|
|
76 extern unsigned long vectors[]; // exception vectors as defined by the stubs |
|
|
77 static unsigned long *hardware_vectors = (unsigned long *)0x20; |
|
|
78 static unsigned long hold_vectors[ARM_VECTORS]; |
|
|
79 |
|
|
80 static int exception_level; |
|
|
81 |
|
|
82 static void |
|
|
83 __take_over_debug_traps(void) |
|
|
84 { |
|
|
85 int i; |
|
|
86 for (i = 0; i < ARM_VECTORS; i++) { |
|
|
87 hold_vectors[i] = hardware_vectors[i]; |
|
|
88 hardware_vectors[i] = vectors[i]; |
|
|
89 } |
|
|
90 } |
|
|
91 |
|
|
92 static void |
|
|
93 __restore_debug_traps(void) |
|
|
94 { |
|
|
95 int i; |
|
|
96 for (i = 0; i < ARM_VECTORS; i++) { |
|
|
97 hardware_vectors[i] = hold_vectors[i]; |
|
|
98 } |
|
|
99 } |
|
|
100 #endif |
|
|
101 |
|
|
102 void |
|
|
103 exception_handler(HAL_SavedRegisters *regs) |
|
|
104 { |
|
|
105 #ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS |
|
|
106 if (__mem_fault_handler && |
|
|
107 regs->vector == CYGNUM_HAL_EXCEPTION_DATA_ACCESS) { |
|
|
108 regs->pc = (unsigned long)__mem_fault_handler; |
|
|
109 return; // Caught an exception inside stubs |
|
|
110 } |
|
|
111 |
|
|
112 if (++exception_level == 1) __take_over_debug_traps(); |
|
|
113 |
|
|
114 _hal_registers = regs; |
|
|
115 __handle_exception(); |
|
|
116 |
|
|
117 // We should decode the vector and pass a more appropriate |
|
|
118 // value as the second argument. For now we simply pass a |
|
|
119 // pointer to the saved registers. We should also divert |
|
|
120 // breakpoint and other debug vectors into the debug stubs. |
|
|
121 |
|
|
122 if (--exception_level == 0) __restore_debug_traps(); |
|
|
123 |
|
|
124 #elif defined(CYGPKG_KERNEL_EXCEPTIONS) |
|
|
125 |
|
|
126 cyg_hal_deliver_exception( regs->vector, (CYG_ADDRWORD)regs ); |
|
|
127 |
|
|
128 #else |
|
|
129 |
|
|
130 CYG_FAIL("Exception!!!"); |
|
|
131 |
|
|
132 #endif |
|
|
133 |
|
|
134 return; |
|
|
135 } |
|
|
136 |
|
|
137 /*------------------------------------------------------------------------*/ |
|
|
138 /* C++ support - run initial constructors */ |
|
|
139 |
|
|
140 #ifdef CYGSEM_HAL_STOP_CONSTRUCTORS_ON_FLAG |
|
|
141 cyg_bool cyg_hal_stop_constructors; |
|
|
142 #endif |
|
|
143 |
|
|
144 typedef void (*pfunc) (void); |
|
|
145 extern pfunc __CTOR_LIST__[]; |
|
|
146 extern pfunc __CTOR_END__[]; |
|
|
147 |
|
|
148 void |
|
|
149 cyg_hal_invoke_constructors (void) |
|
|
150 { |
|
|
151 |
|
|
152 #ifdef CYGSEM_HAL_STOP_CONSTRUCTORS_ON_FLAG |
|
|
153 static pfunc *p = &__CTOR_END__[-1]; |
|
|
154 |
|
|
155 cyg_hal_stop_constructors = 0; |
|
|
156 for (; p >= __CTOR_LIST__; p--) { |
|
|
157 (*p) (); |
|
|
158 if (cyg_hal_stop_constructors) { |
|
|
159 p--; |
|
|
160 break; |
|
|
161 } |
|
|
162 } |
|
|
163 #else |
|
|
164 pfunc *p; |
|
|
165 |
|
|
166 for (p = &__CTOR_END__[-1]; p >= __CTOR_LIST__; p--) |
|
|
167 (*p) (); |
|
|
168 #endif |
|
|
169 } |
|
|
170 |
|
|
171 /*------------------------------------------------------------------------*/ |
|
|
172 /* default ISR */ |
|
|
173 |
|
|
174 externC cyg_uint32 |
|
|
175 hal_default_isr(CYG_ADDRWORD vector, CYG_ADDRWORD data) |
|
|
176 { |
|
|
177 CYG_TRACE1(true, "Interrupt: %d", vector); |
|
|
178 diag_printf("Spurious Interrupt!!! - vector: %d, data: %x\n", vector, |
|
|
179 data); |
|
|
180 CYG_FAIL("Spurious Interrupt!!!"); |
|
|
181 return 0; |
|
|
182 } |
|
|
183 |
|
|
184 /*------------------------------------------------------------------------*/ |
|
|
185 /* Idle thread action */ |
|
|
186 |
|
|
187 void |
|
|
188 hal_idle_thread_action( cyg_uint32 count ) |
|
|
189 { |
|
|
190 } |
|
|
191 |
|
|
192 /*-------------------------------------------------------------------------*/ |
|
|
193 /* Misc functions */ |
|
|
194 |
|
|
195 #ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS |
|
|
196 /* This function will generate a breakpoint exception. It is used at the |
|
|
197 beginning of a program to sync up with a debugger and can be used |
|
|
198 otherwise as a quick means to stop program execution and "break" into |
|
|
199 the debugger. */ |
|
|
200 |
|
|
201 void |
|
|
202 breakpoint(void) |
|
|
203 { |
|
|
204 HAL_BREAKPOINT(breakinst); |
|
|
205 } |
|
|
206 |
|
|
207 |
|
|
208 /* This function returns the opcode for a 'trap' instruction. */ |
|
|
209 |
|
|
210 unsigned long |
|
|
211 __break_opcode (void) |
|
|
212 { |
|
|
213 return HAL_BREAKINST; |
|
|
214 } |
|
|
215 #endif |
|
|
216 |
|
|
217 int |
|
|
218 hal_lsbindex(int mask) |
|
|
219 { |
|
|
220 int i; |
|
|
221 for (i = 0; i < 32; i++) { |
|
|
222 if (mask & (1<<i)) return (i); |
|
|
223 } |
|
|
224 return (-1); |
|
|
225 } |
|
|
226 |
|
|
227 int |
|
|
228 hal_msbindex(int mask) |
|
|
229 { |
|
|
230 int i; |
|
|
231 for (i = 32; i >= 0; i++) { |
|
|
232 if (mask & (1<<i)) return (i); |
|
|
233 } |
|
|
234 return (-1); |
|
|
235 } |
|
|
236 |
|
|
237 void |
|
|
238 dump_buf_with_offset(unsigned char *p, |
|
|
239 int s, |
|
|
240 unsigned char *base) |
|
|
241 { |
|
|
242 int i, c; |
|
|
243 if ((unsigned int)s > (unsigned int)p) { |
|
|
244 s = (unsigned int)s - (unsigned int)p; |
|
|
245 } |
|
|
246 while (s > 0) { |
|
|
247 if (base) { |
|
|
248 diag_printf("%08X: ", (int)p - (int)base); |
|
|
249 } else { |
|
|
250 diag_printf("%08X: ", p); |
|
|
251 } |
|
|
252 for (i = 0; i < 16; i++) { |
|
|
253 if (i < s) { |
|
|
254 diag_printf("%02X", p[i] & 0xFF); |
|
|
255 } else { |
|
|
256 diag_printf(" "); |
|
|
257 } |
|
|
258 if ((i % 2) == 1) diag_printf(" "); |
|
|
259 if ((i % 8) == 7) diag_printf(" "); |
|
|
260 } |
|
|
261 diag_printf(" |"); |
|
|
262 for (i = 0; i < 16; i++) { |
|
|
263 if (i < s) { |
|
|
264 c = p[i] & 0xFF; |
|
|
265 if ((c < 0x20) || (c >= 0x7F)) c = '.'; |
|
|
266 } else { |
|
|
267 c = ' '; |
|
|
268 } |
|
|
269 diag_printf("%c", c); |
|
|
270 } |
|
|
271 diag_printf("|\n"); |
|
|
272 s -= 16; |
|
|
273 p += 16; |
|
|
274 } |
|
|
275 } |
|
|
276 |
|
|
277 void |
|
|
278 dump_buf(unsigned char *p, int s) |
|
|
279 { |
|
|
280 dump_buf_with_offset(p, s, 0); |
|
|
281 } |
|
|
282 |
|
|
283 #ifdef CYGHWR_HAL_ARM_DUMP_EXCEPTIONS |
|
|
284 void |
|
|
285 dump_frame(unsigned char *frame) |
|
|
286 { |
|
|
287 HAL_SavedRegisters *rp = (HAL_SavedRegisters *)frame; |
|
|
288 int i; |
|
|
289 dump_buf(frame, 128); |
|
|
290 diag_printf("Registers:\n"); |
|
|
291 for (i = 0; i <= 10; i++) { |
|
|
292 if ((i == 0) || (i == 6)) diag_printf("R%d: ", i); |
|
|
293 diag_printf("%08X ", rp->d[i]); |
|
|
294 if ((i == 5) || (i == 10)) diag_printf("\n"); |
|
|
295 } |
|
|
296 diag_printf("FP: %08X, SP: %08X, LR: %08X, PC: %08X, PSR: %08X\n", |
|
|
297 rp->fp, rp->sp, rp->lr, rp->pc, rp->cpsr); |
|
|
298 } |
|
|
299 #endif |
|
|
300 |
|
|
301 #if 0 |
|
|
302 void |
|
|
303 show_frame_in(HAL_SavedRegisters *frame) |
|
|
304 { |
|
|
305 int old; |
|
|
306 HAL_DISABLE_INTERRUPTS(old); |
|
|
307 diag_printf("[IN] IRQ Frame:\n"); |
|
|
308 dump_frame((unsigned char *)frame); |
|
|
309 HAL_RESTORE_INTERRUPTS(old); |
|
|
310 } |
|
|
311 |
|
|
312 void |
|
|
313 show_frame_out(HAL_SavedRegisters *frame) |
|
|
314 { |
|
|
315 int old; |
|
|
316 HAL_DISABLE_INTERRUPTS(old); |
|
|
317 diag_printf("[OUT] IRQ Frame:\n"); |
|
|
318 dump_frame((unsigned char *)frame); |
|
|
319 HAL_RESTORE_INTERRUPTS(old); |
|
|
320 } |
|
|
321 #endif |
|
|
322 |
|
|
323 #ifdef CYGHWR_HAL_ARM_DUMP_EXCEPTIONS |
|
|
324 // Debug routines |
|
|
325 void undefined_instruction(HAL_SavedRegisters *frame) |
|
|
326 { |
|
|
327 int old; |
|
|
328 HAL_DISABLE_INTERRUPTS(old); |
|
|
329 diag_printf("[UNDEFINED INSTRUCTION] Frame:\n"); |
|
|
330 dump_frame((unsigned char *)frame); |
|
|
331 HAL_RESTORE_INTERRUPTS(old); |
|
|
332 } |
|
|
333 |
|
|
334 void software_interrupt(HAL_SavedRegisters *frame) |
|
|
335 { |
|
|
336 int old; |
|
|
337 HAL_DISABLE_INTERRUPTS(old); |
|
|
338 diag_printf("[SOFTWARE INTERRUPT] Frame:\n"); |
|
|
339 dump_frame((unsigned char *)frame); |
|
|
340 HAL_RESTORE_INTERRUPTS(old); |
|
|
341 } |
|
|
342 |
|
|
343 void abort_prefetch(HAL_SavedRegisters *frame) |
|
|
344 { |
|
|
345 int old; |
|
|
346 HAL_DISABLE_INTERRUPTS(old); |
|
|
347 diag_printf("[ABORT PREFETCH] Frame:\n"); |
|
|
348 dump_frame((unsigned char *)frame); |
|
|
349 HAL_RESTORE_INTERRUPTS(old); |
|
|
350 } |
|
|
351 |
|
|
352 void abort_data(HAL_SavedRegisters *frame) |
|
|
353 { |
|
|
354 int old; |
|
|
355 HAL_DISABLE_INTERRUPTS(old); |
|
|
356 diag_printf("[ABORT DATA] Frame:\n"); |
|
|
357 dump_frame((unsigned char *)frame); |
|
|
358 HAL_RESTORE_INTERRUPTS(old); |
|
|
359 } |
|
|
360 |
|
|
361 void FIQ(HAL_SavedRegisters *frame) |
|
|
362 { |
|
|
363 int old; |
|
|
364 HAL_DISABLE_INTERRUPTS(old); |
|
|
365 diag_printf("[FIQ] Frame:\n"); |
|
|
366 dump_frame((unsigned char *)frame); |
|
|
367 HAL_RESTORE_INTERRUPTS(old); |
|
|
368 } |
|
|
369 |
|
|
370 void exception_handler_returned(HAL_SavedRegisters *frame) |
|
|
371 { |
|
|
372 int old; |
|
|
373 HAL_DISABLE_INTERRUPTS(old); |
|
|
374 diag_printf("Exception handler returned!\n"); |
|
|
375 dump_frame((unsigned char *)frame); |
|
|
376 HAL_RESTORE_INTERRUPTS(old); |
|
|
377 } |
|
|
378 #endif |
|
|
379 |
|
|
380 /*------------------------------------------------------------------------*/ |
|
|
381 // EOF hal_misc.c |