📄 hal_if.c
字号:
//=============================================================================//// 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>#ifdef CYGPKG_KERNEL# include <pkgconf/kernel.h>#endif#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_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);//--------------------------------------------------------------------------// Implementations and function wrappers for monitor services#ifdef CYGPRI_HAL_IMPLEMENTS_IF_SERVICESstatic voiddelay_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();#else#ifdef HAL_DELAY_US // Use a HAL feature if defined HAL_DELAY_US(usecs);#else // If no accurate delay mechanism, just spin for a while. Having // an inaccurate delay is much better than no delay at all. The // count of 100 should mean the loop takes something resembling // 1us on most CPUs running between 30-100MHz [depends on how many // instructions this compiles to, how many dispatch units can be // used for the simple loop, actual CPU frequency, etc] while (usecs-- > 0) { int i; for (i = 0; i < 100; i++); }#endif#endif}static voidreset(void){ CYGARC_HAL_SAVE_GP(); // 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 CYGARC_HAL_RESTORE_GP();}// 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 intkill_by_reset(int __irq_nr, void* __regs){ CYGARC_HAL_SAVE_GP(); reset(); CYGARC_HAL_RESTORE_GP(); return 0;}static intnop_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#ifdef CYGNUM_HAL_VIRTUAL_VECTOR_AUX_CHANNELS#define CYGNUM_HAL_VIRTUAL_VECTOR_NUM_CHANNELS \ (CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS+CYGNUM_HAL_VIRTUAL_VECTOR_AUX_CHANNELS)#else#define CYGNUM_HAL_VIRTUAL_VECTOR_NUM_CHANNELS \ CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS#endifstatic hal_virtual_comm_table_t comm_channels[CYGNUM_HAL_VIRTUAL_VECTOR_NUM_CHANNELS+1];static intset_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_NUM_CHANNELS, "Invalid channel"); switch (__comm_id) { case CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT: if (__selected_id > 0) 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; break; case CYGNUM_CALL_IF_SET_COMM_ID_MANGLER: __comm_id = 0; update = 1; break; default: __comm_id++; // skip mangler entry update = 1; break; } if (update) { // Find the interrupt state of the channel. __chan = CYGACC_CALL_IF_DEBUG_PROCS(); if (__chan) interrupt_state = CYGACC_COMM_IF_CONTROL(*__chan, __COMMCTL_IRQ_DISABLE); __selected_id = __comm_id; CYGACC_CALL_IF_DEBUG_PROCS_SET(comm_channels[__comm_id]); // Set interrupt state on the new channel. __chan = CYGACC_CALL_IF_DEBUG_PROCS(); if (interrupt_state) CYGACC_COMM_IF_CONTROL(*__chan, __COMMCTL_IRQ_ENABLE); else CYGACC_COMM_IF_CONTROL(*__chan, __COMMCTL_IRQ_DISABLE); } CYGARC_HAL_RESTORE_GP(); return res;}static intset_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_NUM_CHANNELS, "Invalid channel"); switch (__comm_id) { case CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT: if (__selected_id > 0) 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; break; case CYGNUM_CALL_IF_SET_COMM_ID_MANGLER: __comm_id = 0; update = 1; break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -