Mercurial > flash_v2
diff packages/hal/common/current/src/hal_if.c @ 105:5a0cc6c243a9 ecos-sw-2000-06-30
Merge from eCos master repository on 2000-06-30-08:18:49-BST
| author | jlarmour |
|---|---|
| date | Fri, 30 Jun 2000 16:27:35 +0000 |
| parents | 95f3e12a6327 |
| children | 7f461c3a372c |
line wrap: on
line diff
--- a/packages/hal/common/current/src/hal_if.c +++ b/packages/hal/common/current/src/hal_if.c @@ -41,6 +41,10 @@ #include <pkgconf/hal.h> +#ifdef CYGPKG_KERNEL +# include <pkgconf/kernel.h> +#endif + #include <cyg/infra/cyg_ass.h> // assertions #include <cyg/hal/hal_arch.h> // set/restore GP @@ -49,26 +53,64 @@ #include <cyg/hal/hal_if.h> // our interface #include <cyg/hal/hal_diag.h> // Diag IO +#include <cyg/hal/hal_misc.h> // User break #include <cyg/hal/hal_stub.h> // stub functionality #include <cyg/hal/plf_stub.h> // reset entry - FIXME, should be moved +#include <cyg/hal/hal_intr.h> // hal_vsr_table and others + //-------------------------------------------------------------------------- externC void patch_dbg_syscalls(void * vector); externC void init_thread_syscall(void * vector); -externC CYG_ADDRWORD hal_interrupt_handlers[]; -externC CYG_ADDRWORD hal_vsr_table[]; - //-------------------------------------------------------------------------- // Implementations and function wrappers for monitor services + #ifdef CYGPRI_HAL_IMPLEMENTS_IF_SERVICES +static void +delay_us(cyg_int32 usecs) +{ +#ifdef CYGPKG_KERNEL + cyg_int32 start, elapsed; + cyg_int32 usec_ticks, slice; + CYGARC_HAL_SAVE_GP(); + + // How many ticks total we should wait for. + usec_ticks = usecs*CYGNUM_KERNEL_COUNTERS_RTC_PERIOD; + usec_ticks /= CYGNUM_HAL_RTC_NUMERATOR/CYGNUM_HAL_RTC_DENOMINATOR/1000; + + do { + // Spin in slices of 1/2 the RTC period. Allows interrupts + // time to run without messing up the algorithm. If we spun + // for 1 period (or more) of the RTC, there'd be also problems + // figuring out when the timer wrapped. We may lose a tick or + // two for each cycle but it shouldn't matter much. + slice = usec_ticks % (CYGNUM_KERNEL_COUNTERS_RTC_PERIOD / 2); + + HAL_CLOCK_READ(&start); + do { + HAL_CLOCK_READ(&elapsed); + elapsed = (elapsed - start); // counts up! + if (elapsed < 0) + elapsed += CYGNUM_KERNEL_COUNTERS_RTC_PERIOD; + } while (elapsed < slice); + + // Adjust by elapsed, not slice, since an interrupt may have + // been stalling us for some time. + usec_ticks -= elapsed; + } while (usec_ticks > 0); + + CYGARC_HAL_RESTORE_GP(); +#endif +} static void reset(void) { + CYGARC_HAL_SAVE_GP(); // With luck, the platform defines some magic that will cause a hardware // reset. HAL_STUB_PLATFORM_RESET(); @@ -83,6 +125,8 @@ reset(void) #else #error " no RESET_ENTRY" #endif + + CYGARC_HAL_RESTORE_GP(); } // This is the system's default kill signal routine. Unless overridden @@ -92,7 +136,11 @@ reset(void) static int kill_by_reset(int __irq_nr, void* __regs) { + CYGARC_HAL_SAVE_GP(); + reset(); + + CYGARC_HAL_RESTORE_GP(); return 0; } @@ -110,12 +158,14 @@ nop_service(void) static hal_virtual_comm_table_t comm_channels[CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS+1]; - - static int set_debug_comm(int __comm_id) { static int __selected_id = CYGNUM_CALL_IF_SET_COMM_ID_EMPTY; + hal_virtual_comm_table_t* __chan; + int interrupt_state = 0; + int res = 1, update = 0; + CYGARC_HAL_SAVE_GP(); CYG_ASSERT(__comm_id >= CYGNUM_CALL_IF_SET_COMM_ID_MANGLER && __comm_id < CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS, @@ -124,36 +174,56 @@ set_debug_comm(int __comm_id) switch (__comm_id) { case CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT: if (__selected_id > 0) - return __selected_id-1; - if (__selected_id == 0) - return CYGNUM_CALL_IF_SET_COMM_ID_MANGLER; - return __selected_id; + res = __selected_id-1; + else if (__selected_id == 0) + res = CYGNUM_CALL_IF_SET_COMM_ID_MANGLER; + else + res = __selected_id; + break; case CYGNUM_CALL_IF_SET_COMM_ID_EMPTY: CYGACC_CALL_IF_DEBUG_PROCS_SET(0); __selected_id = __comm_id; - return 1; + break; case CYGNUM_CALL_IF_SET_COMM_ID_MANGLER: __comm_id = 0; + update = 1; break; default: __comm_id++; // skip mangler entry + update = 1; break; } - - __selected_id = __comm_id; - - CYGACC_CALL_IF_DEBUG_PROCS_SET(comm_channels[__comm_id]); + + if (update) { + // Find the interrupt state of the channel. + __chan = CYGACC_CALL_IF_DEBUG_PROCS(); + if (__chan) + interrupt_state = CYGACC_COMM_IF_CONTROL(*__chan)(CYGACC_COMM_IF_CH_DATA(*__chan), __COMMCTL_IRQ_DISABLE); + + __selected_id = __comm_id; + CYGACC_CALL_IF_DEBUG_PROCS_SET(comm_channels[__comm_id]); - return 1; + // Set interrupt state on the new channel. + __chan = CYGACC_CALL_IF_DEBUG_PROCS(); + if (interrupt_state) + CYGACC_COMM_IF_CONTROL(*__chan)(CYGACC_COMM_IF_CH_DATA(*__chan), __COMMCTL_IRQ_ENABLE); + else + CYGACC_COMM_IF_CONTROL(*__chan)(CYGACC_COMM_IF_CH_DATA(*__chan), __COMMCTL_IRQ_DISABLE); + } + + CYGARC_HAL_RESTORE_GP(); + return res; } static int set_console_comm(int __comm_id) { static int __selected_id = CYGNUM_CALL_IF_SET_COMM_ID_EMPTY; + int res = 1, update = 0; + CYGARC_HAL_SAVE_GP(); CYG_ASSERT(__comm_id >= CYGNUM_CALL_IF_SET_COMM_ID_MANGLER && __comm_id < CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS, @@ -162,30 +232,37 @@ set_console_comm(int __comm_id) switch (__comm_id) { case CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT: if (__selected_id > 0) - return __selected_id-1; - if (__selected_id == 0) - return CYGNUM_CALL_IF_SET_COMM_ID_MANGLER; - return __selected_id; + res = __selected_id-1; + else if (__selected_id == 0) + res = CYGNUM_CALL_IF_SET_COMM_ID_MANGLER; + else + res = __selected_id; + break; case CYGNUM_CALL_IF_SET_COMM_ID_EMPTY: CYGACC_CALL_IF_CONSOLE_PROCS_SET(0); __selected_id = __comm_id; - return 1; + break; case CYGNUM_CALL_IF_SET_COMM_ID_MANGLER: __comm_id = 0; + update = 1; break; default: __comm_id++; // skip mangler entry + update = 1; break; } - __selected_id = __comm_id; + if (update) { + __selected_id = __comm_id; - CYGACC_CALL_IF_CONSOLE_PROCS_SET(comm_channels[__comm_id]); + CYGACC_CALL_IF_CONSOLE_PROCS_SET(comm_channels[__comm_id]); + } - return 1; + CYGARC_HAL_RESTORE_GP(); + return res; } //---------------------------------- @@ -194,21 +271,25 @@ set_console_comm(int __comm_id) static void flush_icache(void *__p, int __nbytes) { + CYGARC_HAL_SAVE_GP(); #ifdef HAL_ICACHE_FLUSH HAL_ICACHE_FLUSH( __p , __nbytes ); #elif defined(HAL_ICACHE_INVALIDATE) HAL_ICACHE_INVALIDATE(); #endif + CYGARC_HAL_RESTORE_GP(); } static void flush_dcache(void *__p, int __nbytes) { + CYGARC_HAL_SAVE_GP(); #ifdef HAL_DCACHE_FLUSH HAL_DCACHE_FLUSH( __p , __nbytes ); #elif defined(HAL_DCACHE_INVALIDATE) HAL_DCACHE_INVALIDATE(); #endif + CYGARC_HAL_RESTORE_GP(); } #endif @@ -222,10 +303,10 @@ flush_dcache(void *__p, int __nbytes) // routines for that channel. The platform HAL also has the necessary // information to determine if the channel is already initialized by // a debug agent (either builtin or in ROM). -void +void hal_if_diag_init(void) { -#ifndef CYGSEM_HAL_VIRTUAL_VECTOR_DIAG +#ifdef CYGPRI_HAL_IMPLEMENTS_IF_SERVICES cyg_hal_plf_comms_init(); #endif @@ -249,6 +330,12 @@ hal_if_diag_write_char(char c) __chan = CYGACC_CALL_IF_DEBUG_PROCS(); CYGACC_COMM_IF_PUTC(*__chan)(CYGACC_COMM_IF_CH_DATA(*__chan), c); } + + // Check interrupt flag + if (CYGACC_CALL_IF_CONSOLE_INTERRUPT_FLAG()) { + cyg_hal_user_break(0); + CYGACC_CALL_IF_CONSOLE_INTERRUPT_FLAG_SET(0); + } } void @@ -265,6 +352,43 @@ hal_if_diag_read_char(char *c) } #endif // CYGSEM_HAL_VIRTUAL_VECTOR_DIAG +//============================================================================= +// CtrlC support +//============================================================================= + +#if defined(CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT) \ + || defined(CYGDBG_HAL_DEBUG_GDB_CTRLC_SUPPORT) + +struct Hal_SavedRegisters *hal_saved_interrupt_state; + +void +hal_ctrlc_isr_init(void) +{ + hal_virtual_comm_table_t* __chan = CYGACC_CALL_IF_DEBUG_PROCS(); + +#if 1 // Prevents crash on older stubs + if (CYGNUM_CALL_IF_TABLE_VERSION != CYGACC_CALL_IF_VERSION()) + return; +#endif + + CYGACC_COMM_IF_CONTROL(*__chan)(CYGACC_COMM_IF_CH_DATA(*__chan), + __COMMCTL_IRQ_ENABLE); +} + +cyg_uint32 +hal_ctrlc_isr(CYG_ADDRWORD vector, CYG_ADDRWORD data) +{ + hal_virtual_comm_table_t* __chan = CYGACC_CALL_IF_DEBUG_PROCS(); + int isr_ret, ctrlc = 0; + + isr_ret = CYGACC_COMM_IF_DBG_ISR(*__chan)(CYGACC_COMM_IF_CH_DATA(*__chan), + &ctrlc, vector, data); + if (ctrlc) + cyg_hal_user_break( (CYG_ADDRWORD *)hal_saved_interrupt_state ); + return isr_ret; +} +#endif // CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT || CYGDBG_HAL_DEBUG_GDB_CTRLC_SUPPORT + //-------------------------------------------------------------------------- // Init function. It should be called from the platform initialization code. // For monitor configurations it will initialize the calling interface table, @@ -298,9 +422,10 @@ hal_if_init(void) CYGACC_CALL_IF_ICTRL_TABLE_SET(hal_interrupt_handlers); CYGACC_CALL_IF_EXC_TABLE_SET(hal_vsr_table); - // Reset and kill vector + // Miscellaneous services with wrappers in this file. CYGACC_CALL_IF_RESET_SET(reset); CYGACC_CALL_IF_KILL_VECTOR_SET(kill_by_reset); + CYGACC_CALL_IF_DELAY_US_SET(delay_us); // Comm controls CYGACC_CALL_IF_SET_DEBUG_COMM_SET(set_debug_comm); @@ -310,11 +435,12 @@ hal_if_init(void) CYGACC_CALL_IF_FLUSH_ICACHE_SET(flush_icache); CYGACC_CALL_IF_FLUSH_DCACHE_SET(flush_dcache); - // Clear console procs entry. If platform has been configured - // to use a separate console port, it will be set up later - // (hal_diag_init). Alternatively (if this is a stub) it will - // be initialized with the output mangler (O-packetizer for - // GDB) which uses the debug comms. + // Clear debug and console procs entries. If platform has been + // configured to use a separate console port, it will be set + // up later (hal_diag_init). Alternatively (if this is a stub) + // it will be initialized with the output mangler + // (O-packetizer for GDB) which uses the debug comms. + set_debug_comm(CYGNUM_CALL_IF_SET_COMM_ID_EMPTY); set_console_comm(CYGNUM_CALL_IF_SET_COMM_ID_EMPTY); // Data entries not currently supported in eCos @@ -324,6 +450,9 @@ hal_if_init(void) } #endif + // Reset console interrupt flag. + CYGACC_CALL_IF_CONSOLE_INTERRUPT_FLAG_SET(0); + // Set up services provided by clients #if defined(CYGFUN_HAL_COMMON_KERNEL_SUPPORT) && \ ( defined(CYGSEM_HAL_USE_ROM_MONITOR_GDB_stubs) \
