📄 hal_if.c
字号:
//=============================================================================//// hal_if.c//// ROM/RAM interfacing functions////=============================================================================//####ECOSGPLCOPYRIGHTBEGIN####// -------------------------------------------// This file is part of eCos, the Embedded Configurable Operating System.// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.// Copyright (C) 2002, 2003 Gary Thomas// Copyright (C) 2003 Nick Garnett <nickg@calivar.com>// Copyright (C) 2003 Jonathan Larmour <jlarmour@eCosCentric.com>//// 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.//// Alternative licenses for eCos may be arranged by contacting the copyright// holders.// -------------------------------------------//####ECOSGPLCOPYRIGHTEND####//=============================================================================//#####DESCRIPTIONBEGIN####//// Author(s): jskov// Contributors:jskov, woehler// 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/hal_intr.h> // hal_vsr_table and others#ifdef CYGPKG_REDBOOT#include <pkgconf/redboot.h>#ifdef CYGSEM_REDBOOT_FLASH_CONFIG#include <redboot.h>#include <flash_config.h>#endif#ifdef CYGOPT_REDBOOT_FIS#include <fis.h>#endif#endif//--------------------------------------------------------------------------externC void patch_dbg_syscalls(void * vector);externC void init_thread_syscall(void * vector);//--------------------------------------------------------------------------// Implementations and function wrappers for monitor services// flash config state queries#ifdef CYGSEM_REDBOOT_FLASH_CONFIGstatic __call_if_flash_cfg_op_fn_t flash_config_op;static cyg_boolflash_config_op(int op, struct cyg_fconfig *fc){ cyg_bool res = false; CYGARC_HAL_SAVE_GP(); switch (op) { case CYGNUM_CALL_IF_FLASH_CFG_GET: res = flash_get_config(fc->key, fc->val, fc->type); break; case CYGNUM_CALL_IF_FLASH_CFG_NEXT: res = flash_next_key(fc->key, fc->keylen, &fc->type, &fc->offset); break; case CYGNUM_CALL_IF_FLASH_CFG_SET: res = flash_set_config(fc->key, fc->val, fc->type); break; default: // nothing else supported yet - though it is expected that "set" // will fit the same set of arguments, potentially. break; } CYGARC_HAL_RESTORE_GP(); return res;}#endif#ifdef CYGOPT_REDBOOT_FISstatic __call_if_flash_fis_op_fn_t flash_fis_op;static cyg_boolflash_fis_op( int op, char *name, void *val){ cyg_bool res = false; struct fis_image_desc *fis; int num; CYGARC_HAL_SAVE_GP(); fis = fis_lookup(name, &num); if(fis != NULL) { switch ( op ) { case CYGNUM_CALL_IF_FLASH_FIS_GET_FLASH_BASE: *(CYG_ADDRESS *)val = fis->flash_base; res = true; break; case CYGNUM_CALL_IF_FLASH_FIS_GET_SIZE: *(unsigned long *)val = fis->size; res = true; break; case CYGNUM_CALL_IF_FLASH_FIS_GET_MEM_BASE: *(CYG_ADDRESS *)val = fis->mem_base; res = true; break; case CYGNUM_CALL_IF_FLASH_FIS_GET_ENTRY_POINT: *(CYG_ADDRESS *)val = fis->entry_point; res = true; break; case CYGNUM_CALL_IF_FLASH_FIS_GET_DATA_LENGTH: *(unsigned long *)val = fis->data_length; res = true; break; case CYGNUM_CALL_IF_FLASH_FIS_GET_DESC_CKSUM: *(unsigned long *)val = fis->desc_cksum; res = true; break; case CYGNUM_CALL_IF_FLASH_FIS_GET_FILE_CKSUM: *(unsigned long *)val = fis->file_cksum; res = true; break; default: break; } } CYGARC_HAL_RESTORE_GP(); return res;}#endif//----------------------------// Delay uS#ifdef CYGSEM_HAL_VIRTUAL_VECTOR_CLAIM_DELAY_USstatic __call_if_delay_us_t delay_us;static voiddelay_us(cyg_int32 usecs){ CYGARC_HAL_SAVE_GP();#ifdef CYGPKG_KERNEL { cyg_int32 start, elapsed, elapsed_usec; cyg_int32 slice; cyg_int32 usec_per_period = CYGNUM_HAL_RTC_NUMERATOR/CYGNUM_HAL_RTC_DENOMINATOR/1000; cyg_int32 ticks_per_usec = CYGNUM_KERNEL_COUNTERS_RTC_PERIOD/usec_per_period; 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 would also // be problems figuring out when the timer wrapped. We // may lose a tick or two for each cycle but it shouldn't // matter much. // The tests against CYGNUM_KERNEL_COUNTERS_RTC_PERIOD // check for a value that would cause a 32 bit signed // multiply to overflow. But this also implies that just // multiplying by ticks_per_usec will yield a good // approximation. Otherwise we need to do the full // multiply+divide to get sufficient accuracy. Note that // this test is actually constant, so the compiler will // eliminate it and only compile the branch that is // selected. if( usecs > usec_per_period/2 ) slice = CYGNUM_KERNEL_COUNTERS_RTC_PERIOD/2; else if( CYGNUM_KERNEL_COUNTERS_RTC_PERIOD/2 >= 0x7FFFFFFF/usec_per_period ) slice = usecs * ticks_per_usec; else { slice = usecs*CYGNUM_KERNEL_COUNTERS_RTC_PERIOD; slice /= usec_per_period; } 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. if( CYGNUM_KERNEL_COUNTERS_RTC_PERIOD >= 0x7FFFFFFF/usec_per_period ) elapsed_usec = elapsed / ticks_per_usec; else { elapsed_usec = elapsed * usec_per_period; elapsed_usec = elapsed_usec / CYGNUM_KERNEL_COUNTERS_RTC_PERIOD; } // It is possible for elapsed_usec to end up zero in some // circumstances and we could end up looping indefinitely. // Avoid that by ensuring that we always decrement usec by // at least 1 each time. usecs -= elapsed_usec ? elapsed_usec : 1; } while (usecs > 0); }#else // CYGPKG_KERNEL#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 10 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 < 10; i++); }#endif // HAL_DELAY_US#endif // CYGPKG_KERNEL CYGARC_HAL_RESTORE_GP();}#endif // CYGSEM_HAL_VIRTUAL_VECTOR_CLAIM_DELAY_US// Reset functions#ifdef CYGSEM_HAL_VIRTUAL_VECTOR_CLAIM_RESETstatic __call_if_reset_t reset;static voidreset(void){ CYGARC_HAL_SAVE_GP(); // With luck, the platform defines some magic that will cause a hardware // reset.#ifdef HAL_PLATFORM_RESET HAL_PLATFORM_RESET();#endif#ifdef HAL_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_PLATFORM_RESET_ENTRY;#else#error " no RESET_ENTRY"#endif CYG_FAIL("Reset failed"); CYGARC_HAL_RESTORE_GP();}#endif//------------------------------------// NOP service#if defined(CYGSEM_HAL_VIRTUAL_VECTOR_INIT_WHOLE_TABLE) || \ defined(CYGSEM_HAL_VIRTUAL_VECTOR_CLAIM_COMMS)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;}#endif//----------------------------------// Comm controls#ifdef CYGSEM_HAL_VIRTUAL_VECTOR_CLAIM_COMMS#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:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -