📄 hal_stub.c
字号:
//=============================================================================//// hal_stub.c//// Helper functions for stub, specific to eCos HAL////=============================================================================//####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, 2001 Red Hat, Inc. // All Rights Reserved. // ------------------------------------------- // //####COPYRIGHTEND####//=============================================================================//#####DESCRIPTIONBEGIN####//// Author(s): jskov (based on powerpc/cogent hal_stub.c)// Contributors:jskov, dmoseley// Date: 1999-02-12// Purpose: Helper functions for stub, specific to eCos HAL// Description: Parts of the GDB stub requirements are provided by// the eCos HAL, rather than target and/or board specific// code. ////####DESCRIPTIONEND####////=============================================================================#include <pkgconf/hal.h>#ifdef CYGPKG_CYGMON#include <pkgconf/cygmon.h>#endif#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS#include <cyg/hal/hal_stub.h> // Our header#include <cyg/hal/hal_arch.h> // HAL_BREAKINST#include <cyg/hal/hal_cache.h> // HAL_xCACHE_x#include <cyg/hal/hal_intr.h> // interrupt disable/restore#include <cyg/hal/hal_if.h> // ROM calling interface#include <cyg/hal/hal_misc.h> // Helper functions#ifdef CYGDBG_HAL_DEBUG_GDB_THREAD_SUPPORT#include <cyg/hal/dbg-threads-api.h> // dbg_currthread_id#endif#ifdef USE_LONG_NAMES_FOR_ENUM_REGNAMES#ifndef PC#define PC REG_PC#endif#ifndef SP#define SP REG_SP#endif#endif//-----------------------------------------------------------------------------// Extra eCos data.// Saved registers.HAL_SavedRegisters *_hal_registers;target_register_t registers[NUMREGS];target_register_t alt_registers[NUMREGS] ; // Thread or saved process statetarget_register_t * _registers = registers; // Pointer to current set of registerstarget_register_t orig_registers[NUMREGS]; // Registers to get back to original state#if defined(HAL_STUB_HW_WATCHPOINT) || defined(HAL_STUB_HW_BREAKPOINT)static int _hw_stop_reason; // Reason we were stopped by hw.// strings indexed by hw stop reasons defined in hal_stub.hstatic const char * const _hw_stop_str[] = { "", "hbreak", "watch", "rwatch", "awatch"};static void *_watch_data_addr; // The data address if stopped by watchpoint#endif// Register validity checking#ifdef CYGHWR_REGISTER_VALIDITY_CHECKINGint registers_valid[NUMREGS];int *_registers_valid = registers_valid;#endif#ifndef CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT // this should go away// Interrupt control.static volatile __PFI __interruptible_control;#endif//-----------------------------------------------------------------------------// Register access// Return the currently-saved value corresponding to register REG of// the exception context.target_register_t get_register (regnames_t reg){ return _registers[reg];}#ifdef CYGHWR_REGISTER_VALIDITY_CHECKING// Return the validity of register REG.intget_register_valid (regnames_t reg){ return _registers_valid[reg];}#endif// Store VALUE in the register corresponding to WHICH in the exception// context.void put_register (regnames_t which, target_register_t value){ _registers[which] = value;}//-----------------------------------------------------------------------------// Serial stuff#ifdef CYGPKG_CYGMONextern void ecos_bsp_console_putc(char);extern char ecos_bsp_console_getc(void);#endif// Write C to the current serial port.void putDebugChar (int c){#ifdef CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT __call_if_debug_procs_t __debug_procs = CYGACC_CALL_IF_DEBUG_PROCS(); CYGACC_COMM_IF_PUTC(*__debug_procs, c);#elif defined(CYGPKG_CYGMON) ecos_bsp_console_putc(c);#else HAL_STUB_PLATFORM_PUT_CHAR(c);#endif}// Read one character from the current serial port.int getDebugChar (void){#ifdef CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT __call_if_debug_procs_t __debug_procs = CYGACC_CALL_IF_DEBUG_PROCS(); return CYGACC_COMM_IF_GETC(*__debug_procs);#elif defined(CYGPKG_CYGMON) return ecos_bsp_console_getc();#else return HAL_STUB_PLATFORM_GET_CHAR();#endif}// Flush output channelvoidhal_flush_output(void){#ifdef CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT __call_if_debug_procs_t __debug_procs = CYGACC_CALL_IF_DEBUG_PROCS(); CYGACC_COMM_IF_CONTROL(*__debug_procs, __COMMCTL_FLUSH_OUTPUT);#endif}// Set the baud rate for the current serial port.void __set_baud_rate (int baud) {#ifdef CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT __call_if_debug_procs_t __debug_procs = CYGACC_CALL_IF_DEBUG_PROCS(); CYGACC_COMM_IF_CONTROL(*__debug_procs, __COMMCTL_SETBAUD, baud);#elif defined(CYGPKG_CYGMON) // FIXME!#else HAL_STUB_PLATFORM_SET_BAUD_RATE(baud);#endif}//-----------------------------------------------------------------------------// GDB interrupt (BREAK) support.#ifdef CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT#ifndef CYGPKG_HAL_ARM#if (HAL_BREAKINST_SIZE == 1)typedef cyg_uint8 t_inst;#elif (HAL_BREAKINST_SIZE == 2)typedef cyg_uint16 t_inst;#elif (HAL_BREAKINST_SIZE == 4)typedef cyg_uint32 t_inst;#else#error "Don't know how to handle that size"#endiftypedef struct{ t_inst *targetAddr; t_inst savedInstr;} instrBuffer;static instrBuffer break_buffer;volatile int cyg_hal_gdb_running_step = 0;void cyg_hal_gdb_place_break (target_register_t pc){ cyg_hal_gdb_interrupt( pc ); // Let's hope this becomes a drop-through:}void cyg_hal_gdb_interrupt (target_register_t pc){ CYGARC_HAL_SAVE_GP(); // Clear flag that we Continued instead of Stepping cyg_hal_gdb_running_step = 0; // and override existing break? So that a ^C takes effect... if (NULL != break_buffer.targetAddr) cyg_hal_gdb_remove_break( (target_register_t)break_buffer.targetAddr ); if (NULL == break_buffer.targetAddr) { break_buffer.targetAddr = (t_inst*) pc; break_buffer.savedInstr = *(t_inst*)pc; *(t_inst*)pc = (t_inst)HAL_BREAKINST; __data_cache(CACHE_FLUSH); __instruction_cache(CACHE_FLUSH); } CYGARC_HAL_RESTORE_GP();}int cyg_hal_gdb_remove_break (target_register_t pc){ if ( cyg_hal_gdb_running_step ) return 0; if ((t_inst*)pc == break_buffer.targetAddr) { *(t_inst*)pc = break_buffer.savedInstr; break_buffer.targetAddr = NULL; __data_cache(CACHE_FLUSH); __instruction_cache(CACHE_FLUSH); return 1; } return 0;}int cyg_hal_gdb_break_is_set (void){ if (NULL != break_buffer.targetAddr) { return 1; } return 0;}#endif // CYGPKG_HAL_ARM#endif // CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT// Use this function to disable serial interrupts whenever reply// characters are expected from GDB. The reason we want to control// whether the target can be interrupted or not is simply that GDB on// the host will be sending acknowledge characters/commands while the// stub is running - if serial interrupts were still active, the// characters would never reach the (polling) getDebugChar.static voidinterruptible(int state){ static int __interrupts_suspended = 0; if (state) { __interrupts_suspended--; if (0 >= __interrupts_suspended) { __interrupts_suspended = 0;#ifdef CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT // this _check_ should go away { hal_virtual_comm_table_t* __chan; __chan = CYGACC_CALL_IF_DEBUG_PROCS(); CYGACC_COMM_IF_CONTROL(*__chan, __COMMCTL_IRQ_ENABLE); }#else if (__interruptible_control) __interruptible_control(1);#endif } } else { __interrupts_suspended++; if (1 == __interrupts_suspended)#ifdef CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT // this _check_ should go away { hal_virtual_comm_table_t* __chan; __chan = CYGACC_CALL_IF_DEBUG_PROCS(); CYGACC_COMM_IF_CONTROL(*__chan, __COMMCTL_IRQ_DISABLE); }#else if (__interruptible_control) __interruptible_control(0);#endif }}#ifdef CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT//-----------------------------------------------------------------------------// GDB O-packetizer function.// This gets called via the virtual vector debug comms entry and// handles O-packetization. The debug comms entries are used for the// actual device IO.static cyg_uint8cyg_hal_gdb_diag_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_gdb_diag_putc(void* __ch_data, cyg_uint8 c){ static char line[100]; static int pos = 0; CYGARC_HAL_SAVE_GP(); // No need to send CRs if( c == '\r' ) return; line[pos++] = c; if( c == '\n' || pos == sizeof(line) ) { CYG_INTERRUPT_STATE old; hal_virtual_comm_table_t* __chan = CYGACC_CALL_IF_DEBUG_PROCS(); // Disable interrupts. This prevents GDB trying to interrupt us // while we are in the middle of sending a packet. The serial // receive interrupt will be seen when we re-enable interrupts // later.#ifdef CYG_HAL_STARTUP_ROM HAL_DISABLE_INTERRUPTS(old);#else CYG_HAL_GDB_ENTER_CRITICAL_IO_REGION(old);#endif while(1) { static const char hex[] = "0123456789ABCDEF"; cyg_uint8 csum = 0, c1; int i; CYGACC_COMM_IF_PUTC(*__chan, '$'); CYGACC_COMM_IF_PUTC(*__chan, 'O'); csum += 'O'; for( i = 0; i < pos; i++ ) { char ch = line[i]; char h = hex[(ch>>4)&0xF]; char l = hex[ch&0xF]; CYGACC_COMM_IF_PUTC(*__chan, h); CYGACC_COMM_IF_PUTC(*__chan, l); csum += h; csum += l; } CYGACC_COMM_IF_PUTC(*__chan, '#'); CYGACC_COMM_IF_PUTC(*__chan, hex[(csum>>4)&0xF]); CYGACC_COMM_IF_PUTC(*__chan, hex[csum&0xF]); nak: c1 = CYGACC_COMM_IF_GETC(*__chan); if( c1 == '+' ) break; if( cyg_hal_is_break( &c1 , 1 ) ) { // Caller's responsibility to react on this. CYGACC_CALL_IF_CONSOLE_INTERRUPT_FLAG_SET(1); break; } if( c1 != '-' ) goto nak; } pos = 0; // And re-enable interrupts#ifdef CYG_HAL_STARTUP_ROM HAL_RESTORE_INTERRUPTS(old);#else CYG_HAL_GDB_LEAVE_CRITICAL_IO_REGION(old);#endif } CYGARC_HAL_RESTORE_GP();}static voidcyg_hal_gdb_diag_write(void* __ch_data, const cyg_uint8* __buf, cyg_uint32 __len){ CYGARC_HAL_SAVE_GP(); while(__len-- > 0) cyg_hal_gdb_diag_putc(__ch_data, *__buf++); CYGARC_HAL_RESTORE_GP();}static voidcyg_hal_gdb_diag_read(void* __ch_data, cyg_uint8* __buf, cyg_uint32 __len){ CYGARC_HAL_SAVE_GP(); while(__len-- > 0) *__buf++ = cyg_hal_gdb_diag_getc(__ch_data); CYGARC_HAL_RESTORE_GP();}static intcyg_hal_gdb_diag_control(void *__ch_data, __comm_control_cmd_t __func, ...){ // Do nothing (yet). return 0;}#endif//-----------------------------------------------------------------------------// eCos stub entry and exit magic.#ifdef CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORTint cyg_hal_gdb_break;#endif// Called at stub *kill*static void handle_exception_exit( void ){ int i; for (i = 0; i < (sizeof(registers)/sizeof(registers[0])); i++) registers[i] = orig_registers[i];}// Called at stub *entry*static void handle_exception_cleanup( void ){ int i; static int orig_registers_set = 0; interruptible(0);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -