Mercurial > flash_v2
diff packages/hal/common/current/src/hal_if.c @ 101:c37d3a9e1b28 ecos-sw-2000-06-16
Merge from eCos master repository on 2000-06-16-07:47:03-BST
| author | jlarmour |
|---|---|
| date | Fri, 16 Jun 2000 16:43:59 +0000 |
| parents | |
| children | 95f3e12a6327 |
line wrap: on
line diff
new file mode 100644 --- /dev/null +++ b/packages/hal/common/current/src/hal_if.c @@ -0,0 +1,455 @@ +//============================================================================= +// +// hal_if.c +// +// ROM/RAM interfacing functions +// +//============================================================================= +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//============================================================================= +//#####DESCRIPTIONBEGIN#### +// +// Author(s): jskov +// Contributors:jskov +// Date: 2000-06-07 +// +//####DESCRIPTIONEND#### +// +//============================================================================= + +#include <pkgconf/hal.h> + +#include <cyg/infra/cyg_ass.h> // assertions + +#include <cyg/hal/hal_arch.h> // set/restore GP + +#include <cyg/hal/hal_io.h> // IO macros +#include <cyg/hal/hal_if.h> // our interface + +#include <cyg/hal/hal_diag.h> // Diag IO + +#include <cyg/hal/hal_stub.h> // stub functionality +#include <cyg/hal/plf_stub.h> // reset entry - FIXME, should be moved + + +//-------------------------------------------------------------------------- + +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[]; + + +//-------------------------------------------------------------------------- +// Configuration control for the services in this feil. +#if defined(CYG_HAL_STARTUP_ROM) || \ + ( defined(CYG_HAL_STARTUP_RAM) && \ + !defined(CYGSEM_HAL_USE_ROM_MONITOR)) +# define CYGPRI_IMPLEMENTS_IF_SERVICES +#endif + +//-------------------------------------------------------------------------- +// Implementations and function wrappers for monitor services +#ifdef CYGPRI_IMPLEMENTS_IF_SERVICES + +static void +reset(void) +{ + // With luck, the platform defines some magic that will cause a hardware + // reset. + HAL_STUB_PLATFORM_RESET(); + +#ifdef HAL_STUB_PLATFORM_RESET_ENTRY + // If that's not the case (above is an empty statement) there may + // be defined an address we can jump to - and effectively + // reinitialize the system. Not quite as good as a reset, but it + // is often enough. + goto *HAL_STUB_PLATFORM_RESET_ENTRY; + +#else +#error " no RESET_ENTRY" +#endif +} + +// This is the system's default kill signal routine. Unless overridden +// by the application, it will cause a board reset when GDB quits the +// connection. (The user can avoid the reset by using the GDB 'detach' +// command instead of 'kill' or 'quit'). +static int +kill_by_reset(int __irq_nr, void* __regs) +{ + reset(); + return 0; +} + +static int +nop_service(void) +{ + // This is the default service. It always returns false (0), and + // _does_ not trigger any assertions. Clients must either cope + // with the service failure or assert. + return 0; +} + +//---------------------------------- +// Comm controls + +static hal_virtual_comm_table_t comm_channels[CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS]; + +static int +set_debug_comm(int __comm_id) +{ + static int __selected_id; + + CYG_ASSERT(-1 == __comm_id + || __comm_id < CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS, + "Invalid channel"); + + if (-1 == __comm_id) + return __selected_id; + + __selected_id = __comm_id; + + CYGACC_CALL_IF_DEBUG_PROCS_SET(comm_channels[__comm_id]); + + return 1; +} + +static int +set_console_comm(int __comm_id) +{ + static int __selected_id; + + CYG_ASSERT(-1 == __comm_id + || __comm_id < CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS, + "Invalid channel"); + + if (-1 == __comm_id) + return __selected_id; + + __selected_id = __comm_id; + + CYGACC_CALL_IF_CONSOLE_PROCS_SET(comm_channels[__comm_id]); + + return 1; +} + + +#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS +//---------------------------------- +// eCos debug procedure wrappers +static void +debug_write(void* __ch_data, const cyg_uint8* __buf, cyg_uint32 __len) +{ + CYGARC_HAL_SAVE_GP(); + + while(__len-- > 0) + HAL_STUB_PLATFORM_PUT_CHAR(*__buf++); + + CYGARC_HAL_RESTORE_GP(); +} + +static void +debug_read(void* __ch_data, cyg_uint8* __buf, cyg_uint32 __len) +{ + CYGARC_HAL_SAVE_GP(); + + while(__len-- > 0) + *__buf++ = HAL_STUB_PLATFORM_GET_CHAR(); + + CYGARC_HAL_RESTORE_GP(); +} + + +static void +debug_putc(void* __ch_data, cyg_uint8 __ch) +{ + CYGARC_HAL_SAVE_GP(); + + HAL_STUB_PLATFORM_PUT_CHAR(__ch); + + CYGARC_HAL_RESTORE_GP(); +} + +static cyg_uint8 +debug_getc(void* __ch_data) +{ + cyg_uint8 __ch; + CYGARC_HAL_SAVE_GP(); + + __ch = HAL_STUB_PLATFORM_GET_CHAR(); + + CYGARC_HAL_RESTORE_GP(); + return __ch; +} + +static int +debug_control(void *__ch_data, __comm_control_cmd_t __func, ...) +{ + // Do nothing (yet). + return 0; +} +#endif // CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS + +//---------------------------------- +// Cache functions + +static void +flush_icache(void *__p, int __nbytes) +{ +#ifdef HAL_ICACHE_FLUSH + HAL_ICACHE_FLUSH( __p , __nbytes ); +#elif defined(HAL_ICACHE_INVALIDATE) + HAL_ICACHE_INVALIDATE(); +#endif +} + +static void +flush_dcache(void *__p, int __nbytes) +{ +#ifdef HAL_DCACHE_FLUSH + HAL_DCACHE_FLUSH( __p , __nbytes ); +#elif defined(HAL_DCACHE_INVALIDATE) + HAL_DCACHE_INVALIDATE(); +#endif +} + +#endif + +#if !defined(CYGPRI_CONSOLE_PROCS_HANDLED) \ + && defined(CYGSEM_HAL_VIRTUAL_VECTOR_DIAG) +// -------------------- +// Console wrapper functions. These are used for pumping data to the device +// via low-level functions provided by the platform HAL. Mangling has +// happened (if applicable) by the time the stream hits this code. +static void +console_write(void* __ch_data, const cyg_uint8* __buf, cyg_uint32 __len) +{ + CYGARC_HAL_SAVE_GP(); + + while(__len-- > 0) + HAL_PLF_DIAG_RAW_WRITE_CHAR(*__buf++); + + CYGARC_HAL_RESTORE_GP(); +} + +static void +console_read(void* __ch_data, cyg_uint8* __buf, cyg_uint32 __len) +{ + CYGARC_HAL_SAVE_GP(); + + while(__len-- > 0) + HAL_PLF_DIAG_RAW_READ_CHAR(*__buf++); + + CYGARC_HAL_RESTORE_GP(); +} + + +static void +console_putc(void* __ch_data, cyg_uint8 __ch) +{ + CYGARC_HAL_SAVE_GP(); + + HAL_PLF_DIAG_RAW_WRITE_CHAR(__ch); + + CYGARC_HAL_RESTORE_GP(); +} + +static cyg_uint8 +console_getc(void* __ch_data) +{ + cyg_uint8 __ch; + CYGARC_HAL_SAVE_GP(); + + HAL_PLF_DIAG_RAW_READ_CHAR(__ch); + + CYGARC_HAL_RESTORE_GP(); + return __ch; +} + +static int +console_control(void *__ch_data, __comm_control_cmd_t __func, ...) +{ + // Do nothing (yet). + return 0; +} +#endif + +#if defined(CYGSEM_HAL_VIRTUAL_VECTOR_DIAG) +//----------------------------------------------------------------------------- +// Console IO functions that adhere to the virtual vector table semantics in +// order to ensure proper debug agent mangling when required. +// +// The platform HAL must specify the channel used, and provide raw IO +// 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 +hal_if_diag_init(void) +{ +#ifndef CYGPRI_CONSOLE_PROCS_HANDLED + // Set up console procs for the channel and initialize it. + hal_virtual_comm_table_t* comm; + // Hook console wrappers up on the diag channel + CYGACC_CALL_IF_SET_CONSOLE_COMM()(CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL); + comm = CYGACC_CALL_IF_CONSOLE_PROCS(); + + CYGACC_COMM_IF_WRITE_SET(*comm, console_write); + CYGACC_COMM_IF_READ_SET(*comm, console_read); + CYGACC_COMM_IF_PUTC_SET(*comm, console_putc); + CYGACC_COMM_IF_GETC_SET(*comm, console_getc); + CYGACC_COMM_IF_CONTROL_SET(*comm, console_control); + + // Init device. + HAL_PLF_DIAG_RAW_INIT(); +#endif +} + +void +hal_if_diag_write_char(char c) +{ + hal_virtual_comm_table_t* __chan = CYGACC_CALL_IF_CONSOLE_PROCS(); + + if (__chan) + CYGACC_COMM_IF_PUTC(*__chan)(*__chan, c); + else { + __chan = CYGACC_CALL_IF_DEBUG_PROCS(); + CYGACC_COMM_IF_PUTC(*__chan)(*__chan, c); + } +} + +void +hal_if_diag_read_char(char *c) +{ + hal_virtual_comm_table_t* __chan = CYGACC_CALL_IF_CONSOLE_PROCS(); + + if (__chan) + *c = CYGACC_COMM_IF_GETC(*__chan)(*__chan); + else { + __chan = CYGACC_CALL_IF_DEBUG_PROCS(); + *c = CYGACC_COMM_IF_GETC(*__chan)(*__chan); + } +} +#endif // CYGSEM_HAL_VIRTUAL_VECTOR_DIAG + +//-------------------------------------------------------------------------- +// Init function. It should be called from the platform initialization code. +// For monitor configurations it will initialize the calling interface table, +// for client configurations it will patch the existing table as per +// configuration. +void +hal_if_init(void) +{ + // Set up services provided by monitors +#ifdef CYGPRI_IMPLEMENTS_IF_SERVICES + { + hal_virtual_comm_table_t* comm; + int i, j; + // Initialize tables with the NOP service. + // This should only be done for service routine entries - data + // pointers should be NULLed. + for (i = 0; i < CYGNUM_CALL_IF_TABLE_SIZE; i++) + hal_virtual_vector_table[i] = (CYG_ADDRWORD) &nop_service; + + for (j = 0; j < CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS; j++) + for (i = 0; i < CYGNUM_COMM_IF_TABLE_SIZE; i++) + comm_channels[j][i] = (CYG_ADDRWORD) &nop_service; + + + // Fill in supported services. + + // Version number + CYGACC_CALL_IF_VERSION_SET(CYGNUM_CALL_IF_TABLE_VERSION); + + // ICTRL and EXC tables - I assume these to be the equivalents of + // ISR and VSR tables. + CYGACC_CALL_IF_ICTRL_TABLE_SET(hal_interrupt_handlers); + CYGACC_CALL_IF_EXC_TABLE_SET(hal_vsr_table); + + // Reset and kill vector + CYGACC_CALL_IF_RESET_SET(reset); + CYGACC_CALL_IF_KILL_VECTOR_SET(kill_by_reset); + + // Comm controls + CYGACC_CALL_IF_SET_DEBUG_COMM_SET(set_debug_comm); + CYGACC_CALL_IF_SET_CONSOLE_COMM_SET(set_console_comm); + + // Cache functions + CYGACC_CALL_IF_FLUSH_ICACHE_SET(flush_icache); + CYGACC_CALL_IF_FLUSH_DCACHE_SET(flush_dcache); + + // Clear console procs entry. If platform has been to + // 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. + CYGACC_CALL_IF_CONSOLE_PROCS_SET(0); + +#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS + // Hook debug wrappers up on the debug channel + set_debug_comm(CYGNUM_HAL_VIRTUAL_VECTOR_DEBUG_CHANNEL); + comm = CYGACC_CALL_IF_DEBUG_PROCS(); + CYGACC_COMM_IF_WRITE_SET(*comm, debug_write); + CYGACC_COMM_IF_READ_SET(*comm, debug_read); + CYGACC_COMM_IF_PUTC_SET(*comm, debug_putc); + CYGACC_COMM_IF_GETC_SET(*comm, debug_getc); + CYGACC_COMM_IF_CONTROL_SET(*comm, debug_control); +#endif + + // Data entries not currently supported in eCos + CYGACC_CALL_IF_CPU_DATA_SET(0); + CYGACC_CALL_IF_BOARD_DATA_SET(0); + CYGACC_CALL_IF_DBG_DATA_SET(0); + } +#endif + + // Set up services provided by clients +#if defined(CYGFUN_HAL_COMMON_KERNEL_SUPPORT) && \ + ( defined(CYGSEM_HAL_USE_ROM_MONITOR_GDB_stubs) \ + || defined(CYGSEM_HAL_USE_ROM_MONITOR_CygMon)) + + patch_dbg_syscalls( (void *)(hal_virtual_vector_table) ); +#endif + + // Init client services +#if !defined(CYGPKG_KERNEL) && defined(CYGDBG_HAL_DEBUG_GDB_THREAD_SUPPORT) + // Only include this code if we do not have a kernel. Otherwise + // the kernel supplies the functionality for the app we are linked + // with. + + // Prepare for application installation of thread info function in + // vector table. + init_thread_syscall( (void *)&hal_virtual_vector_table[CYGNUM_CALL_IF_DBG_SYSCALL] ); +#endif + + // Finally, install async breakpoint handler if it is configured in. + // FIXME: this should probably check for STUBS instead (but code is + // conditional on BREAK for now) +#if defined(CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT) + // Install async breakpoint handler into vector table. + CYGACC_CALL_IF_INSTALL_BPT_FN_SET(&cyg_hal_gdb_interrupt); +#endif +}
