1 /*==========================================================================
5 // HAL miscellaneous functions
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.
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.
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
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.
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.
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.
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####
43 // Author(s): nickg, gthomas
44 // Contributors: nickg, gthomas
46 // Purpose: HAL miscellaneous functions
47 // Description: This file contains miscellaneous functions provided by the
50 //####DESCRIPTIONEND####
52 //=========================================================================*/
54 #include <pkgconf/hal.h>
55 #include <pkgconf/hal_arm.h>
57 #include <pkgconf/kernel.h>
60 #include <pkgconf/cygmon.h>
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
67 #include <cyg/hal/hal_arch.h> // HAL header
68 #include <cyg/hal/hal_intr.h> // HAL header
70 #include <cyg/infra/diag.h>
72 /*------------------------------------------------------------------------*/
73 /* First level C exception handler. */
75 externC void __handle_exception (void);
77 externC HAL_SavedRegisters *_hal_registers;
78 #ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
79 externC void* volatile __mem_fault_handler;
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
95 extern unsigned long vectors[]; // exception vectors as defined by the stubs
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;
103 __take_over_debug_traps(void)
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];
112 __restore_debug_traps(void)
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];
117 #endif // !CYGPKG_CYGMON
121 exception_handler(HAL_SavedRegisters *regs)
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
136 #if defined(CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS) && !defined(CYGPKG_CYGMON)
137 if (++exception_level == 1) __take_over_debug_traps();
139 _hal_registers = regs;
140 __handle_exception();
142 if (--exception_level == 0) __restore_debug_traps();
144 #elif defined(CYGPKG_KERNEL_EXCEPTIONS)
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.
151 cyg_hal_deliver_exception( regs->vector, (CYG_ADDRWORD)regs );
155 CYG_FAIL("Exception!!!");
162 void hal_spurious_IRQ(HAL_SavedRegisters *regs) CYGBLD_ATTRIB_WEAK;
164 hal_spurious_IRQ(HAL_SavedRegisters *regs)
166 #if defined(CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS)
167 exception_handler(regs);
169 CYG_FAIL("Spurious interrupt!!");
173 /*------------------------------------------------------------------------*/
174 /* C++ support - run initial constructors */
176 #ifdef CYGSEM_HAL_STOP_CONSTRUCTORS_ON_FLAG
177 cyg_bool cyg_hal_stop_constructors;
180 typedef void (*pfunc) (void);
181 extern pfunc __CTOR_LIST__[];
182 extern pfunc __CTOR_END__[];
185 cyg_hal_invoke_constructors (void)
187 #ifdef CYGSEM_HAL_STOP_CONSTRUCTORS_ON_FLAG
188 static pfunc *p = &__CTOR_END__[-1];
190 cyg_hal_stop_constructors = 0;
191 for (; p >= __CTOR_LIST__; p--) {
193 if (cyg_hal_stop_constructors) {
201 for (p = &__CTOR_END__[-1]; p >= __CTOR_LIST__; p--)
206 /*------------------------------------------------------------------------*/
207 /* Architecture default ISR */
210 hal_arch_default_isr(CYG_ADDRWORD vector, CYG_ADDRWORD data)
212 CYG_TRACE1(true, "Interrupt: %d", vector);
214 CYG_FAIL("Spurious Interrupt!!!");
218 /*-------------------------------------------------------------------------*/
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
230 HAL_BREAKPOINT(_breakinst);
234 /* This function returns the opcode for a 'trap' instruction. */
237 __break_opcode (void)
239 return HAL_BREAKINST;
244 hal_lsbindex(int mask)
247 for (i = 0; i < 32; i++) {
248 if (mask & (1<<i)) return (i);
254 hal_msbindex(int mask)
257 for (i = 31; i >= 0; i--) {
258 if (mask & (1<<i)) return (i);
263 #ifdef CYGHWR_HAL_ARM_DUMP_EXCEPTIONS
265 dump_frame(unsigned char *frame)
267 HAL_SavedRegisters *rp = (HAL_SavedRegisters *)frame;
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");
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);
283 show_frame_in(HAL_SavedRegisters *frame)
286 HAL_DISABLE_INTERRUPTS(old);
287 diag_printf("[IN] IRQ Frame:\n");
288 dump_frame((unsigned char *)frame);
289 HAL_RESTORE_INTERRUPTS(old);
293 show_frame_out(HAL_SavedRegisters *frame)
296 HAL_DISABLE_INTERRUPTS(old);
297 diag_printf("[OUT] IRQ Frame:\n");
298 dump_frame((unsigned char *)frame);
299 HAL_RESTORE_INTERRUPTS(old);
303 #ifdef CYGHWR_HAL_ARM_DUMP_EXCEPTIONS
305 void cyg_hal_report_undefined_instruction(HAL_SavedRegisters *frame)
308 HAL_DISABLE_INTERRUPTS(old);
309 diag_printf("[UNDEFINED INSTRUCTION] Frame:\n");
310 dump_frame((unsigned char *)frame);
311 HAL_RESTORE_INTERRUPTS(old);
314 void cyg_hal_report_software_interrupt(HAL_SavedRegisters *frame)
317 HAL_DISABLE_INTERRUPTS(old);
318 diag_printf("[SOFTWARE INTERRUPT] Frame:\n");
319 dump_frame((unsigned char *)frame);
320 HAL_RESTORE_INTERRUPTS(old);
323 void cyg_hal_report_abort_prefetch(HAL_SavedRegisters *frame)
326 HAL_DISABLE_INTERRUPTS(old);
327 diag_printf("[ABORT PREFETCH] Frame:\n");
328 dump_frame((unsigned char *)frame);
329 HAL_RESTORE_INTERRUPTS(old);
332 void cyg_hal_report_abort_data(HAL_SavedRegisters *frame)
335 HAL_DISABLE_INTERRUPTS(old);
336 diag_printf("[ABORT DATA] Frame:\n");
337 dump_frame((unsigned char *)frame);
338 HAL_RESTORE_INTERRUPTS(old);
341 void cyg_hal_report_exception_handler_returned(HAL_SavedRegisters *frame)
344 HAL_DISABLE_INTERRUPTS(old);
345 diag_printf("Exception handler returned!\n");
346 dump_frame((unsigned char *)frame);
347 HAL_RESTORE_INTERRUPTS(old);
351 /*------------------------------------------------------------------------*/