📄 hal_if.c
字号:
static voidcyg_hal_diag_mangler_gdb_putc(void* __ch_data, cyg_uint8 c){#if CYGNUM_HAL_DEBUG_GDB_PROTOCOL_RETRIES != 0 int tries = CYGNUM_HAL_DEBUG_GDB_PROTOCOL_RETRIES;#endif // No need to send CRs if( c == '\r' ) return; CYGARC_HAL_SAVE_GP(); __mangler_line[__mangler_pos++] = c; if( c == '\n' || __mangler_pos == sizeof(__mangler_line) ) cyg_hal_diag_mangler_gdb_flush(__ch_data); CYGARC_HAL_RESTORE_GP();}static voidcyg_hal_diag_mangler_gdb_write(void* __ch_data, const cyg_uint8* __buf, cyg_uint32 __len){ CYGARC_HAL_SAVE_GP(); while(__len-- > 0) cyg_hal_diag_mangler_gdb_putc(__ch_data, *__buf++); CYGARC_HAL_RESTORE_GP();}static voidcyg_hal_diag_mangler_gdb_read(void* __ch_data, cyg_uint8* __buf, cyg_uint32 __len){ CYGARC_HAL_SAVE_GP(); while(__len-- > 0) *__buf++ = cyg_hal_diag_mangler_gdb_getc(__ch_data); CYGARC_HAL_RESTORE_GP();}static intcyg_hal_diag_mangler_gdb_control(void *__ch_data, __comm_control_cmd_t __func, ...){ CYGARC_HAL_SAVE_GP(); if (__func == __COMMCTL_FLUSH_OUTPUT) cyg_hal_diag_mangler_gdb_flush(__ch_data); CYGARC_HAL_RESTORE_GP(); return 0;}// This is the COMMS init function. It gets called both by the stubs// and diag init code to initialize the COMMS mangler channel table -// that's all. The callers have to decide whether to actually use this// channel.voidcyg_hal_diag_mangler_gdb_init(void){ hal_virtual_comm_table_t* comm; int cur = CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT); // Initialize mangler procs CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_CALL_IF_SET_COMM_ID_MANGLER); comm = CYGACC_CALL_IF_CONSOLE_PROCS(); CYGACC_COMM_IF_WRITE_SET(*comm, cyg_hal_diag_mangler_gdb_write); CYGACC_COMM_IF_READ_SET(*comm, cyg_hal_diag_mangler_gdb_read); CYGACC_COMM_IF_PUTC_SET(*comm, cyg_hal_diag_mangler_gdb_putc); CYGACC_COMM_IF_GETC_SET(*comm, cyg_hal_diag_mangler_gdb_getc); CYGACC_COMM_IF_CONTROL_SET(*comm, cyg_hal_diag_mangler_gdb_control); // Restore the original console channel. CYGACC_CALL_IF_SET_CONSOLE_COMM(cur);}//-----------------------------------------------------------------------------// Null console output mangler// COMMS init function at end.// This gets called via the virtual vector console comms entry and// just forwards IO to the debug comms entries.// This differs from setting the console channel to the same as the// debug channel in that console output will go to the debug channel// even if the debug channel is changed.static cyg_uint8cyg_hal_diag_mangler_null_getc(void* __ch_data){ cyg_uint8 __ch; hal_virtual_comm_table_t* __chan = CYGACC_CALL_IF_DEBUG_PROCS(); CYGARC_HAL_SAVE_GP(); __ch = CYGACC_COMM_IF_GETC(*__chan); CYGARC_HAL_RESTORE_GP(); return __ch;}static voidcyg_hal_diag_mangler_null_putc(void* __ch_data, cyg_uint8 c){ hal_virtual_comm_table_t* __chan = CYGACC_CALL_IF_DEBUG_PROCS(); CYGARC_HAL_SAVE_GP(); CYGACC_COMM_IF_PUTC(*__chan, c); CYGARC_HAL_RESTORE_GP();}static voidcyg_hal_diag_mangler_null_write(void* __ch_data, const cyg_uint8* __buf, cyg_uint32 __len){ CYGARC_HAL_SAVE_GP(); while(__len-- > 0) cyg_hal_diag_mangler_null_putc(__ch_data, *__buf++); CYGARC_HAL_RESTORE_GP();}static voidcyg_hal_diag_mangler_null_read(void* __ch_data, cyg_uint8* __buf, cyg_uint32 __len){ CYGARC_HAL_SAVE_GP(); while(__len-- > 0) *__buf++ = cyg_hal_diag_mangler_null_getc(__ch_data); CYGARC_HAL_RESTORE_GP();}static intcyg_hal_diag_mangler_null_control(void *__ch_data, __comm_control_cmd_t __func, ...){ // Do nothing (yet). return 0;}// This is the COMMS init function. It gets called both by the stubs// and diag init code to initialize the COMMS mangler channel table -// that's all. The callers have to decide whether to actually use this// channel.voidcyg_hal_diag_mangler_null_init(void){ hal_virtual_comm_table_t* comm; int cur = CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT); // Initialize mangler procs CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_CALL_IF_SET_COMM_ID_MANGLER); comm = CYGACC_CALL_IF_CONSOLE_PROCS(); CYGACC_COMM_IF_WRITE_SET(*comm, cyg_hal_diag_mangler_null_write); CYGACC_COMM_IF_READ_SET(*comm, cyg_hal_diag_mangler_null_read); CYGACC_COMM_IF_PUTC_SET(*comm, cyg_hal_diag_mangler_null_putc); CYGACC_COMM_IF_GETC_SET(*comm, cyg_hal_diag_mangler_null_getc); CYGACC_COMM_IF_CONTROL_SET(*comm, cyg_hal_diag_mangler_null_control); // Restore the original console channel. CYGACC_CALL_IF_SET_CONSOLE_COMM(cur);}//-----------------------------------------------------------------------------// Console IO functions that adhere to the virtual vector table semantics in// order to ensure proper debug agent mangling when required.//externC void cyg_hal_plf_comms_init(void);voidhal_if_diag_init(void){ // This function may be called from various places and the code // should only run once. static cyg_uint8 called = 0; if (called) return; called = 1;#ifndef CYGSEM_HAL_VIRTUAL_VECTOR_INHERIT_CONSOLE#if defined(CYGDBG_HAL_DIAG_TO_DEBUG_CHAN) // Use the mangler channel, which in turn uses the debug channel. CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_CALL_IF_SET_COMM_ID_MANGLER); // Initialize the mangler channel.#if defined(CYGSEM_HAL_DIAG_MANGLER_GDB) cyg_hal_diag_mangler_gdb_init();#elif defined(CYGSEM_HAL_DIAG_MANGLER_None) cyg_hal_diag_mangler_null_init();#endif#else // CYGDBG_HAL_DIAG_TO_DEBUG_CHAN // Use an actual (raw) IO channel CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL);#endif // CYGDBG_HAL_DIAG_TO_DEBUG_CHAN#endif // CYGSEM_HAL_VIRTUAL_VECTOR_INHERIT_CONSOLE}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, c); else { __chan = CYGACC_CALL_IF_DEBUG_PROCS(); // FIXME: What should be done if assertions are not enabled? // This is a bad bad situation - we have no means for diag // output; we want to hit a breakpoint to alert the developer // or something like that. CYG_ASSERT(__chan, "No valid channel set"); CYGACC_COMM_IF_PUTC(*__chan, c); } // Check interrupt flag if (CYGACC_CALL_IF_CONSOLE_INTERRUPT_FLAG()) { CYGACC_CALL_IF_CONSOLE_INTERRUPT_FLAG_SET(0); cyg_hal_user_break(0); }}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); else { __chan = CYGACC_CALL_IF_DEBUG_PROCS(); // FIXME: What should be done if assertions are not enabled? // This is a bad bad situation - we have no means for diag // output; we want to hit a breakpoint to alert the developer // or something like that. CYG_ASSERT(__chan, "No valid channel set"); *c = CYGACC_COMM_IF_GETC(*__chan); }}#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;voidhal_ctrlc_isr_init(void){ // A ROM monitor never enables the interrupt itself. This is left // to the (RAM) application.#ifndef CYGSEM_HAL_ROM_MONITOR hal_virtual_comm_table_t* __chan = CYGACC_CALL_IF_DEBUG_PROCS();#if 1 // Prevents crash on older stubs int v_m; // Allow only ctrl-c interrupt enabling when version in table is // below legal max and above the necessary service, and _not_ // the value we set it to below. v_m = CYGACC_CALL_IF_VERSION() & CYGNUM_CALL_IF_TABLE_VERSION_CALL_MASK; if (v_m >= CYGNUM_CALL_IF_TABLE_VERSION_CALL_MAX || v_m < CYGNUM_CALL_IF_SET_DEBUG_COMM || v_m == CYGNUM_CALL_IF_TABLE_VERSION_CALL_HACK) return; // Now trash that value - otherwise downloading an image with // builtin stubs on a board with older stubs (which will cause the // version to be set to VERSION_CALL) may cause all subsequent // runs to (wrongly) fall through to the below code. If there is // a new stub on the board, it will reinitialize the version field // on reset. Yes, this is a gross hack! CYGACC_CALL_IF_VERSION_SET(CYGNUM_CALL_IF_TABLE_VERSION_CALL_HACK);#endif // We can only enable interrupts on a valid debug channel. if (__chan) CYGACC_COMM_IF_CONTROL(*__chan, __COMMCTL_IRQ_ENABLE);#endif}cyg_uint32hal_ctrlc_isr(CYG_ADDRWORD vector, CYG_ADDRWORD data){ hal_virtual_comm_table_t* __chan = CYGACC_CALL_IF_DEBUG_PROCS(); int isr_ret = 0, ctrlc = 0; if (__chan) { isr_ret = CYGACC_COMM_IF_DBG_ISR(*__chan, &ctrlc, vector, data); if (ctrlc) cyg_hal_user_break( (CYG_ADDRWORD *)hal_saved_interrupt_state ); } return isr_ret;}cyg_boolhal_ctrlc_check(CYG_ADDRWORD vector, CYG_ADDRWORD data){ hal_virtual_comm_table_t* __chan = CYGACC_CALL_IF_DEBUG_PROCS(); int gdb_vector = vector-1; int isr_ret, ctrlc = 0; // This check only to avoid crash on older stubs in case of unhandled // interrupts. It is a bit messy, but required in a transition period. if (__chan && (CYGNUM_CALL_IF_TABLE_VERSION_CALL_HACK == (CYGACC_CALL_IF_VERSION() & CYGNUM_CALL_IF_TABLE_VERSION_CALL_MASK))){ gdb_vector = CYGACC_COMM_IF_CONTROL(*__chan, __COMMCTL_DBG_ISR_VECTOR); } if (vector == gdb_vector) { isr_ret = CYGACC_COMM_IF_DBG_ISR(*__chan, &ctrlc, vector, data); if (ctrlc) { cyg_hal_user_break( (CYG_ADDRWORD *)hal_saved_interrupt_state ); return true; } } return false;}#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,// for client configurations it will patch the existing table as per// configuration.voidhal_if_init(void){ //********************************************************************** // // Note that if your RAM application is configured to initialize // the whole table _or_ the communication channels, you _cannot_ // step through this function with the debugger. If your channel // configurations are set to the default, you should be able to // simply step over this function though (or use 'finish' once you // have entered this function if that GDB command works). // // If you really do need to debug this code, the best approach is // to have a working RedBoot / GDB stub in ROM and then change the // hal_virtual_vector_table to reside at some other address in the // RAM configuration than that used by the ROM monitor. Then // you'll be able to use the ROM monitor to debug the below code // and check that it does the right thing. // // Note that if you have a ROM monitor in ROM/flash which does // support virtual vectors, you should be able to disable the // option CYGSEM_HAL_VIRTUAL_VECTOR_INIT_WHOLE_TABLE. On some // targets (which predate the introduction of virtual vectors) // that option is enabled per default and needs to be explicitly // disabled when you have an updated ROM monitor. // //**********************************************************************#ifdef CYGSEM_HAL_VIRTUAL_VECTOR_INIT_WHOLE_TABLE { int i; // 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; // Version number CYGACC_CALL_IF_VERSION_SET(CYGNUM_CALL_IF_TABLE_VERSION_CALL |((CYG_ADDRWORD)CYGNUM_CALL_IF_TABLE_VERSION_COMM<<CYGNUM_CALL_IF_TABLE_VERSION_COMM_shift)); }#endif // Miscellaneous services with wrappers in this file.#ifdef CYGSEM_HAL_VIRTUAL_VECTOR_CLAIM_RESET CYGACC_CALL_IF_RESET_SET(reset); CYGACC_CALL_IF_KILL_VECTOR_SET(kill_by_reset);#endif#ifdef CYGSEM_HAL_VIRTUAL_VECTOR_CLAIM_DELAY_US CYGACC_CALL_IF_DELAY_US_SET(delay_us);#endif#ifdef CYGSEM_HAL_VIRTUAL_VECTOR_CLAIM_CACHE // Cache functions CYGACC_CALL_IF_FLUSH_ICACHE_SET(flush_icache); CYGACC_CALL_IF_FLUSH_DCACHE_SET(flush_dcache);#endif#ifdef CYGSEM_REDBOOT_FLASH_CONFIG CYGACC_CALL_IF_FLASH_CFG_OP_SET(flash_config_op);#endif // Data entries not currently supported in eCos#ifdef CYGSEM_HAL_VIRTUAL_VECTOR_CLAIM_DATA CYGACC_CALL_IF_DBG_DATA_SET(0);#endif#ifdef CYGSEM_HAL_VIRTUAL_VECTOR_CLAIM_VERSION CYGACC_CALL_IF_MONITOR_VERSION_SET(0);#endif // Comm controls#ifdef CYGSEM_HAL_VIRTUAL_VECTOR_CLAIM_COMMS { int i, j; // Clear out tables with safe dummy function. for (j = 0; j < CYGNUM_HAL_VIRTUAL_VECTOR_NUM_CHANNELS+1; j++) for (i = 0; i < CYGNUM_COMM_IF_TABLE_SIZE; i++) comm_channels[j][i] = (CYG_ADDRWORD) &nop_service; // Set accessor functions CYGACC_CALL_IF_SET_DEBUG_COMM_SET(set_debug_comm); CYGACC_CALL_IF_SET_CONSOLE_COMM_SET(set_console_comm); // Initialize console/debug procs. Note that these _must_ // be set to empty before the comms init call. set_debug_comm(CYGNUM_CALL_IF_SET_COMM_ID_EMPTY); set_console_comm(CYGNUM_CALL_IF_SET_COMM_ID_EMPTY); // Initialize channels. This used to be done in // hal_diag_init() and the stub initHardware() functions, but // it makes more sense to have here. cyg_hal_plf_comms_init(); // Always set the debug channel. If stubs are included, it is // necessary. If no stubs are included it does not hurt and is // likely to be required by the hal_if_diag_init code anyway // as it may rely on it if using a mangler. set_debug_comm(CYGNUM_HAL_VIRTUAL_VECTOR_DEBUG_CHANNEL); // Set console channel to a safe default. hal_if_diag_init // will override with console channel or mangler if necessary. set_console_comm(CYGNUM_HAL_VIRTUAL_VECTOR_DEBUG_CHANNEL); } // Reset console interrupt flag. CYGACC_CALL_IF_CONSOLE_INTERRUPT_FLAG_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#if 0 != CYGINT_HAL_PLF_IF_INIT // Call platform specific initializations - should only be used // to augment what has already been set up, etc. plf_if_init();#endif}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -