📄 hal_stub.c
字号:
// Expand the HAL_SavedRegisters structure into the GDB register // array format. HAL_GET_GDB_REGISTERS(®isters[0], _hal_registers); _registers = ®isters[0]; if (!orig_registers_set) { for (i = 0; i < (sizeof(registers)/sizeof(registers[0])); i++) orig_registers[i] = registers[i]; orig_registers_set = 1; if (orig_registers[PC] == (target_register_t)&_breakinst) orig_registers[PC] += HAL_BREAKINST_SIZE; } #ifdef HAL_STUB_PLATFORM_STUBS_FIXUP // Some architectures may need to fix the PC in case of a partial // or fully executed trap instruction. GDB only takes correct action // when the PC is pointing to the breakpoint instruction it set. // // Most architectures would leave PC pointing at the trap // instruction itself though, and so do not need to do anything // special. HAL_STUB_PLATFORM_STUBS_FIXUP();#endif#ifdef CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT // If we continued instead of stepping, when there was a break set // ie. we were stepping within a critical region, clear the break, and // that flag. If we stopped for some other reason, this has no effect. if ( cyg_hal_gdb_running_step ) { cyg_hal_gdb_running_step = 0; cyg_hal_gdb_remove_break(get_register (PC)); } // FIXME: (there may be a better way to do this) // If we hit a breakpoint set by the gdb interrupt stub, make it // seem like an interrupt rather than having hit a breakpoint. cyg_hal_gdb_break = cyg_hal_gdb_remove_break(get_register (PC));#endif#if defined(HAL_STUB_HW_WATCHPOINT) || defined(HAL_STUB_HW_BREAKPOINT) // For HW watchpoint/breakpoint support, we need to know if we // stopped because of watchpoint or hw break. We do that here // before GDB has a chance to remove the watchpoints and save // the information for later use in building response packets. _hw_stop_reason = HAL_STUB_IS_STOPPED_BY_HARDWARE(_watch_data_addr);#endif }// Called at stub *exit*static void handle_exception_init( void ){ // Compact register array again. HAL_SET_GDB_REGISTERS(_hal_registers, ®isters[0]); interruptible(1);}//-----------------------------------------------------------------------------// Initialization.// Signal handler.int cyg_hal_process_signal (int signal){ // We don't care about the signal (atm). return 0;}// Install the standard set of trap handlers for the stub.void __install_traps (void){ // Set signal handling vector so we can treat 'C<signum>' as 'c'. __process_signal_vec = &cyg_hal_process_signal; // Set exit vector to reset vector. This will allow automatic reset on // some platforms. __process_exit_vec = &handle_exception_exit; __cleanup_vec = &handle_exception_cleanup; __init_vec = &handle_exception_init;#ifndef CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT // this should go away#ifdef CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT // Control of GDB interrupts. __interruptible_control = HAL_STUB_PLATFORM_INTERRUPTIBLE;#endif#endif // Nothing further to do, handle_exception will be called when an // exception occurs.}// Initialize the hardware.void initHardware (void) { static int initialized = 0; if (initialized) return; initialized = 1; // Get serial port initialized. HAL_STUB_PLATFORM_INIT_SERIAL();#ifdef CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT { 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_gdb_diag_write); CYGACC_COMM_IF_READ_SET(*comm, cyg_hal_gdb_diag_read); CYGACC_COMM_IF_PUTC_SET(*comm, cyg_hal_gdb_diag_putc); CYGACC_COMM_IF_GETC_SET(*comm, cyg_hal_gdb_diag_getc); CYGACC_COMM_IF_CONTROL_SET(*comm, cyg_hal_gdb_diag_control); // Now either restore the previous console channel, or let the // mangler stay in its place. The latter happens if the // console channel was previously unspecified, or if the // previous channel matches the used for GDB communication. if (CYGNUM_CALL_IF_SET_COMM_ID_EMPTY != cur && CYGNUM_HAL_VIRTUAL_VECTOR_DEBUG_CHANNEL != cur) CYGACC_CALL_IF_SET_CONSOLE_COMM(cur); // Set the debug channel. CYGACC_CALL_IF_SET_DEBUG_COMM(CYGNUM_HAL_VIRTUAL_VECTOR_DEBUG_CHANNEL); }#endif // CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT#ifdef HAL_STUB_PLATFORM_INIT // If the platform defines any initialization code, call it here. HAL_STUB_PLATFORM_INIT();#endif #ifndef CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT // this should go away#ifdef CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT // Get interrupt handler initialized. HAL_STUB_PLATFORM_INIT_BREAK_IRQ();#endif#endif // !CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT}// Reset the board.void __reset (void){#ifdef CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT __call_if_reset_t __rom_reset = CYGACC_CALL_IF_RESET_GET(); if (__rom_reset) __rom_reset();#else HAL_STUB_PLATFORM_RESET();#endif}//-----------------------------------------------------------------------------// Breakpoint support.#ifndef CYGPKG_HAL_ARM// This function will generate a breakpoint exception. It is used at// the beginning of a program to sync up with a debugger and can be// used otherwise as a quick means to stop program execution and// "break" into the debugger.voidbreakpoint(){ HAL_BREAKPOINT(_breakinst);}// This function returns the opcode for a 'trap' instruction.unsigned long __break_opcode (){ return HAL_BREAKINST;}#endif//-----------------------------------------------------------------------------// Write the 'T' packet in BUFFER. SIGVAL is the signal the program received.void __build_t_packet (int sigval, char *buf){ target_register_t addr; char *ptr = buf; *ptr++ = 'T'; *ptr++ = __tohex (sigval >> 4); *ptr++ = __tohex (sigval);#ifdef CYGDBG_HAL_DEBUG_GDB_THREAD_SUPPORT // Include thread ID if thread manipulation is required. { int id = dbg_currthread_id (); if (id != 0) { *ptr++ = 't'; *ptr++ = 'h'; *ptr++ = 'r'; *ptr++ = 'e'; *ptr++ = 'a'; *ptr++ = 'd'; *ptr++ = ':';#if (CYG_BYTEORDER == CYG_LSBFIRST) // FIXME: Temporary workaround for PR 18903. Thread ID must be // big-endian in the T packet. { unsigned char* bep = (unsigned char*)&id; int be_id; be_id = id; *bep++ = (be_id >> 24) & 0xff ; *bep++ = (be_id >> 16) & 0xff ; *bep++ = (be_id >> 8) & 0xff ; *bep++ = (be_id & 0xff) ; }#endif ptr = __mem2hex((char *)&id, ptr, sizeof(id), 0); *ptr++ = ';'; } }#endif#ifdef HAL_STUB_HW_WATCHPOINT switch(_hw_stop_reason) { case HAL_STUB_HW_STOP_WATCH: case HAL_STUB_HW_STOP_RWATCH: case HAL_STUB_HW_STOP_AWATCH: strcpy(ptr, _hw_stop_str[_hw_stop_reason]); ptr += strlen(_hw_stop_str[_hw_stop_reason]); *ptr++ = ':'; // Send address MSB first ptr += __intToHex(ptr, (target_register_t)_watch_data_addr, sizeof(_watch_data_addr) * 8); *ptr++ = ';'; break; default: break; }#endif *ptr++ = __tohex (PC >> 4); *ptr++ = __tohex (PC); *ptr++ = ':'; addr = get_register (PC); if (sizeof(addr) < REGSIZE(PC)) { // GDB is expecting REGSIZE(PC) number of bytes. // We only have sizeof(addr) number. Let's fill // the appropriate number of bytes intelligently. target_register_t extend_val = 0;#ifdef CYGARC_SIGN_EXTEND_REGISTERS { unsigned long bits_in_addr = (sizeof(addr) << 3); // ie Size in bytes * 8 target_register_t sign_bit_mask = (1 << (bits_in_addr - 1)); if ((addr & sign_bit_mask) == sign_bit_mask) extend_val = ~0; }#endif ptr = __mem2hex((char *)&extend_val, ptr, REGSIZE(PC) - sizeof(addr), 0); } ptr = __mem2hex((char *)&addr, ptr, sizeof(addr), 0); *ptr++ = ';'; *ptr++ = __tohex (SP >> 4); *ptr++ = __tohex (SP); *ptr++ = ':'; addr = (target_register_t) get_register (SP); if (sizeof(addr) < REGSIZE(SP)) { // GDB is expecting REGSIZE(SP) number of bytes. // We only have sizeof(addr) number. Let's fill // the appropriate number of bytes intelligently. target_register_t extend_val = 0;#ifdef CYGARC_SIGN_EXTEND_REGISTERS { unsigned long bits_in_addr = (sizeof(addr) << 3); // ie Size in bytes * 8 target_register_t sign_bit_mask = (1 << (bits_in_addr - 1)); if ((addr & sign_bit_mask) == sign_bit_mask) extend_val = ~0; }#endif ptr = __mem2hex((char *)&extend_val, ptr, REGSIZE(SP) - sizeof(addr), 0); } ptr = __mem2hex((char *)&addr, ptr, sizeof(addr), 0); *ptr++ = ';'; *ptr++ = 0;}//-----------------------------------------------------------------------------// Cache functions.// Perform the specified operation on the instruction cache. // Returns 1 if the cache is enabled, 0 otherwise.int __instruction_cache (cache_control_t request){ int state = 1; switch (request) { case CACHE_ENABLE: HAL_ICACHE_ENABLE(); break; case CACHE_DISABLE: HAL_ICACHE_DISABLE(); state = 0; break; case CACHE_FLUSH: HAL_ICACHE_SYNC(); break; case CACHE_NOOP: /* fall through */ default: break; }#ifdef HAL_ICACHE_IS_ENABLED HAL_ICACHE_IS_ENABLED(state);#endif return state;}// Perform the specified operation on the data cache. // Returns 1 if the cache is enabled, 0 otherwise.int __data_cache (cache_control_t request){ int state = 1; switch (request) { case CACHE_ENABLE: HAL_DCACHE_ENABLE(); break; case CACHE_DISABLE: HAL_DCACHE_DISABLE(); state = 0; break; case CACHE_FLUSH: HAL_DCACHE_SYNC(); break; case CACHE_NOOP: /* fall through */ default: break; }#ifdef HAL_DCACHE_IS_ENABLED HAL_DCACHE_IS_ENABLED(state);#endif return state;}//-----------------------------------------------------------------------------// Memory accessor functions.// The __mem_fault_handler pointer is volatile since it is only// set/cleared by the function below - which does not rely on any// other functions, so the compiler may decide to not bother updating// the pointer at all. If any of the memory accesses cause an// exception, the pointer must be set to ensure the exception handler// can make use of it.void* volatile __mem_fault_handler = (void *)0;/* These are the "arguments" to __do_read_mem and __do_write_mem, which are passed as globals to avoid squeezing them thru __set_mem_fault_trap. */static volatile target_register_t memCount;static void__do_copy_mem (unsigned char* src, unsigned char* dst){ unsigned long *long_dst; unsigned long *long_src; unsigned short *short_dst; unsigned short *short_src; __mem_fault = 1; /* Defaults to 'fail'. Is cleared */ /* when the copy loop completes. */ __mem_fault_handler = &&err; // See if it's safe to do multi-byte, aligned operations while (memCount) { if ((memCount >= sizeof(long)) && (((target_register_t)dst & (sizeof(long)-1)) == 0) && (((target_register_t)src & (sizeof(long)-1)) == 0)) { long_dst = (unsigned long *)dst; long_src = (unsigned long *)src; *long_dst++ = *long_src++; memCount -= sizeof(long); dst = (unsigned char *)long_dst; src = (unsigned char *)long_src; } else if ((memCount >= sizeof(short)) && (((target_register_t)dst & (sizeof(short)-1)) == 0) && (((target_register_t)src & (sizeof(short)-1)) == 0)) { short_dst = (unsigned short *)dst; short_src = (unsigned short *)src; *short_dst++ = *short_src++; memCount -= sizeof(short); dst = (unsigned char *)short_dst; src = (unsigned char *)short_src; } else { *dst++ = *src++; memCount--; } } __mem_fault = 0; err: __mem_fault_handler = (void *)0;}/* * __read_mem_safe: * Get contents of target memory, abort on error. */int__read_mem_safe (void *dst, void *src, int count){ memCount = count; __do_copy_mem((unsigned char*) src, (unsigned char*) dst); return count - memCount; // return number of bytes successfully read}/* * __write_mem_safe: * Set contents of target memory, abort on error. */int__write_mem_safe (void *src, void *dst, int count){ memCount = count; __do_copy_mem((unsigned char*) src, (unsigned char*) dst); return count - memCount; // return number of bytes successfully written}//-----------------------------------------------------------------------------// Target extras?!int __process_target_query(char * pkt, char * out, int maxOut){ return 0 ; }int __process_target_set(char * pkt, char * out, int maxout){ return 0 ; }int __process_target_packet(char * pkt, char * out, int maxout){ return 0 ; }// GDB string output, making sure interrupts are disabled.// This function gets used by some diag output functions.void hal_output_gdb_string(target_register_t str, int string_len){ unsigned long __state; HAL_DISABLE_INTERRUPTS(__state); __output_gdb_string(str, string_len); HAL_RESTORE_INTERRUPTS(__state);}#endif // CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -