📄 hal_stub.c
字号:
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
}
}
//-----------------------------------------------------------------------------
// eCos stub entry and exit magic.
#ifdef CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT
int cyg_hal_gdb_break;
#endif
#ifdef CYGPKG_REDBOOT
// Trampoline for returning to RedBoot from exception/stub code
static void
return_from_stub(int exit_status)
{
CYGACC_CALL_IF_MONITOR_RETURN(exit_status);
}
#endif
// Called at stub *kill*
static void
handle_exception_exit( void )
{
#ifdef CYGPKG_REDBOOT
#ifdef CYGSEM_REDBOOT_BSP_SYSCALLS_GPROF
{ // Reset the timer to default and cancel any callback
extern void sys_profile_reset(void);
sys_profile_reset();
}
#endif // CYGSEM_REDBOOT_BSP_SYSCALLS_GPROF
set_pc((target_register_t)return_from_stub);
#else
int i;
for (i = 0; i < (sizeof(registers)/sizeof(registers[0])); i++)
registers[i] = orig_registers[i];
#endif
}
// Called at stub *entry*
static void
handle_exception_cleanup( void )
{
#ifndef CYGPKG_REDBOOT
static int orig_registers_set = 0;
#endif
interruptible(0);
// Expand the HAL_SavedRegisters structure into the GDB register
// array format.
HAL_GET_GDB_REGISTERS(®isters[0], _hal_registers);
_registers = ®isters[0];
#ifndef CYGPKG_REDBOOT
if (!orig_registers_set) {
int i;
for (i = 0; i < (sizeof(registers)/sizeof(registers[0])); i++)
orig_registers[i] = registers[i];
_registers = &orig_registers[0];
if (__is_breakpoint_function ())
__skipinst ();
_registers = ®isters[0];
orig_registers_set = 1;
}
#endif
#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;
__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 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_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.
void
breakpoint()
{
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;
target_register_t extend_val = 0;
*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:
#ifdef HAL_STUB_HW_SEND_STOP_REASON_TEXT
// Not all GDBs understand this.
strcpy(ptr, _hw_stop_str[_hw_stop_reason]);
ptr += strlen(_hw_stop_str[_hw_stop_reason]);
#endif
*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.
#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
}
#if (CYG_BYTEORDER == CYG_MSBFIRST)
ptr = __mem2hex((char *)&extend_val, ptr, REGSIZE(PC) - sizeof(addr), 0);
#endif
ptr = __mem2hex((char *)&addr, ptr, sizeof(addr), 0);
#if (CYG_BYTEORDER == CYG_LSBFIRST)
ptr = __mem2hex((char *)&extend_val, ptr, REGSIZE(PC) - sizeof(addr), 0);
#endif
*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.
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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -