]> git.kernelconcepts.de Git - karo-tx-redboot.git/blob - packages/hal/arm/arch/v2_0/src/hal_misc.c
ba1303465b2bf82aa1269b817797d40369738f32
[karo-tx-redboot.git] / packages / hal / arm / arch / v2_0 / src / hal_misc.c
1 /*==========================================================================
2 //
3 //      hal_misc.c
4 //
5 //      HAL miscellaneous functions
6 //
7 //==========================================================================
8 //####ECOSGPLCOPYRIGHTBEGIN####
9 // -------------------------------------------
10 // This file is part of eCos, the Embedded Configurable Operating System.
11 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
12 //
13 // eCos is free software; you can redistribute it and/or modify it under
14 // the terms of the GNU General Public License as published by the Free
15 // Software Foundation; either version 2 or (at your option) any later version.
16 //
17 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
18 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
19 // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
20 // for more details.
21 //
22 // You should have received a copy of the GNU General Public License along
23 // with eCos; if not, write to the Free Software Foundation, Inc.,
24 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
25 //
26 // As a special exception, if other files instantiate templates or use macros
27 // or inline functions from this file, or you compile this file and link it
28 // with other works to produce a work based on this file, this file does not
29 // by itself cause the resulting work to be covered by the GNU General Public
30 // License. However the source code for this file must still be made available
31 // in accordance with section (3) of the GNU General Public License.
32 //
33 // This exception does not invalidate any other reasons why a work based on
34 // this file might be covered by the GNU General Public License.
35 //
36 // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
37 // at http://sources.redhat.com/ecos/ecos-license/
38 // -------------------------------------------
39 //####ECOSGPLCOPYRIGHTEND####
40 //==========================================================================
41 //#####DESCRIPTIONBEGIN####
42 //
43 // Author(s):    nickg, gthomas
44 // Contributors: nickg, gthomas
45 // Date:         1999-02-20
46 // Purpose:      HAL miscellaneous functions
47 // Description:  This file contains miscellaneous functions provided by the
48 //               HAL.
49 //
50 //####DESCRIPTIONEND####
51 //
52 //=========================================================================*/
53
54 #include <pkgconf/hal.h>
55 #include <pkgconf/hal_arm.h>
56 #ifdef CYGPKG_KERNEL
57 #include <pkgconf/kernel.h>
58 #endif
59 #ifdef CYGPKG_CYGMON
60 #include <pkgconf/cygmon.h>
61 #endif
62
63 #include <cyg/infra/cyg_type.h>
64 #include <cyg/infra/cyg_trac.h>         // tracing macros
65 #include <cyg/infra/cyg_ass.h>          // assertion macros
66
67 #include <cyg/hal/hal_arch.h>           // HAL header
68 #include <cyg/hal/hal_intr.h>           // HAL header
69
70 #include <cyg/infra/diag.h>
71
72 /*------------------------------------------------------------------------*/
73 /* First level C exception handler.                                       */
74
75 externC void __handle_exception (void);
76
77 externC HAL_SavedRegisters *_hal_registers;
78 #ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
79 externC void* volatile __mem_fault_handler;
80 #endif
81
82
83 #ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
84 /* Force exception handling into the GDB stubs.  This is done by taking over
85    the exception vectors while executing in the stubs.  This allows for the
86    debugged program to handle exceptions itself, except while the GDB
87    processing is underway.  The only vector that can't be handled this way
88    is the illegal instruction vector which is used for breakpoint/single-step
89    and must be maintained by the stubs at all times.
90    Note: the interrupt vectors are _not_ preempted as the stubs probably can't
91    handle them properly.
92 */
93
94 #define ARM_VECTORS 8
95 extern unsigned long vectors[];  // exception vectors as defined by the stubs
96
97 #if !defined(CYGPKG_CYGMON)
98 static unsigned long *hardware_vectors = (unsigned long *)0x20;
99 static unsigned long hold_vectors[ARM_VECTORS];
100 static int exception_level;
101
102 static void
103 __take_over_debug_traps(void)
104 {
105     hold_vectors[CYGNUM_HAL_VECTOR_ABORT_PREFETCH] = hardware_vectors[CYGNUM_HAL_VECTOR_ABORT_PREFETCH];
106     hardware_vectors[CYGNUM_HAL_VECTOR_ABORT_PREFETCH] = vectors[CYGNUM_HAL_VECTOR_ABORT_PREFETCH];
107     hold_vectors[CYGNUM_HAL_VECTOR_ABORT_DATA] = hardware_vectors[CYGNUM_HAL_VECTOR_ABORT_DATA];
108     hardware_vectors[CYGNUM_HAL_VECTOR_ABORT_DATA] = vectors[CYGNUM_HAL_VECTOR_ABORT_DATA];
109 }
110
111 static void
112 __restore_debug_traps(void)
113 {
114     hardware_vectors[CYGNUM_HAL_VECTOR_ABORT_PREFETCH] = hold_vectors[CYGNUM_HAL_VECTOR_ABORT_PREFETCH];
115     hardware_vectors[CYGNUM_HAL_VECTOR_ABORT_DATA] = hold_vectors[CYGNUM_HAL_VECTOR_ABORT_DATA];
116 }
117 #endif // !CYGPKG_CYGMON
118 #endif
119
120 void
121 exception_handler(HAL_SavedRegisters *regs)
122 {
123     // Special case handler for code which has chosen to take care
124     // of data exceptions (i.e. code which expects them to happen)
125     // This is common in discovery code, e.g. checking for a particular
126     // device which may generate an exception when probing if the
127     // device is not present
128 #ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
129     if (__mem_fault_handler && 
130         regs->vector == CYGNUM_HAL_EXCEPTION_DATA_ACCESS) {
131         regs->pc = (unsigned long)__mem_fault_handler;
132         return; // Caught an exception inside stubs        
133     }
134 #endif
135
136 #if defined(CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS) && !defined(CYGPKG_CYGMON)
137     if (++exception_level == 1) __take_over_debug_traps();
138
139     _hal_registers = regs;
140     __handle_exception();
141
142     if (--exception_level == 0) __restore_debug_traps();
143
144 #elif defined(CYGPKG_KERNEL_EXCEPTIONS)
145
146     // We should decode the vector and pass a more appropriate
147     // value as the second argument. For now we simply pass a
148     // pointer to the saved registers. We should also divert
149     // breakpoint and other debug vectors into the debug stubs.
150
151     cyg_hal_deliver_exception( regs->vector, (CYG_ADDRWORD)regs );
152
153 #else
154
155     CYG_FAIL("Exception!!!");
156     
157 #endif    
158     
159     return;
160 }
161
162 void hal_spurious_IRQ(HAL_SavedRegisters *regs) CYGBLD_ATTRIB_WEAK;
163 void
164 hal_spurious_IRQ(HAL_SavedRegisters *regs)
165 {
166 #if defined(CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS)
167     exception_handler(regs);
168 #else
169     CYG_FAIL("Spurious interrupt!!");
170 #endif    
171 }
172
173 /*------------------------------------------------------------------------*/
174 /* C++ support - run initial constructors                                 */
175
176 #ifdef CYGSEM_HAL_STOP_CONSTRUCTORS_ON_FLAG
177 cyg_bool cyg_hal_stop_constructors;
178 #endif
179
180 typedef void (*pfunc) (void);
181 extern pfunc __CTOR_LIST__[];
182 extern pfunc __CTOR_END__[];
183
184 void
185 cyg_hal_invoke_constructors (void)
186 {
187 #ifdef CYGSEM_HAL_STOP_CONSTRUCTORS_ON_FLAG
188     static pfunc *p = &__CTOR_END__[-1];
189     
190     cyg_hal_stop_constructors = 0;
191     for (; p >= __CTOR_LIST__; p--) {
192         (*p) ();
193         if (cyg_hal_stop_constructors) {
194             p--;
195             break;
196         }
197     }
198 #else
199     pfunc *p;
200
201     for (p = &__CTOR_END__[-1]; p >= __CTOR_LIST__; p--)
202         (*p) ();
203 #endif
204 }
205
206 /*------------------------------------------------------------------------*/
207 /* Architecture default ISR                                               */
208
209 externC cyg_uint32
210 hal_arch_default_isr(CYG_ADDRWORD vector, CYG_ADDRWORD data)
211 {
212     CYG_TRACE1(true, "Interrupt: %d", vector);
213
214     CYG_FAIL("Spurious Interrupt!!!");
215     return 0;
216 }
217
218 /*-------------------------------------------------------------------------*/
219 /* Misc functions                                                          */
220
221 #ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
222 /* This function will generate a breakpoint exception.  It is used at the
223    beginning of a program to sync up with a debugger and can be used
224    otherwise as a quick means to stop program execution and "break" into
225    the debugger. */
226
227 void
228 breakpoint(void)
229 {
230     HAL_BREAKPOINT(_breakinst);
231 }
232
233
234 /* This function returns the opcode for a 'trap' instruction.  */
235
236 unsigned long
237 __break_opcode (void)
238 {
239     return HAL_BREAKINST;
240 }
241 #endif
242
243 int
244 hal_lsbindex(int mask)
245 {
246     int i;
247     for (i = 0;  i < 32;  i++) {
248       if (mask & (1<<i)) return (i);
249     }
250     return (-1);
251 }
252
253 int
254 hal_msbindex(int mask)
255 {
256     int i;
257     for (i = 31;  i >= 0;  i--) {
258       if (mask & (1<<i)) return (i);
259     }
260     return (-1);
261 }
262
263 #ifdef  CYGHWR_HAL_ARM_DUMP_EXCEPTIONS
264 void
265 dump_frame(unsigned char *frame)
266 {
267     HAL_SavedRegisters *rp = (HAL_SavedRegisters *)frame;
268     int i;
269     diag_dump_buf(frame, 128);
270     diag_printf("Registers:\n");
271     for (i = 0;  i <= 10;  i++) {
272         if ((i == 0) || (i == 6)) diag_printf("R%d: ", i);
273         diag_printf("%08X ", rp->d[i]);
274         if ((i == 5) || (i == 10)) diag_printf("\n");
275     }
276     diag_printf("FP: %08X, SP: %08X, LR: %08X, PC: %08X, PSR: %08X\n",
277                 rp->fp, rp->sp, rp->lr, rp->pc, rp->cpsr);
278 }
279 #endif
280
281 #if 0
282 void
283 show_frame_in(HAL_SavedRegisters *frame)
284 {
285     int old;
286     HAL_DISABLE_INTERRUPTS(old);
287     diag_printf("[IN] IRQ Frame:\n");
288     dump_frame((unsigned char *)frame);
289     HAL_RESTORE_INTERRUPTS(old);
290 }
291
292 void
293 show_frame_out(HAL_SavedRegisters *frame)
294 {
295     int old;
296     HAL_DISABLE_INTERRUPTS(old);
297     diag_printf("[OUT] IRQ Frame:\n");
298     dump_frame((unsigned char *)frame);
299     HAL_RESTORE_INTERRUPTS(old);
300 }
301 #endif
302
303 #ifdef  CYGHWR_HAL_ARM_DUMP_EXCEPTIONS
304 // Debug routines
305 void cyg_hal_report_undefined_instruction(HAL_SavedRegisters *frame)
306 {
307     int old;
308     HAL_DISABLE_INTERRUPTS(old);
309     diag_printf("[UNDEFINED INSTRUCTION] Frame:\n");
310     dump_frame((unsigned char *)frame);
311     HAL_RESTORE_INTERRUPTS(old);
312 }
313
314 void cyg_hal_report_software_interrupt(HAL_SavedRegisters *frame)
315 {
316     int old;
317     HAL_DISABLE_INTERRUPTS(old);
318     diag_printf("[SOFTWARE INTERRUPT] Frame:\n");
319     dump_frame((unsigned char *)frame);
320     HAL_RESTORE_INTERRUPTS(old);
321 }
322
323 void cyg_hal_report_abort_prefetch(HAL_SavedRegisters *frame)
324 {
325     int old;
326     HAL_DISABLE_INTERRUPTS(old);
327     diag_printf("[ABORT PREFETCH] Frame:\n");
328     dump_frame((unsigned char *)frame);    
329     HAL_RESTORE_INTERRUPTS(old);
330 }
331
332 void cyg_hal_report_abort_data(HAL_SavedRegisters *frame)
333 {
334     int old;
335     HAL_DISABLE_INTERRUPTS(old);
336     diag_printf("[ABORT DATA] Frame:\n");
337     dump_frame((unsigned char *)frame);
338     HAL_RESTORE_INTERRUPTS(old);
339 }
340
341 void cyg_hal_report_exception_handler_returned(HAL_SavedRegisters *frame)
342 {    
343     int old;
344     HAL_DISABLE_INTERRUPTS(old);
345     diag_printf("Exception handler returned!\n");
346     dump_frame((unsigned char *)frame);
347     HAL_RESTORE_INTERRUPTS(old);
348 }
349 #endif
350
351 /*------------------------------------------------------------------------*/
352 // EOF hal_misc.c