📄 hal_stub.c
字号:
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:
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.
#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.
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++ = ';';
HAL_STUB_ARCH_T_PACKET_EXTRAS(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;
// Zero memCount is not really an error, but the goto is necessary to
// keep some compilers from reordering stuff across the 'err' label.
if (memCount == 0) goto err;
__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
}
#ifdef TARGET_HAS_HARVARD_MEMORY
static void
__do_copy_from_progmem (unsigned char* src, unsigned char* dst)
{
unsigned long *long_dst;
unsigned long *long_src;
unsigned short *short_dst;
unsigned short *short_src;
// Zero memCount is not really an error, but the goto is necessary to
// keep some compilers from reordering stuff across the 'err' label.
if (memCount == 0) goto err;
__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++ = __read_prog_uint32(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++ = __read_prog_uint16(short_src++);
memCount -= sizeof(short);
dst = (unsigned char *)short_dst;
src = (unsigned char *)short_src;
} else {
*dst++ = __read_prog_uint8(src++);
memCount--;
}
}
__mem_fault = 0;
err:
__mem_fault_handler = (void *)0;
}
static void
__do_copy_to_progmem (unsigned char* src, unsigned char* dst)
{
unsigned long *long_dst;
unsigned long *long_src;
unsigned short *short_dst;
unsigned short *short_src;
// Zero memCount is not really an error, but the goto is necessary to
// keep some compilers from reordering stuff across the 'err' label.
if (memCount == 0) goto err;
__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;
__write_prog_uint32(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;
__write_prog_uint16(short_dst++, *short_src++);
memCount -= sizeof(short);
dst = (unsigned char *)short_dst;
src = (unsigned char *)short_src;
} else {
__write_prog_uint8(dst++, *src++);
memCount--;
}
}
__mem_fault = 0;
err:
__mem_fault_handler = (void *)0;
}
/*
* __read_progmem_safe:
* Get contents of target memory, abort on error.
*/
int
__read_progmem_safe (void *dst, void *src, int count)
{
memCount = count;
__do_copy_from_progmem((unsigned char*) src, (unsigned char*) dst);
return count - memCount; // return number of bytes successfully read
}
/*
* __write_progmem_safe:
* Set contents of target memory, abort on error.
*/
int
__write_progmem_safe (void *src, void *dst, int count)
{
memCount = count;
__do_copy_to_progmem((unsigned char*) src, (unsigned char*) dst);
return count - memCount; // return number of bytes successfully written
}
#endif
//-----------------------------------------------------------------------------
// 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 + -