Mercurial > nand-ecoscentric
diff packages/hal/cortexm/arch/current/src/hal_misc.c @ 2580:07fc475e1c28
Add Cortex-M architecture HAL, STM32 variant and STM3210E platform HALs.
Add STM32 serial driver and on-chip flash driver.
Fix some compile problems with dlmalloc.
See the various ChangeLogs for details.
| author | nickg |
|---|---|
| date | Mon, 03 Nov 2008 14:53:50 +0000 |
| parents | |
| children | 9da21501bc5b |
line wrap: on
line diff
new file mode 100644 --- /dev/null +++ b/packages/hal/cortexm/arch/current/src/hal_misc.c @@ -0,0 +1,672 @@ +/*========================================================================== +// +// hal_misc.c +// +// Cortex-M exception vectors +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 2008 eCosCentric Limited. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): nickg +// Date: 2008-07-30 +// +//####DESCRIPTIONEND#### +// +//========================================================================*/ + +#include <pkgconf/hal.h> +#include <pkgconf/hal_cortexm.h> +#ifdef CYGPKG_KERNEL +#include <pkgconf/kernel.h> +#endif + +#include <cyg/infra/diag.h> +#include <cyg/infra/cyg_type.h> +#include <cyg/infra/cyg_trac.h> // tracing macros +#include <cyg/infra/cyg_ass.h> // assertion macros + +#include <cyg/hal/hal_arch.h> // HAL header +#include <cyg/hal/hal_intr.h> // HAL header + +#include <cyg/hal/drv_api.h> + +//========================================================================== + +typedef cyg_uint32 cyg_isr(cyg_uint32 vector, CYG_ADDRWORD data); + +//========================================================================== +// External references + +// VSRs in vectors.S +__externC void hal_default_exception_vsr( void ); +__externC void hal_default_interrupt_vsr( void ); +__externC void hal_default_svc_vsr( void ); +__externC void hal_pendable_svc_vsr( void ); +__externC void hal_switch_state_vsr( void ); + +// HAL and eCos functions +__externC void hal_system_init( void ); +__externC void hal_variant_init( void ); +__externC void hal_platform_init( void ); +__externC void hal_ctrlc_isr_init( void ); +__externC void initialize_stub( void ); +__externC void cyg_hal_invoke_constructors( void ); +__externC void cyg_start( void ); +__externC void cyg_interrupt_post_dsr( CYG_ADDRWORD intr_obj ); +__externC void interrupt_end(cyg_uint32 isr_ret, CYG_ADDRWORD intr, HAL_SavedRegisters *regs ); + +// DATA and BSS locations +__externC cyg_uint32 __ram_data_start; +__externC cyg_uint32 __ram_data_end; +__externC cyg_uint32 __rom_data_start; +__externC cyg_uint32 __bss_start; +__externC cyg_uint32 __bss_end; + +// Scheduler lock +__externC volatile cyg_uint32 cyg_scheduler_sched_lock; + +//========================================================================== +// Interrupt tables + +volatile CYG_ADDRESS hal_interrupt_handlers[CYGNUM_HAL_ISR_COUNT]; +volatile CYG_ADDRWORD hal_interrupt_data [CYGNUM_HAL_ISR_COUNT]; +volatile CYG_ADDRESS hal_interrupt_objects [CYGNUM_HAL_ISR_COUNT]; + +//========================================================================== +// Main entry point +// +// Enter here from reset via slot 1 of VSR table. The stack pointer is +// already set to the value in VSR slot 0, usually the top of internal +// SRAM. + +void hal_reset_vsr( void ) +{ + // Call system init routine. This should do the minimum necessary + // for the rest of the initialization to complete. For example set + // up GPIO, the SRAM, power management etc. This routine is + // usually supplied by the platform HAL. Calls to + // hal_variant_init() and hal_platform_init() later will perform + // the main initialization. + + hal_system_init(); + + // Initialize vector table in base of SRAM. + { + register int i; + +#if !defined(CYG_HAL_STARTUP_RAM) + + // Only install the exception vectors for non-RAM startup. For + // RAM startup we want these to continue to point to the original + // VSRs, which will belong to RedBoot or GDB stubs. + + for( i = 2; i < 15; i++ ) + hal_vsr_table[i] = (CYG_ADDRESS)hal_default_exception_vsr; + +#endif + // Always point SVC and PENDSVC vectors to our local versions + + hal_vsr_table[CYGNUM_HAL_VECTOR_SERVICE] = (CYG_ADDRESS)hal_default_svc_vsr; + hal_vsr_table[CYGNUM_HAL_VECTOR_PENDSV] = (CYG_ADDRESS)hal_pendable_svc_vsr; + + // For all startup type, redirect interrupt vectors to our VSR. + for( i = CYGNUM_HAL_VECTOR_SYS_TICK ; + i < CYGNUM_HAL_VECTOR_SYS_TICK + CYGNUM_HAL_VSR_MAX; + i++ ) + hal_vsr_table[i] = (CYG_ADDRESS)hal_default_interrupt_vsr; + } + + +#if !defined(CYG_HAL_STARTUP_RAM) + + // Ensure that the CPU will use the vector table we have just set + // up. + +# if defined(CYGHWR_HAL_CORTEXM_M3) + + // On M3 parts, the NVIC contains a vector table base register. We + // program this to relocate the vector table base to the base of + // SRAM. + + HAL_WRITE_UINT32( CYGARC_REG_NVIC_BASE+CYGARC_REG_NVIC_VTOR, + CYGARC_REG_NVIC_VTOR_TBLOFF(0)| + CYGARC_REG_NVIC_VTOR_TBLBASE_SRAM ); + +# else + +# error Unknown SRAM/VECTAB remap mechanism + +# endif + + // Use SVC to switch our state to thread mode running on the PSP. + // We don't need to do this for RAM startup since the ROM code + // will have already done it. + + hal_vsr_table[CYGNUM_HAL_VECTOR_SERVICE] = (CYG_ADDRESS)hal_switch_state_vsr; + + __asm__ volatile( "swi" ); + + hal_vsr_table[CYGNUM_HAL_VECTOR_SERVICE] = (CYG_ADDRESS)hal_default_svc_vsr; + +#endif // !defined(CYG_HAL_STARTUP_RAM) + +#if defined(CYG_HAL_STARTUP_ROM) + // Relocate data from ROM to RAM + { + register cyg_uint32 *p, *q; + for( p = &__ram_data_start, q = &__rom_data_start; + p < &__ram_data_end; + p++, q++ ) + *p = *q; + } +#endif + + // Clear BSS + { + register cyg_uint32 *p; + for( p = &__bss_start; p < &__bss_end; p++ ) + *p = 0; + } + + // Initialize interrupt vectors. Set the levels for all interrupts + // to default values. Also set the default priorities of the + // system handlers: all exceptions maximum priority except SVC and + // PendSVC which are lowest priority. + { + register int i; + + HAL_WRITE_UINT32( CYGARC_REG_NVIC_BASE+CYGARC_REG_NVIC_SHPR0, 0x00000000 ); + HAL_WRITE_UINT32( CYGARC_REG_NVIC_BASE+CYGARC_REG_NVIC_SHPR1, 0xFF000000 ); + HAL_WRITE_UINT32( CYGARC_REG_NVIC_BASE+CYGARC_REG_NVIC_SHPR2, 0x00FF0000 ); + + hal_interrupt_handlers[CYGNUM_HAL_INTERRUPT_SYS_TICK] = (CYG_ADDRESS)hal_default_isr; + + for( i = 1; i < CYGNUM_HAL_ISR_COUNT; i++ ) + { + hal_interrupt_handlers[i] = (CYG_ADDRESS)hal_default_isr; + HAL_WRITE_UINT8( CYGARC_REG_NVIC_BASE+CYGARC_REG_NVIC_PR(i-CYGNUM_HAL_INTERRUPT_EXTERNAL), 0x80 ); + } + } + +#if defined(CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS) + // Enable DebugMonitor exceptions. This is needed to enable single + // step. This only has an effect if no external JTAG device is + // attached. + { + CYG_ADDRESS base = CYGARC_REG_DEBUG_BASE; + cyg_uint32 demcr; + + HAL_READ_UINT32( base+CYGARC_REG_DEBUG_DEMCR, demcr ); + demcr |= CYGARC_REG_DEBUG_DEMCR_MON_EN; + HAL_WRITE_UINT32( base+CYGARC_REG_DEBUG_DEMCR, demcr ); + } +#endif + +#if !defined(CYG_HAL_STARTUP_RAM) + // Enable Usage, Bus and Mem fault handlers. Do this for ROM and + // JTAG startups. For RAM startups, this will have already been + // done by the ROM monitor. + { + CYG_ADDRESS base = CYGARC_REG_NVIC_BASE; + cyg_uint32 shcsr; + + HAL_READ_UINT32( base+CYGARC_REG_NVIC_SHCSR, shcsr ); + shcsr |= CYGARC_REG_NVIC_SHCSR_USGFAULTENA; + shcsr |= CYGARC_REG_NVIC_SHCSR_BUSFAULTENA; + shcsr |= CYGARC_REG_NVIC_SHCSR_MEMFAULTENA; + HAL_WRITE_UINT32( base+CYGARC_REG_NVIC_SHCSR, shcsr ); + } +#endif + + // Call variant and platform init routines + hal_variant_init(); + hal_platform_init(); + + // Start up the system clock + HAL_CLOCK_INITIALIZE( CYGNUM_HAL_RTC_PERIOD ); + +#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS + + initialize_stub(); + +#endif + +#if defined(CYGDBG_HAL_DEBUG_GDB_CTRLC_SUPPORT) || \ + defined(CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT) + + hal_ctrlc_isr_init(); + +#endif + + // Run through static constructors + cyg_hal_invoke_constructors(); + + // Finally call into application + cyg_start(); + for(;;); +} + +//========================================================================== +// Handle Exceptions +// +// Exceptions are passed here from the initial VSR. We pass the +// exception on to GDB stubs or the kernel as appropriate. + +__externC void __handle_exception (void); + +__externC HAL_SavedRegisters *_hal_registers; +#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS +__externC void* volatile __mem_fault_handler; +#endif + +void hal_deliver_exception( HAL_SavedRegisters *regs ) +{ + // Special case handler for code which has chosen to take care + // of data exceptions (i.e. code which expects them to happen) + // This is common in discovery code, e.g. checking for a particular + // device which may generate an exception when probing if the + // device is not present +#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS + if (__mem_fault_handler ) + { + regs->u.exception.pc = (unsigned long)__mem_fault_handler; + return; // Caught an exception inside stubs + } +#endif + +#if defined(CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS) + + _hal_registers = regs; + __handle_exception(); + +#elif defined(CYGPKG_KERNEL_EXCEPTIONS) + + cyg_hal_deliver_exception( regs->u.exception.vector, (CYG_ADDRWORD)regs ); + +#else + + CYG_FAIL("Exception!!!"); + +#endif +} + +//========================================================================== +// Handle Interrupts +// +// Interrupts are passed here from the low-level VSR in vectors.S. We +// look up the ISR in the interrupt table, call it and if it requests +// it, post a DSR. If necessary we also then cause the pendable SVC to +// be requested. +// +// This function is also callable from ISR springboards that decode +// additional interrupts via external controllers to deliver an +// interrupt to a secondary vector. + +void hal_deliver_interrupt( cyg_uint32 vector ) +{ + register cyg_uint32 isr_result; + register cyg_isr *isr; + cyg_bool pendsvc = false; + +#if defined(CYGPKG_KERNEL_INSTRUMENT) && \ + defined(CYGDBG_KERNEL_INSTRUMENT_INTR) + cyg_instrument(RAISE_INTR, vector, 0 ); +#endif + + isr = (cyg_isr *)hal_interrupt_handlers[vector]; + + // Call the ISR + isr_result = isr( vector, hal_interrupt_data[vector] ); + + +#if !defined(CYGIMP_HAL_COMMON_INTERRUPTS_CHAIN) + // If the ISR has returned the CALL_DSR bit, post the DSR and set + // the pendable SVC exception pending. + if( isr_result & CYG_ISR_CALL_DSR ) + { + cyg_interrupt_post_dsr( hal_interrupt_objects[vector] ); + + // Post the pendable SVC to call interrupt_end(). But only if + // the scheduler lock is currently zero. If it is non zero + // then interrupt_end will do nothing useful, so avoid calling + // it. + if( cyg_scheduler_sched_lock == 0 ) + pendsvc = true; + } +#else + // When chaining we don't know here whether the nested interrupt + // has posted a DSR, so we have to run interrupt_end() regardless. + // However, the same considerations as above regarding the + // scheduler lock still apply. + if( cyg_scheduler_sched_lock == 0 ) + pendsvc = true; +#endif + + // Post the pendable SVC if required. + if( pendsvc ) + { + cyg_uint32 icsr; + HAL_READ_UINT32( CYGARC_REG_NVIC_BASE+CYGARC_REG_NVIC_ICSR, icsr ); + icsr |= CYGARC_REG_NVIC_ICSR_PENDSVSET; + HAL_WRITE_UINT32( CYGARC_REG_NVIC_BASE+CYGARC_REG_NVIC_ICSR, icsr ); + } +} + +//========================================================================== +// Call interrupt_end() +// +// This is called on the thread stack as a result of the pendable +// SVC. interrupt_end() decrements the scheduler lock, calls DSRs and +// optionally switches thread context. So before calling, we must +// increment the lock. The actual interrupt end processing has already +// been done above in hal_default_interrupt_vsr1(), so the arguments +// are zero. + +__externC void hal_interrupt_end( void ) +{ +#ifdef CYGFUN_HAL_COMMON_KERNEL_SUPPORT + cyg_scheduler_sched_lock++; +#endif + + interrupt_end(0,0,0); +} + +//========================================================================== +// Interrupt masking and configuration + +#ifndef HAL_VAR_INTERRUPT_MASK +#define HAL_VAR_INTERRUPT_MASK( __vector ) CYG_EMPTY_STATEMENT +#define HAL_VAR_INTERRUPT_UNMASK( __vector ) CYG_EMPTY_STATEMENT +#define HAL_VAR_INTERRUPT_SET_LEVEL( __vector, __level ) CYG_EMPTY_STATEMENT +#define HAL_VAR_INTERRUPT_ACKNOWLEDGE( __vector ) CYG_EMPTY_STATEMENT +#define HAL_VAR_INTERRUPT_CONFIGURE( __vector, __level, __up ) CYG_EMPTY_STATEMENT +#endif + +//-------------------------------------------------------------------------- + +__externC void hal_interrupt_mask( cyg_uint32 vector ) +{ + if( vector >= CYGNUM_HAL_INTERRUPT_EXTERNAL && + vector <= CYGNUM_HAL_INTERRUPT_NVIC_MAX ) + HAL_WRITE_UINT32( CYGARC_REG_NVIC_BASE+CYGARC_REG_NVIC_CER(vector-CYGNUM_HAL_INTERRUPT_EXTERNAL), + CYGARC_REG_NVIC_IBIT(vector-CYGNUM_HAL_INTERRUPT_EXTERNAL) ); + else if( vector == CYGNUM_HAL_INTERRUPT_SYS_TICK ) + { + cyg_uint32 csr; + HAL_READ_UINT32(CYGARC_REG_SYSTICK_BASE+CYGARC_REG_SYSTICK_CSR, csr ); + csr &= ~CYGARC_REG_SYSTICK_CSR_TICKINT; + HAL_WRITE_UINT32(CYGARC_REG_SYSTICK_BASE+CYGARC_REG_SYSTICK_CSR, csr ); + } + HAL_VAR_INTERRUPT_MASK( vector ); +} + +//-------------------------------------------------------------------------- + +__externC void hal_interrupt_unmask( cyg_uint32 vector ) +{ + if( vector >= CYGNUM_HAL_INTERRUPT_EXTERNAL && + vector <= CYGNUM_HAL_INTERRUPT_NVIC_MAX ) + HAL_WRITE_UINT32( CYGARC_REG_NVIC_BASE+CYGARC_REG_NVIC_SER(vector-CYGNUM_HAL_INTERRUPT_EXTERNAL), + CYGARC_REG_NVIC_IBIT(vector-CYGNUM_HAL_INTERRUPT_EXTERNAL) ); + else if( vector == CYGNUM_HAL_INTERRUPT_SYS_TICK ) + { + cyg_uint32 csr; + HAL_READ_UINT32(CYGARC_REG_SYSTICK_BASE+CYGARC_REG_SYSTICK_CSR, csr ); + csr |= CYGARC_REG_SYSTICK_CSR_TICKINT; + HAL_WRITE_UINT32(CYGARC_REG_SYSTICK_BASE+CYGARC_REG_SYSTICK_CSR, csr ); + } + HAL_VAR_INTERRUPT_UNMASK( vector ); +} + +//-------------------------------------------------------------------------- + +__externC void hal_interrupt_acknowledge( cyg_uint32 vector ) +{ + HAL_VAR_INTERRUPT_ACKNOWLEDGE( vector ); +} + +//-------------------------------------------------------------------------- + +__externC void hal_interrupt_configure( cyg_uint32 vector, cyg_uint32 level, cyg_uint32 up ) +{ + HAL_VAR_INTERRUPT_CONFIGURE( vector, level, up ); +} + +//-------------------------------------------------------------------------- + +__externC void hal_interrupt_set_level( cyg_uint32 vector, cyg_uint32 level ) +{ + cyg_uint32 l = (level)+CYGNUM_HAL_CORTEXM_PRIORITY_MAX; + if( l > 0xFF ) l = 0xFF; /* clamp to 0xFF */ + if( vector >= CYGNUM_HAL_INTERRUPT_EXTERNAL && + vector <= CYGNUM_HAL_INTERRUPT_NVIC_MAX ) + { + HAL_WRITE_UINT8( CYGARC_REG_NVIC_BASE+CYGARC_REG_NVIC_PR(vector-CYGNUM_HAL_INTERRUPT_EXTERNAL), + l ); + } + else if ( vector == CYGNUM_HAL_INTERRUPT_SYS_TICK ) + { + cyg_uint32 shpr2; + HAL_READ_UINT32( CYGARC_REG_NVIC_BASE+CYGARC_REG_NVIC_SHPR2, shpr2 ); + shpr2 &= ~0xFF000000; + shpr2 |= (l)<<24; + HAL_WRITE_UINT32( CYGARC_REG_NVIC_BASE+CYGARC_REG_NVIC_SHPR2, shpr2 ); + } + HAL_VAR_INTERRUPT_SET_LEVEL( vector, level ); +} + +//========================================================================== +// Microsecond delay +// +// The system RTC is set up to tick at 1MHz so all we need to do here +// is count ticks. + +__externC void hal_delay_us( cyg_int32 us ) +{ + cyg_uint32 t0, t1; + + HAL_CLOCK_READ( &t0 ); + while ( us > 0 ) + { + HAL_CLOCK_READ( &t1 ); + if( t1 < t0 ) + t1 += CYGNUM_HAL_RTC_PERIOD; + us -= t1-t0; + t0 = t1; + } +} + +//========================================================================== +// C++ support - run initial constructors + +#ifdef CYGSEM_HAL_STOP_CONSTRUCTORS_ON_FLAG +cyg_bool cyg_hal_stop_constructors; +#endif + +typedef void (*pfunc) (void); + +extern pfunc __init_array_start__[]; +extern pfunc __init_array_end__[]; +#define CONSTRUCTORS_START (__init_array_start__[0]) +#define CONSTRUCTORS_END (__init_array_end__) +#define NEXT_CONSTRUCTOR(c) ((c)++) + +void +cyg_hal_invoke_constructors (void) +{ +#ifdef CYGSEM_HAL_STOP_CONSTRUCTORS_ON_FLAG + static pfunc *p = &CONSTRUCTORS_START; + + cyg_hal_stop_constructors = 0; + for (; p != CONSTRUCTORS_END; NEXT_CONSTRUCTOR(p)) { + (*p)(); + if (cyg_hal_stop_constructors) { + NEXT_CONSTRUCTOR(p); + break; + } + } +#else + pfunc *p; + + for (p = &CONSTRUCTORS_START; p != CONSTRUCTORS_END; NEXT_CONSTRUCTOR(p)) + (*p)(); +#endif +} + +//========================================================================== +// Architecture default ISR + +__externC cyg_uint32 +hal_arch_default_isr(CYG_ADDRWORD vector, CYG_ADDRWORD data) +{ + CYG_TRACE1(true, "Interrupt: %d", vector); + + CYG_FAIL("Spurious Interrupt!!!"); + + return 0; +} + +//========================================================================== +// GDB support +// +// These functions translate between HAL saved contexts and GDB +// register dumps. + +__externC void hal_get_gdb_registers( HAL_CORTEXM_GDB_Registers *gdbreg, HAL_SavedRegisters *regs ) +{ + int i; + cyg_uint32 *p = gdbreg->f0; + + switch( regs->u.type ) + { + case HAL_SAVEDREGISTERS_THREAD: + for( i = 0; i < 13; i++ ) + gdbreg->gpr[i] = regs->u.thread.r[i]; + gdbreg->gpr[13] = regs->u.thread.sp; + gdbreg->gpr[14] = regs->u.thread.pc; + gdbreg->gpr[15] = regs->u.thread.pc; + gdbreg->ps = 0x01000000; + break; + + case HAL_SAVEDREGISTERS_EXCEPTION: + gdbreg->gpr[0] = regs->u.exception.r0; + gdbreg->gpr[1] = regs->u.exception.r1; + gdbreg->gpr[2] = regs->u.exception.r2; + gdbreg->gpr[3] = regs->u.exception.r3; + for( i = 0; i < 8; i++ ) + gdbreg->gpr[i+4] = regs->u.exception.r4_11[i]; + gdbreg->gpr[12] = regs->u.exception.r12; + gdbreg->gpr[13] = ((cyg_uint32)regs)+sizeof(regs->u.exception); + gdbreg->gpr[14] = regs->u.exception.lr; + gdbreg->gpr[15] = regs->u.exception.pc; + gdbreg->ps = regs->u.exception.psr; + break; + + case HAL_SAVEDREGISTERS_INTERRUPT: + gdbreg->gpr[0] = regs->u.interrupt.r0; + gdbreg->gpr[1] = regs->u.interrupt.r1; + gdbreg->gpr[2] = regs->u.interrupt.r2; + gdbreg->gpr[3] = regs->u.interrupt.r3; + gdbreg->gpr[12] = regs->u.interrupt.r12; + gdbreg->gpr[13] = ((cyg_uint32)regs)+sizeof(regs->u.interrupt); + gdbreg->gpr[14] = regs->u.interrupt.lr; + gdbreg->gpr[15] = regs->u.interrupt.pc; + gdbreg->ps = regs->u.interrupt.psr; + break; + } + + // Clear FP state, which we don't use + for( i = 0; i < (8*3+1); i++ ) + p[i] = 0; + +} + +__externC void hal_set_gdb_registers( HAL_CORTEXM_GDB_Registers *gdbreg, HAL_SavedRegisters *regs ) +{ + int i; + + switch( regs->u.type ) + { + case HAL_SAVEDREGISTERS_THREAD: + for( i = 0; i < 13; i++ ) + regs->u.thread.r[i] = gdbreg->gpr[i]; + regs->u.thread.sp = gdbreg->gpr[13]; + regs->u.thread.pc = gdbreg->gpr[14]; + regs->u.thread.pc = gdbreg->gpr[15]; + break; + + case HAL_SAVEDREGISTERS_EXCEPTION: + regs->u.exception.r0 = gdbreg->gpr[0]; + regs->u.exception.r1 = gdbreg->gpr[1]; + regs->u.exception.r2 = gdbreg->gpr[2]; + regs->u.exception.r3 = gdbreg->gpr[3]; + for( i = 0; i < 8; i++ ) + regs->u.exception.r4_11[i] = gdbreg->gpr[i+4]; + regs->u.exception.r12 = gdbreg->gpr[12]; + regs->u.exception.lr = gdbreg->gpr[14]; + regs->u.exception.pc = gdbreg->gpr[15]; + regs->u.exception.psr = gdbreg->ps; + break; + + case HAL_SAVEDREGISTERS_INTERRUPT: + regs->u.interrupt.r0 = gdbreg->gpr[0]; + regs->u.interrupt.r1 = gdbreg->gpr[1]; + regs->u.interrupt.r2 = gdbreg->gpr[2]; + regs->u.interrupt.r3 = gdbreg->gpr[3]; + regs->u.interrupt.r12 = gdbreg->gpr[12]; + regs->u.interrupt.lr = gdbreg->gpr[14]; + regs->u.interrupt.pc = gdbreg->gpr[15]; + regs->u.interrupt.psr = gdbreg->ps; + break; + } +} + +//========================================================================== +// When compiling C++ code with static objects the compiler +// inserts a call to __cxa_atexit() with __dso_handle as one of the +// arguments. __cxa_atexit() would normally be provided by glibc, and +// __dso_handle is part of crtstuff.c. eCos applications +// are linked rather differently, so either a differently-configured +// compiler is needed or dummy versions of these symbols should be +// provided. If these symbols are not actually used then providing +// them is still harmless, linker garbage collection will remove them. + +void +__cxa_atexit(void (*arg1)(void*), void* arg2, void* arg3) +{ +} + +void* __dso_handle = (void*) &__dso_handle; + +//========================================================================== +// EOF hal_misc.c
