diff --git a/components/gdb/SConscript b/components/gdb/SConscript deleted file mode 100644 index 8893d238bcc1e945e062a5259d28060297b6e796..0000000000000000000000000000000000000000 --- a/components/gdb/SConscript +++ /dev/null @@ -1,23 +0,0 @@ -Import('rtconfig') -from building import * - -src = Glob('*.c') -comm = 'libcpu/' + rtconfig.ARCH -if (rtconfig.CPU == 'cortex-m4') or (rtconfig.CPU == 'cortex-m3'): - comm = 'libcpu/cortexm' - -cwd = GetCurrentDir() -if rtconfig.PLATFORM == 'armcc': - src = src + Glob(comm + '/*.c') + Glob(comm + '/*_rvds.S') - -if rtconfig.PLATFORM == 'gcc': - src = src + Glob(comm + '/*.c') + Glob(comm + '/*_gcc.S') - -if rtconfig.PLATFORM == 'iar': - src = src + Glob(comm + '/*.c') + Glob(comm + '/*_iar.S') - -CPPPATH = [cwd, cwd + '/' + comm] - -group = DefineGroup('gdb', src, depend = ['RT_USING_GDB'], CPPPATH = CPPPATH) - -Return('group') diff --git a/components/gdb/gdb_stub.c b/components/gdb/gdb_stub.c deleted file mode 100644 index a07c165cbbeccef85a825fba35f81babd0c5b8e7..0000000000000000000000000000000000000000 --- a/components/gdb/gdb_stub.c +++ /dev/null @@ -1,1005 +0,0 @@ -/* - * GDB stub. - * - * Migarte form linux to rt-thread by Wzyy2 - * Original edition : KGDB stub - * - * File : gdb_stub.c - * This file is part of RT-Thread RTOS - * COPYRIGHT (C) 2006, RT-Thread Develop Team - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rt-thread.org/license/LICENSE - * - * Change Logs: - * Date Author Notes - * 2014-07-04 Wzyy2 first version - * - * This file incorporates work covered by the following copyright and - * permission notice: - * - * KGDB stub. - * - * Maintainer: Jason Wessel - * - * Copyright (C) 2000-2001 VERITAS Software Corporation. - * Copyright (C) 2002-2004 Timesys Corporation - * Copyright (C) 2003-2004 Amit S. Kale - * Copyright (C) 2004 Pavel Machek - * Copyright (C) 2004-2006 Tom Rini - * Copyright (C) 2004-2006 LinSysSoft Technologies Pvt. Ltd. - * Copyright (C) 2005-2008 Wind River Systems, Inc. - * Copyright (C) 2007 MontaVista Software, Inc. - * Copyright (C) 2008 Red Hat, Inc., Ingo Molnar - * - * Contributors at various stages not listed above: - * Jason Wessel ( jason.wessel@windriver.com ) - * George Anzinger - * Anurekh Saxena (anurekh.saxena@timesys.com) - * Lake Stevens Instrument Division (Glenn Engel) - * Jim Kingdon, Cygnus Support. - * - * Original KGDB stub: David Grothe , - * Tigran Aivazian - * - * This file is licensed under the terms of the GNU General Public License - * version 2. This program is licensed "as is" without any warranty of any - * kind, whether express or implied. - */ -#include -#include -#include -#include "gdb_stub.h" - - -struct gdb_state { - int signo; - int pass_exception; -}gs; - -/** - * gdb_connected - Is a host GDB connected to us? - */ -int gdb_connected; - - - -/* - * Holds information about breakpoints in a kernel. These breakpoints are - * added and removed by gdb. - */ -#if RT_GDB_HAVE_SWBP -static struct gdb_bkpt gdb_break[GDB_MAX_BREAKPOINTS] = { - [0 ... GDB_MAX_BREAKPOINTS-1] = { .state = BP_UNDEFINED } -}; -#endif - - -/* Storage for the registers, in GDB format. */ -static unsigned long gdb_regs[(NUMREGBYTES + - sizeof(unsigned long) - 1) / -sizeof(unsigned long)]; - -char remcom_in_buffer[BUFMAX]; -char remcom_out_buffer[BUFMAX]; - - -static const char hexchars[] = "0123456789abcdef"; - - -//to call that there has been an error -void* volatile gdb_mem_fault_handler = (void *)0; -static long probe_kernel_write(void *dst, void *src, size_t size) -{ - int i = 0; - char *dst_ptr = (char *)dst; - char *src_ptr = (char *)src; - - gdb_mem_fault_handler = &&err; - - for (i = 0; i= 'a') && (ch <= 'f')) - return ch - 'a' + 10; - if ((ch >= '0') && (ch <= '9')) - return ch - '0'; - if ((ch >= 'A') && (ch <= 'F')) - return ch - 'A' + 10; - return -1; -} - -static char tohex(char c) -{ - return hexchars[c & 15]; -} - -/* - * Copy the binary array pointed to by buf into mem. Fix $, #, and - * 0x7d escaped with 0x7d. Return a pointer to the character after - * the last byte written. - */ -int gdb_ebin2mem(char *buf, char *mem, int count) -{ - int err = 0; - char c; - - while (count-- > 0) { - c = *buf++; - if (c == 0x7d) - c = *buf++ ^ 0x20; - - err = probe_kernel_write(mem, &c, 1); - if (err) - break; - - mem++; - } - - return err; -} - -/* - * Convert the hex array pointed to by buf into binary to be placed in mem. - * Return a pointer to the character AFTER the last byte written. - * May return an error. - */ -int gdb_hex2mem(char *buf, char *mem, int count) -{ - char *tmp_raw; - char *tmp_hex; - - tmp_raw = buf + count * 2; - - tmp_hex = tmp_raw - 1; - while (tmp_hex >= buf) { - tmp_raw--; - *tmp_raw = hex(*tmp_hex--); - *tmp_raw |= hex(*tmp_hex--) << 4; - } - - return probe_kernel_write(mem, tmp_raw, count); -} -/* - * Convert the memory pointed to by mem into hex, placing result in buf. - * Return a pointer to the last char put in buf (null). May return an error. - */ -int gdb_mem2hex(char *mem, char *buf, int count) -{ - char *tmp = mem; - char ch; - - gdb_mem_fault_handler = &&err; - - while (count > 0) { - ch = *(tmp++); - *(buf++) = tohex((ch >> 4) & 0xf); - *(buf++) = tohex(ch & 0xf); - - count--; - } - *buf = 0; - - gdb_mem_fault_handler = (void *)0; - return 0; -err: - gdb_mem_fault_handler = (void *)0; - return -1; -} - -/* - * While we find nice hex chars, build a long_val. - * Return number of chars processed. - */ -int gdb_hex2long(char **ptr, unsigned long *long_val) -{ - int hex_val; - int num = 0; - int negate = 0; - - *long_val = 0; - - if (**ptr == '-') { - negate = 1; - (*ptr)++; - } - while (**ptr) { - hex_val = hex(**ptr); - if (hex_val < 0) - break; - - *long_val = (*long_val << 4) | hex_val; - num++; - (*ptr)++; - } - - if (negate) - *long_val = -*long_val; - - return num; -} - -/* Write memory due to an 'M' or 'X' packet. */ -static int write_mem_msg(int binary) -{ - char *ptr = &remcom_in_buffer[1]; - unsigned long addr; - unsigned long length; - int err; - - if (gdb_hex2long(&ptr, &addr) > 0 && *(ptr++) == ',' && - gdb_hex2long(&ptr, &length) > 0 && *(ptr++) == ':') { -#ifdef GDB_DATA_ACCESS - //accesses to areas not backed can cause error - if (gdb_permit_data_access(addr, length)) - return -1; -#endif - if (binary) - err = gdb_ebin2mem(ptr, (char *)addr, length); - else - err = gdb_hex2mem(ptr, (char *)addr, length); - if (err) - return err; -#ifdef RT_GDB_ICACHE - if (CACHE_FLUSH_IS_SAFE) - gdb_flush_icache_range(addr, addr + length); -#endif - return 0; - } - - return -1; -} - -/* - * Send the packet in buffer. - * Check for gdb connection if asked for. - */ -static void put_packet(char *buffer) -{ - unsigned char checksum; - int count; - char ch; - - /* - * $#. - */ - while (1) { - gdb_io_ops.write_char('$'); - checksum = 0; - count = 0; - - while ((ch = buffer[count])) { - gdb_io_ops.write_char(ch); - checksum += ch; - count++; - } - - gdb_io_ops.write_char('#'); - gdb_io_ops.write_char(tohex((checksum >> 4) & 0xf)); - gdb_io_ops.write_char(tohex(checksum & 0xf)); - - - /* Now see what we get in reply. */ - ch = gdb_io_ops.read_char(); - - /* If we get an ACK, we are done. */ - if (ch == '+') - return; - - /* - * If we get the start of another packet, this means - * that GDB is attempting to reconnect. We will NAK - * the packet being sent, and stop trying to send this - * packet. - */ - if (ch == '$') { - gdb_io_ops.write_char('-'); - if (gdb_io_ops.flush) - gdb_io_ops.flush(); - return; - } - } -} - -/* scan for the sequence $# */ -static void get_packet(char *buffer) -{ - unsigned char checksum; - unsigned char xmitcsum; - int count; - char ch; - - do { - /* - * Spin and wait around for the start character, ignore all - * other characters: - */ - while ((ch = (gdb_io_ops.read_char())) != '$') - /* nothing */; - gdb_connected = 1; - checksum = 0; - xmitcsum = -1; - - count = 0; - - /* - * now, read until a # or end of buffer is found: - */ - while (count < (BUFMAX - 1)) { - ch = gdb_io_ops.read_char(); - if (ch == '#') - break; - checksum = checksum + ch; - buffer[count] = ch; - count = count + 1; - } - buffer[count] = 0; - - if (ch == '#') { - xmitcsum = hex(gdb_io_ops.read_char()) << 4; - xmitcsum += hex(gdb_io_ops.read_char()); - - if (checksum != xmitcsum) - /* failed checksum */ - gdb_io_ops.write_char('-'); - else - /* successful transfer */ - gdb_io_ops.write_char('+'); - if (gdb_io_ops.flush) - gdb_io_ops.flush(); - } - } while (checksum != xmitcsum); -} - -static void error_packet(char *pkt, int error) -{ - error = -error; - pkt[0] = 'E'; - pkt[1] = tohex((error / 10)); - pkt[2] = tohex((error % 10)); - pkt[3] = '\0'; -} - -#if RT_GDB_HAVE_SWBP -static int gdb_arch_set_breakpoint(unsigned long addr, char *saved_instr) -{ - int err; - - err = probe_kernel_write((void *)saved_instr, (void *)addr, BREAK_INSTR_SIZE); - if (err) - return err; - - return probe_kernel_write((void *)addr, (void *)arch_gdb_ops.gdb_bpt_instr, - BREAK_INSTR_SIZE); -} - -static int gdb_arch_remove_breakpoint(unsigned long addr, char *bundle) -{ - return probe_kernel_write((void *)addr, - (void *)bundle, BREAK_INSTR_SIZE); -} -static int gdb_validate_break_address(unsigned long addr) -{ - char tmp_variable[BREAK_INSTR_SIZE]; - int err; - /* Validate setting the breakpoint and then removing it. In the - * remove fails, the kernel needs to emit a bad message because we - * are deep trouble not being able to put things back the way we - * found them. - */ - err = gdb_arch_set_breakpoint(addr, tmp_variable); - if (err) - return err; - err = gdb_arch_remove_breakpoint(addr, tmp_variable); - if (err) - rt_kprintf("GDB: Critical breakpoint error,memory destroyed at: %08x \n", addr); - return err; -} - -/* - * Some architectures need cache flushes when we set/clear a - * breakpoint: - */ -static void gdb_flush_swbreak_addr(unsigned long addr) -{ - if (!CACHE_FLUSH_IS_SAFE) - return; - - /* Force flush instruction cache if it was outside the mm */ - gdb_flush_icache_range(addr, addr + BREAK_INSTR_SIZE); -} - -/* - * SW breakpoint management: - */ -static int gdb_activate_sw_breakpoints(void) -{ - unsigned long addr; - int error = 0; - int i; - - for (i = 0; i < GDB_MAX_BREAKPOINTS; i++) { - if (gdb_break[i].state != BP_SET) - continue; - - addr = gdb_break[i].bpt_addr; - error = gdb_arch_set_breakpoint(addr, - (char *)(gdb_break[i].saved_instr)); - if (error) - return error; - - gdb_flush_swbreak_addr(addr); - gdb_break[i].state = BP_ACTIVE; - } - return 0; -} - -int gdb_set_sw_break(unsigned long addr) -{ - int err = gdb_validate_break_address(addr); - int breakno = -1; - int i; - - if (err) - return err; - - for (i = 0; i < GDB_MAX_BREAKPOINTS; i++) { - if ((gdb_break[i].state == BP_SET) && - (gdb_break[i].bpt_addr == addr)) - return -1; - } - for (i = 0; i < GDB_MAX_BREAKPOINTS; i++) { - if (gdb_break[i].state == BP_REMOVED) { - breakno = i; - break; - } - } - - if (breakno == -1) { - for (i = 0; i < GDB_MAX_BREAKPOINTS; i++) { - if (gdb_break[i].state == BP_UNDEFINED) { - breakno = i; - break; - } - } - } - - if (breakno == -1) - return -1; - - gdb_break[breakno].state = BP_SET; - gdb_break[breakno].type = BP_BREAKPOINT; - gdb_break[breakno].bpt_addr = addr; - - return 0; -} - -static int gdb_deactivate_sw_breakpoints(void) -{ - unsigned long addr; - int error = 0; - int i; - - for (i = 0; i < GDB_MAX_BREAKPOINTS; i++) { - if (gdb_break[i].state != BP_ACTIVE) - continue; - addr = gdb_break[i].bpt_addr; - error = gdb_arch_remove_breakpoint(addr, - (char *)(gdb_break[i].saved_instr)); - if (error) - return error; - - gdb_flush_swbreak_addr(addr); - gdb_break[i].state = BP_SET; - } - return 0; -} - -int gdb_remove_sw_break(unsigned long addr) -{ - int i; - - for (i = 0; i < GDB_MAX_BREAKPOINTS; i++) { - if ((gdb_break[i].state == BP_SET) && - (gdb_break[i].bpt_addr == addr)) { - gdb_break[i].state = BP_REMOVED; - return 0; - } - } - return -1; -} - -int gdb_isremovedbreak(unsigned long addr) -{ - int i; - - for (i = 0; i < GDB_MAX_BREAKPOINTS; i++) { - if ((gdb_break[i].state == BP_REMOVED) && - (gdb_break[i].bpt_addr == addr)) - return 1; - } - return 0; -} -#endif - -static int remove_all_break() -{ -#if RT_GDB_HAVE_SWBP - unsigned long addr; - int error=0; - int i; - - /* Clear memory breakpoints. */ - for (i = 0; i < GDB_MAX_BREAKPOINTS; i++) { - if (gdb_break[i].state != BP_ACTIVE) - goto setundefined; - addr = gdb_break[i].bpt_addr; - error = gdb_arch_remove_breakpoint(addr, - (char *)gdb_break[i].saved_instr); - if (error) - rt_kprintf("GDB: breakpoint remove failed: %lx\n", - addr); -setundefined: - gdb_break[i].state = BP_UNDEFINED; - } -#endif - -#if RT_GDB_HAVE_HWBP - /* Clear hardware breakpoints. */ - arch_gdb_ops.remove_all_hw_break(); -#endif - - return 0; -} - - -static char gdbmsgbuf[BUFMAX + 1]; -static void gdb_msg_write(const char *s, int len) -{ - char *bufptr; - int wcount; - int i; - - /* 'O'utput */ - gdbmsgbuf[0] = 'O'; - - /* Fill and send buffers... */ - while (len > 0) { - bufptr = gdbmsgbuf + 1; - - /* Calculate how many this time */ - if ((len << 1) > (BUFMAX - 2)) - wcount = (BUFMAX - 2) >> 1; - else - wcount = len; - - /* Pack in hex chars */ - for (i = 0; i < wcount; i++) { - *(bufptr++) = tohex((s[i] >> 4) & 0xf); - *(bufptr++) = tohex(s[i] & 0xf); - } - *bufptr = '\0'; - - /* Move up */ - s += wcount; - len -= wcount; - - /* Write packet */ - put_packet(gdbmsgbuf); - } -} - -/* - * Return true if there is a valid gdb I/O module. Also if no - * debugger is attached a message can be printed to the console about - * waiting for the debugger to attach. - * - * The print_wait argument is only to be true when called from inside - * the core gdb_handle_exception, because it will wait for the - * debugger to attach. - */ -static int gdb_io_ready(int print_wait) -{ - if (!gdb_dev) - return 0; - if (gdb_connected) - return 1; - if (print_wait) - rt_kprintf("GDB: Waiting for remote debugger\n"); - return 1; -} - -/* Handle the '?' status packets */ -static void gdb_cmd_status(struct gdb_state *gs) -{ - /* - * We know that this packet is only sent - * during initial connect. So to be safe, - * we clear out our breakpoints now in case - * GDB is reconnecting. - */ - remove_all_break(); - - remcom_out_buffer[0] = 'S'; - remcom_out_buffer[1] = tohex((gs->signo >> 4) &0xf); - remcom_out_buffer[2] = tohex(gs->signo & 0xf); - remcom_out_buffer[3] = 0; -} - -/* Handle the 'm' memory read bytes */ -static void gdb_cmd_memread(struct gdb_state *gs) -{ - char *ptr = &remcom_in_buffer[1]; - unsigned long length; - unsigned long addr; - int err; - - if (gdb_hex2long(&ptr, &addr) > 0 && *ptr++ == ',' && - gdb_hex2long(&ptr, &length) > 0) { -#ifdef GDB_DATA_ACCESS - //accesses to areas not backed can cause error - if (gdb_permit_data_access(addr, length)) - return ; -#endif - err = gdb_mem2hex((char *)addr, remcom_out_buffer, length); - if (err) - error_packet(remcom_out_buffer, err); - } else { - error_packet(remcom_out_buffer, -1); - } -} - -/* Handle the 'M' memory write bytes */ -static void gdb_cmd_memwrite(struct gdb_state *gs) -{ - int err = write_mem_msg(0); - - if (err) - error_packet(remcom_out_buffer, err); - else - strcpy(remcom_out_buffer, "OK"); -} - -/* Handle the 'X' memory binary write bytes */ -static void gdb_cmd_binwrite(struct gdb_state *gs) -{ - int err = write_mem_msg(1); - - if (err) - error_packet(remcom_out_buffer, err); - else - strcpy(remcom_out_buffer, "OK"); -} - -/* Handle the 'q' query packets */ -static void gdb_cmd_query(struct gdb_state *gs) -{ - /* nothing,because we have no thread support */ -} - - -/* Handle the 'g' or 'p' get registers request */ -static void gdb_cmd_getregs(struct gdb_state *gs) -{ - char len = sizeof(long); - - gdb_get_register((unsigned long *)gdb_regs); - - /*get one registers*/ - if (remcom_in_buffer[0] == 'p'){ - char *p = &remcom_in_buffer[1]; - unsigned long regno = 0; - - if (gdb_hex2long(&p, ®no)){ - gdb_mem2hex(((char *)gdb_regs) + regno * len, remcom_out_buffer, len); - return; - } else { - strcpy(remcom_out_buffer, "INVALID"); - return; - } - } - - gdb_mem2hex((char *)gdb_regs, remcom_out_buffer, NUMREGBYTES); -} - -/* Handle the 'G' or 'P' set registers request */ -static void gdb_cmd_setregs(struct gdb_state *gs) -{ - char len = sizeof(long); - - /*set one registers*/ - if (remcom_in_buffer[0] == 'P'){ - char *p = &remcom_in_buffer[1]; - unsigned long regno = 0; - - if (gdb_hex2long(&p, ®no) && *p++ == '='){ - gdb_get_register((unsigned long *)gdb_regs); - gdb_hex2mem(p, ((char *)gdb_regs) + regno * len, len); - gdb_put_register(gdb_regs); - strcpy(remcom_out_buffer, "OK"); - } - - return; - } - - gdb_hex2mem(&remcom_in_buffer[1], (char *)gdb_regs, NUMREGBYTES); - - gdb_put_register(gdb_regs); - strcpy(remcom_out_buffer, "OK"); -} - -/* Handle the 'D' or 'k', detach or kill packets */ -static void gdb_cmd_detachkill(struct gdb_state *gs) -{ - int error; - - /* The detach case */ - if (remcom_in_buffer[0] == 'D') { - error = remove_all_break(); - if (error < 0) { - error_packet(remcom_out_buffer, error); - } else { - strcpy(remcom_out_buffer, "OK"); - gdb_connected = 0; - } - put_packet(remcom_out_buffer); - } else { - /* - * Assume the kill case, with no exit code checking, - * trying to force detach the debugger: - */ - remove_all_break(); - gdb_connected = 0; - } -} - -/* Handle the 'z' or 'Z' breakpoint remove or set packets */ -static void gdb_cmd_break(struct gdb_state *gs) -{ - /* - * Since GDB-5.3, it's been drafted that '0' is a software - * breakpoint, '1' is a hardware breakpoint, so let's do that. - */ - char *bpt_type = &remcom_in_buffer[1]; - char *ptr = &remcom_in_buffer[2]; - unsigned long addr; - unsigned long length; - int error = 0; - - if (arch_gdb_ops.set_hw_breakpoint && *bpt_type >= '1') { - /* Unsupported */ - if (*bpt_type > '4') - return; - } - /* - * Test if this is a hardware breakpoint, and - * if we support it: - */ - if (*bpt_type == '1' && !(arch_gdb_ops.flags)) { - /* Unsupported. */ - return; - } - if (*(ptr++) != ',') { - error_packet(remcom_out_buffer, -1); - return; - } - if (!gdb_hex2long(&ptr, &addr)) { - error_packet(remcom_out_buffer, -1); - return; - } - if (*(ptr++) != ',' || - !gdb_hex2long(&ptr, &length)) { - error_packet(remcom_out_buffer, -1); - return; - } -#if RT_GDB_HAVE_SWBP - if (remcom_in_buffer[0] == 'Z' && *bpt_type == '0') - error = gdb_set_sw_break(addr); - else if (remcom_in_buffer[0] == 'z' && *bpt_type == '0') - error = gdb_remove_sw_break(addr); -#else - if (remcom_in_buffer[0] == 'Z' && *bpt_type == '0') - error = arch_gdb_ops.set_hw_breakpoint(addr, - (int)length, BP_HARDWARE_BREAKPOINT); - else if (remcom_in_buffer[0] == 'z' && *bpt_type == '0') - error = arch_gdb_ops.remove_hw_breakpoint(addr, - (int) length, BP_HARDWARE_BREAKPOINT); -#endif - else if (remcom_in_buffer[0] == 'Z') - error = arch_gdb_ops.set_hw_breakpoint(addr, - (int)length, *bpt_type - '0'); - else if (remcom_in_buffer[0] == 'z') - error = arch_gdb_ops.remove_hw_breakpoint(addr, - (int) length, *bpt_type - '0'); - - if (error == 0) - strcpy(remcom_out_buffer, "OK"); - else - error_packet(remcom_out_buffer, error); -} - -/* Handle the 'C' signal / exception passing packets */ -static int gdb_cmd_exception_pass(struct gdb_state *gs) -{ - /* C09 == pass exception - * C15 == detach gdb, pass exception - */ - if (remcom_in_buffer[1] == '0' && remcom_in_buffer[2] == '9') { - - gs->pass_exception = 1; - remcom_in_buffer[0] = 'c'; - - } else if (remcom_in_buffer[1] == '1' && remcom_in_buffer[2] == '5') { - - gs->pass_exception = 1; - remcom_in_buffer[0] = 'D'; - remove_all_break(); - gdb_connected = 0; - return 1; - - } else { - error_packet(remcom_out_buffer, -1); - return 0; - } - - /* Indicate fall through */ - return -1; -} - - -/*more about packet in https://www.sourceware.org/gdb/current/onlinedocs/gdb/Packets.html#Packets*/ -static int process_packet(char *pkt) -{ - int status = 0; - int tmp; - - status = gdb_arch_handle_exception(remcom_in_buffer, - remcom_out_buffer); - - remcom_out_buffer[0] = 0; - switch (pkt[0]) { - case '?':/* gdbserial status */ - gdb_cmd_status(&gs); - break; - case 'q':/* query command */ - gdb_cmd_query(&gs); - break; - case 'p': /* return the value of a single CPU register */ - case 'g': /* return the value of the CPU registers */ - gdb_cmd_getregs(&gs); - break; - case 'P': /* set the value of a single CPU registers - return OK */ - case 'G': /* set the value of the CPU registers - return OK */ - gdb_cmd_setregs(&gs); - break; - case 'm': /* mAA..AA,LLLL Read LLLL bytes at address AA..AA */ - gdb_cmd_memread(&gs); - break; - case 'X':/* XAA..AA,LLLL: Write LLLL escaped binary bytes at address AA.AA*/ - gdb_cmd_binwrite(&gs); - break; - case 'M':/* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */ - gdb_cmd_memwrite(&gs); - break; - case 'D': /* Debugger detach */ - case 'k': /* Debugger detach via kill */ - gdb_cmd_detachkill(&gs); - break; - case 'C':/* Exception passing */ - tmp = gdb_cmd_exception_pass(&gs); - if (tmp > 0) - process_packet(remcom_in_buffer); - if (tmp == 0) - break; - case 'z':/* Break point remove */ - case 'Z':/* Break point set */ - gdb_cmd_break(&gs); - break; - case 'H':/* task related */ - break; - case 'T':/* Query thread status */ - break; - case 'b': /* bBB... Set baud rate to BB... */ - break; - case 's': /* sAA..AA step form address AA..AA (optional) */ - case 'c': /* cAA..AA Continue at address AA..AA (optional) */ -#if RT_GDB_HAVE_SWBP - gdb_activate_sw_breakpoints(); -#endif - break; - } - - if (!status) - return -1; - -exit: - put_packet(remcom_out_buffer); - return 0; -} - - -/* - * This function does all command procesing for interfacing to gdb. - */ -int gdb_process_exception() -{ - int status; - - do { - get_packet(remcom_in_buffer); - status = process_packet(remcom_in_buffer); - } while (status == 0); - - if (status < 0) - return 0; - else - return 1; -} - - -int gdb_handle_exception(int signo, void *regs) -{ - int error; - - gs.signo = signo; - - if (!gdb_io_ready(1)) { - error = 1; - return error; /* No I/O connection, so resume the system */ - } - -#if RT_GDB_HAVE_SWBP - gdb_deactivate_sw_breakpoints(); -#endif - gdb_set_register(regs); - - /* Clear the out buffer. */ - memset(remcom_out_buffer, 0, sizeof(remcom_out_buffer)); - - if (gdb_connected) { - char *ptr; - - gdb_io_ops.write_char('\n'); - /* Reply to host that an exception has occurred */ - ptr = remcom_out_buffer; - *ptr++ = 'T'; - *ptr++ = tohex((gs.signo >> 4) &0xf); - *ptr++ = tohex(gs.signo & 0xf); - /*ptr += strlen(strcpy(ptr, "thread:"));*/ - /**ptr++ = ';';*/ - put_packet(remcom_out_buffer); - } - gs.pass_exception = 0; - - - while (gdb_process_exception()); - - error = gs.pass_exception; - - return error; -} - -void gdb_console_write(const char *s, unsigned count) -{ - /* If we're debugging, or GDB has not connected, don't try - * and print. */ - if (!gdb_connected) - return; - - gdb_msg_write(s, count); -} - diff --git a/components/gdb/gdb_stub.h b/components/gdb/gdb_stub.h deleted file mode 100644 index cb9688ee3a7e6dcc46b4cee5251da815d5dab29e..0000000000000000000000000000000000000000 --- a/components/gdb/gdb_stub.h +++ /dev/null @@ -1,131 +0,0 @@ -/* - * This provides the functions that GDB needs to share between - * different portions. - * - * GDB stub. - * - * Migarte form linux to rt-thread by Wzyy2 - * Original edition : KGDB stub - * - * File : gdb_stub.h - * This file is part of RT-Thread RTOS - * COPYRIGHT (C) 2006, RT-Thread Develop Team - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rt-thread.org/license/LICENSE - * - * Change Logs: - * Date Author Notes - * 2014-07-04 Wzyy2 first version - */ -#ifndef __GDB_STUB_H__ -#define __GDB_STUB_H__ - -#include -#include - - -#ifndef RT_GDB_MAX_BREAKPOINTS - #define GDB_MAX_BREAKPOINTS 20 -#else - #define GDB_MAX_BREAKPOINTS RT_GDB_MAX_BREAKPOINTS -#endif - - -// Signal definitions -#define SIGHUP 1 /* hangup */ -#define SIGINT 2 /* interrupt */ //irq or fiq -#define SIGQUIT 3 /* quit */ -#define SIGILL 4 /* illegal instruction (not reset when caught) */ -#define SIGTRAP 5 /* trace trap (not reset when caught) */ -#define SIGIOT 6 /* IOT instruction */ -#define SIGABRT 6 /* used by abort, replace SIGIOT in the future */ -#define SIGEMT 7 /* EMT instruction */ -#define SIGFPE 8 /* floating point exception */ -#define SIGKILL 9 /* kill (cannot be caught or ignored) */ -#define SIGBUS 10 /* bus error */ //abort or reserved -#define SIGSEGV 11 /* segmentation violation */ -#define SIGSYS 12 /* bad argument to system call */ -#define SIGPIPE 13 /* write on a pipe with no one to read it */ -#define SIGALRM 14 /* alarm clock */ -#define SIGTERM 15 /* software termination signal from kill */ - -enum gdb_bptype { - BP_BREAKPOINT = 0, - BP_HARDWARE_BREAKPOINT, - BP_WRITE_WATCHPOINT, - BP_READ_WATCHPOINT, - BP_ACCESS_WATCHPOINT, - BP_POKE_BREAKPOINT, -}; - -enum gdb_bpstate { - BP_UNDEFINED = 0, - BP_REMOVED, - BP_SET, - BP_ACTIVE -}; - -struct gdb_bkpt { - unsigned long bpt_addr; - unsigned char saved_instr[BREAK_INSTR_SIZE]; - enum gdb_bptype type; - enum gdb_bpstate state; -}; - -/** - * struct gdb_arch - Describe architecture specific values. - * @gdb_bpt_instr: The instruction to trigger a breakpoint. - * @flags: Flags for the breakpoint, currently just %GDB_HW_BREAKPOINT. - * @set_hw_breakpoint: Allow an architecture to specify how to set a hardware - * breakpoint. - * @remove_hw_breakpoint: Allow an architecture to specify how to remove a - * hardware breakpoint. - * @remove_all_hw_break: Allow an architecture to specify how to remove all - * hardware breakpoints. - */ -struct gdb_arch { - unsigned char gdb_bpt_instr[BREAK_INSTR_SIZE]; - unsigned long flags; - - int (*set_hw_breakpoint)(unsigned long, int, enum gdb_bptype); - int (*remove_hw_breakpoint)(unsigned long, int, enum gdb_bptype); - void (*remove_all_hw_break)(void); -}; -/** - * struct gdb_io - Describe the interface for an I/O driver to talk with KGDB. - * @read_char: Pointer to a function that will return one char. - * @write_char: Pointer to a function that will write one char. - * @flush: Pointer to a function that will flush any pending writes. - * @init: Pointer to a function that will initialize the device. - */ -struct gdb_io { - int (*read_char) (void); - void (*write_char) (char); - void (*flush) (void); - int (*init) (void); -}; - -extern int gdb_connected; -extern void* volatile gdb_mem_fault_handler; - -int gdb_hex2long(char **ptr, unsigned long *long_val); -int gdb_mem2hex(char *mem, char *buf, int count); -int gdb_hex2mem(char *buf, char *mem, int count); -int gdb_ebin2mem(char *buf, char *mem, int count); -int gdb_set_sw_break(unsigned long addr); -int gdb_remove_sw_break(unsigned long addr); -int gdb_isremovedbreak(unsigned long addr); -void gdb_console_write(const char *s, unsigned count); -int gdb_handle_exception(int signo, void *regs); - -/* hal */ -extern struct gdb_io gdb_io_ops; -extern rt_device_t gdb_dev; -void gdb_start(); -void gdb_set_device(const char* device_name); - - - -#endif /* __GDB_STUB_H__ */ diff --git a/components/gdb/hal_stub.c b/components/gdb/hal_stub.c deleted file mode 100644 index 8cf4a31a51c57e88fd243af2f6393f049b48adfe..0000000000000000000000000000000000000000 --- a/components/gdb/hal_stub.c +++ /dev/null @@ -1,105 +0,0 @@ -/* - * I/O and interface portion of GDB stub - * - * File : hal_stub.c - * This file is part of RT-Thread RTOS - * COPYRIGHT (C) 2006, RT-Thread Develop Team - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rt-thread.org/license/LICENSE - * - * Change Logs: - * Date Author Notes - * 2014-07-04 Wzyy2 first version - */ -#include -#include -#include "gdb_stub.h" - -#ifdef RT_USING_SERIAL -#include -#endif - -rt_device_t gdb_dev = RT_NULL; -static struct rt_serial_device *gdb_serial; -char gdb_io_set; - -void gdb_uart_putc(char c); -int gdb_uart_getc(); - - -/*if you want to use something instead of the serial,change it */ -struct gdb_io gdb_io_ops = { - gdb_uart_getc, - gdb_uart_putc -}; - - -/** - * @ingroup gdb_stub - * - * This function will get GDB stubs started, with a proper environment - */ -void gdb_start() -{ - if (gdb_dev == RT_NULL) - rt_kprintf("GDB: no gdb_dev found,please set it first\n"); - else - gdb_breakpoint(); -} - - -/** - * @ingroup gdb_stub - * - * This function sets the input device of gdb_stub. - * - * @param device_name the name of new input device. - */ -void gdb_set_device(const char* device_name) -{ - rt_device_t dev = RT_NULL; - dev = rt_device_find(device_name); - if(dev == RT_NULL){ - rt_kprintf("GDB: can not find device: %s\n", device_name); - return; - } - - /* open this device and set the new device */ - if (rt_device_open(dev, RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_STREAM) == RT_EOK) - { - gdb_dev = dev; - gdb_serial = (struct rt_serial_device *)gdb_dev; - } -} - -void gdb_uart_putc(char c) -{ -#ifdef RT_GDB_DEBUG - rt_kprintf("%c",c); -#endif - rt_device_write(gdb_dev, 0, &c, 1); -} - -/* polling */ -int gdb_uart_getc() -{ - int ch; - -#ifdef RT_USING_SERIAL - ch = -1; - do { - ch = gdb_serial->ops->getc(gdb_serial); - } while (ch == -1); -#else - rt_device_read(gdb_dev, 0, &ch, 1); -#endif - -#ifdef RT_GDB_DEBUG - rt_kprintf("%c",ch); -#endif - - return ch; -} - diff --git a/components/gdb/libcpu/arm/arch_gdb.h b/components/gdb/libcpu/arm/arch_gdb.h deleted file mode 100644 index b9462499f2f7d9417e1977e33a994eb890a6d213..0000000000000000000000000000000000000000 --- a/components/gdb/libcpu/arm/arch_gdb.h +++ /dev/null @@ -1,90 +0,0 @@ -/* - * ARM GDB support - * arch-specific portion of GDB stub - * - * File : arch_gdb.h(arm) - * This file is part of RT-Thread RTOS - * COPYRIGHT (C) 2006, RT-Thread Develop Team - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rt-thread.org/license/LICENSE - * - * Change Logs: - * Date Author Notes - * 2014-07-04 wzyy2 first version - */ -#ifndef __ARM_GDB_H__ -#define __ARM_GDB_H__ - -#include - - -#ifndef RT_GDB_HAVE_HWBP - #define RT_GDB_HAVE_HWBP 0 -#endif -#ifndef RT_GDB_HAVE_SWBP - #define RT_GDB_HAVE_SWBP 1 -#endif - - -#if RT_GDB_HAVE_HWBP - #error GDB:No hardware_breakpoint support -#endif - - -/* - * By doing this as an undefined instruction trap, we force a mode - * switch from SVC to UND mode, allowing us to save full kernel state. - * We also define a GDB_COMPILED_BREAK which can be used to compile - * in breakpoints. - */ -#define BREAK_INSTR_SIZE 4 -#define GDB_BREAKINST 0xe7ffdefe -#define GDB_COMPILED_BREAK 0xe7ffdeff -#define CACHE_FLUSH_IS_SAFE 1 - -#define ARM_GP_REGS 16 -#define ARM_FP_REGS 8 -#define ARM_EXTRA_REGS 2 -#define GDB_MAX_REGS (ARM_GP_REGS + (ARM_FP_REGS * 3) + ARM_EXTRA_REGS) -#define NUMREGBYTES (GDB_MAX_REGS << 2) - - -//#define BUFMAX ((NUMREGBYTES << 1) + 10) -#define BUFMAX 400 - -enum regnames { - GDB_R0, /*0*/ - GDB_R1, /*1*/ - GDB_R2, /*2*/ - GDB_R3, /*3*/ - GDB_R4, /*4*/ - GDB_R5, /*5*/ - GDB_R6, /*6*/ - GDB_R7, /*7*/ - GDB_R8, /*8*/ - GDB_R9, /*9*/ - GDB_R10, /*10*/ - GDB_FP, /*11*/ - GDB_IP, /*12*/ - GDB_SPT, /*13*/ - GDB_LR, /*14*/ - GDB_PC, /*15*/ - GDB_CPSR = GDB_MAX_REGS-1 -}; - -/* arch */ -extern struct gdb_arch arch_gdb_ops; -void gdb_breakpoint(); -void gdb_get_register(unsigned long *gdb_regs); -void gdb_put_register(unsigned long *gdb_regs); -void gdb_set_register(void *hw_regs); -int gdb_arch_handle_exception(char *remcom_in_buffer, - char *remcom_out_buffer); -void gdb_flush_icache_range(unsigned long start, unsigned long end); -int gdb_undef_hook(void *regs); - -int gdb_handle_exception(int signo, void *regs); - -#endif /* __ARM_GDB_H__ */ diff --git a/components/gdb/libcpu/arm/arm_stub.c b/components/gdb/libcpu/arm/arm_stub.c deleted file mode 100644 index a312d39f4a4e3185eafa1eb106045938eb04e487..0000000000000000000000000000000000000000 --- a/components/gdb/libcpu/arm/arm_stub.c +++ /dev/null @@ -1,499 +0,0 @@ -/* - * ARM GDB support - * arch-specific portion of GDB stub - * - * File : arm_stub.c - * This file is part of RT-Thread RTOS - * COPYRIGHT (C) 2006, RT-Thread Develop Team - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rt-thread.org/license/LICENSE - * - * Change Logs: - * Date Author Notes - * 2014-07-04 Wzyy2 first version - */ -#include -#include -#include -#include - -#define PS_N 0x80000000 -#define PS_Z 0x40000000 -#define PS_C 0x20000000 -#define PS_V 0x10000000 - -#define IS_THUMB_ADDR(addr) ((addr) & 1) -#define MAKE_THUMB_ADDR(addr) ((addr) | 1) -#define UNMAKE_THUMB_ADDR(addr) ((addr) & ~1) - -static int compiled_break = 0; -static unsigned long step_addr = 0; -static int ins_will_execute(unsigned long ins); -static unsigned long target_ins(unsigned long *pc, unsigned long ins); - - -/*struct gdb_arch - Describe architecture specific values.*/ -struct gdb_arch arch_gdb_ops = { - .gdb_bpt_instr = {0xfe, 0xde, 0xff, 0xe7} //Little-Endian -}; - -struct rt_gdb_register -{ - rt_uint32_t r0; - rt_uint32_t r1; - rt_uint32_t r2; - rt_uint32_t r3; - rt_uint32_t r4; - rt_uint32_t r5; - rt_uint32_t r6; - rt_uint32_t r7; - rt_uint32_t r8; - rt_uint32_t r9; - rt_uint32_t r10; - rt_uint32_t fp; - rt_uint32_t ip; - rt_uint32_t sp; - rt_uint32_t lr; - rt_uint32_t pc; - rt_uint32_t cpsr; - rt_uint32_t ORIG_r0; -}*regs; - -/** - * gdb_breakpoint - generate a compiled_breadk - * It is used to sync up with a debugger and stop progarm - */ -void gdb_breakpoint() -{ - asm(".word 0xe7ffdeff"); -} - -void gdb_set_register(void *hw_regs) -{ - regs = (struct rt_gdb_register *)hw_regs; -} -void gdb_get_register(unsigned long *gdb_regs) -{ - int regno; - /* Initialize all to zero. */ - for (regno = 0; regno < GDB_MAX_REGS; regno++) - gdb_regs[regno] = 0; - - gdb_regs[GDB_R0] = regs->r0; - gdb_regs[GDB_R1] = regs->r1; - gdb_regs[GDB_R2] = regs->r2; - gdb_regs[GDB_R3] = regs->r3; - gdb_regs[GDB_R4] = regs->r4; - gdb_regs[GDB_R5] = regs->r5; - gdb_regs[GDB_R6] = regs->r6; - gdb_regs[GDB_R7] = regs->r7; - gdb_regs[GDB_R8] = regs->r8; - gdb_regs[GDB_R9] = regs->r9; - gdb_regs[GDB_R10] = regs->r10; - gdb_regs[GDB_FP] = regs->fp; - gdb_regs[GDB_IP] = regs->ip; - gdb_regs[GDB_SPT] = regs->sp; - gdb_regs[GDB_LR] = regs->lr; - gdb_regs[GDB_PC] = regs->pc; - gdb_regs[GDB_CPSR] = regs->cpsr; - -}; - - -void gdb_put_register(unsigned long *gdb_regs) -{ - regs->r0 = gdb_regs[GDB_R0]; - regs->r1 = gdb_regs[GDB_R1]; - regs->r2 = gdb_regs[GDB_R2]; - regs->r3 = gdb_regs[GDB_R3]; - regs->r4 = gdb_regs[GDB_R4]; - regs->r5 = gdb_regs[GDB_R5]; - regs->r6 = gdb_regs[GDB_R6]; - regs->r7 = gdb_regs[GDB_R7]; - regs->r8 = gdb_regs[GDB_R8]; - regs->r9 = gdb_regs[GDB_R9]; - regs->r10 = gdb_regs[GDB_R10]; - regs->fp = gdb_regs[GDB_FP]; - regs->ip = gdb_regs[GDB_IP]; - regs->sp = gdb_regs[GDB_SPT]; - regs->lr = gdb_regs[GDB_LR]; - regs->pc = gdb_regs[GDB_PC]; - regs->cpsr = gdb_regs[GDB_CPSR]; -} - - -/* It will be called during process_packet */ -int gdb_arch_handle_exception(char *remcom_in_buffer, - char *remcom_out_buffer) -{ - unsigned long addr,curins; - char *ptr; - - /*clear single step*/ - if (step_addr) { - gdb_remove_sw_break(step_addr); - step_addr = 0; - } - - switch (remcom_in_buffer[0]) { - case 'D': - case 'k': - case 'c': - /* - * If this was a compiled breakpoint, we need to move - * to the next instruction or we will breakpoint - * over and over again - */ - ptr = &remcom_in_buffer[1]; - if (gdb_hex2long(&ptr, &addr)) - regs->pc = addr; - else if (compiled_break == 1) - regs->pc += 4; - compiled_break = 0; - return 0; - - case 's': - ptr = &remcom_in_buffer[1]; - if (gdb_hex2long(&ptr, &addr)) - regs->pc = addr; - - curins = *(unsigned long*)(regs->pc); - if (ins_will_execute(curins)) - //Decode instruction to decide what the next pc will be - step_addr = target_ins((unsigned long *)regs->pc, curins); - else - step_addr = regs->pc + 4; - -#ifdef RT_GDB_DEBUG - rt_kprintf("\n next will be %x \n",step_addr); -#endif - gdb_set_sw_break(step_addr); - - if (compiled_break == 1) - regs->pc += 4; - compiled_break = 0; - return 0; - } - - return -1; - -} - -/* flush icache to let the sw breakpoint working */ -void gdb_flush_icache_range(unsigned long start, unsigned long end) -{ -#ifdef RT_GDB_ICACHE - extern void mmu_invalidate_icache(); - mmu_invalidate_icache(); //for arm,wo can only invalidate it -#endif -} - -/* register a hook in undef*/ -int gdb_undef_hook(void *regs) -{ - struct rt_gdb_register *tmp_reg = (struct rt_gdb_register *)regs; - unsigned long *tmp_pc = (unsigned long *)tmp_reg->pc; - - /* it is a compiled break */ - if (*tmp_pc == GDB_COMPILED_BREAK) { - compiled_break = 1; - gdb_handle_exception(SIGTRAP, regs); - return 1; - - } - /* it is a sw break */ - else if (*tmp_pc == GDB_BREAKINST) { - gdb_handle_exception(SIGTRAP, regs); - return 1; - } - /*or we just go */ - return 0; - -} - -static unsigned long gdb_arch_regs[GDB_MAX_REGS]; -static int ins_will_execute(unsigned long ins) -{ - unsigned long psr = regs->cpsr; // condition codes - int res = 0; - switch ((ins & 0xF0000000) >> 28) { - case 0x0: // EQ - res = (psr & PS_Z) != 0; - break; - case 0x1: // NE - res = (psr & PS_Z) == 0; - break; - case 0x2: // CS - res = (psr & PS_C) != 0; - break; - case 0x3: // CC - res = (psr & PS_C) == 0; - break; - case 0x4: // MI - res = (psr & PS_N) != 0; - break; - case 0x5: // PL - res = (psr & PS_N) == 0; - break; - case 0x6: // VS - res = (psr & PS_V) != 0; - break; - case 0x7: // VC - res = (psr & PS_V) == 0; - break; - case 0x8: // HI - res = ((psr & PS_C) != 0) && ((psr & PS_Z) == 0); - break; - case 0x9: // LS - res = ((psr & PS_C) == 0) || ((psr & PS_Z) != 0); - break; - case 0xA: // GE - res = ((psr & (PS_N|PS_V)) == (PS_N|PS_V)) || - ((psr & (PS_N|PS_V)) == 0); - break; - case 0xB: // LT - res = ((psr & (PS_N|PS_V)) == PS_N) || - ((psr & (PS_N|PS_V)) == PS_V); - break; - case 0xC: // GT - res = ((psr & (PS_N|PS_V)) == (PS_N|PS_V)) || - ((psr & (PS_N|PS_V)) == 0); - res = ((psr & PS_Z) == 0) && res; - break; - case 0xD: // LE - res = ((psr & (PS_N|PS_V)) == PS_N) || - ((psr & (PS_N|PS_V)) == PS_V); - res = ((psr & PS_Z) == PS_Z) || res; - break; - case 0xE: // AL - res = 1; - break; - case 0xF: // NV - if (((ins & 0x0E000000) >> 24) == 0xA) - res = 1; - else - res = 0; - break; - } - return res; -} - -static unsigned long RmShifted(int shift) -{ - unsigned long Rm = gdb_arch_regs[shift & 0x00F]; - int shift_count; - if ((shift & 0x010) == 0) { - shift_count = (shift & 0xF80) >> 7; - } else { - shift_count = gdb_arch_regs[(shift & 0xF00) >> 8]; - } - switch ((shift & 0x060) >> 5) { - case 0x0: // Logical left - Rm <<= shift_count; - break; - case 0x1: // Logical right - Rm >>= shift_count; - break; - case 0x2: // Arithmetic right - Rm = (unsigned long)((long)Rm >> shift_count); - break; - case 0x3: // Rotate right - if (shift_count == 0) { - // Special case, RORx - Rm >>= 1; - if (gdb_arch_regs[GDB_CPSR] & PS_C) Rm |= 0x80000000; - } else { - Rm = (Rm >> shift_count) | (Rm << (32-shift_count)); - } - break; - } - return Rm; -} - -// Decide the next instruction to be executed for a given instruction -static unsigned long target_ins(unsigned long *pc, unsigned long ins) -{ - unsigned long new_pc, offset, op2; - unsigned long Rn; - int i, reg_count, c; - - gdb_get_register(gdb_arch_regs); - - switch ((ins & 0x0C000000) >> 26) { - case 0x0: - // BX or BLX - if ((ins & 0x0FFFFFD0) == 0x012FFF10) { - new_pc = (unsigned long)gdb_arch_regs[ins & 0x0000000F]; - return new_pc; - } - // Data processing - new_pc = (unsigned long)(pc+1); - if ((ins & 0x0000F000) == 0x0000F000) { - // Destination register is PC - if ((ins & 0x0FBF0000) != 0x010F0000) { - Rn = (unsigned long)gdb_arch_regs[(ins & 0x000F0000) >> 16]; - if ((ins & 0x000F0000) == 0x000F0000) Rn += 8; // PC prefetch! - if ((ins & 0x02000000) == 0) { - op2 = RmShifted(ins & 0x00000FFF); - } else { - op2 = ins & 0x000000FF; - i = (ins & 0x00000F00) >> 8; // Rotate count - op2 = (op2 >> (i*2)) | (op2 << (32-(i*2))); - } - switch ((ins & 0x01E00000) >> 21) { - case 0x0: // AND - new_pc = Rn & op2; - break; - case 0x1: // EOR - new_pc = Rn ^ op2; - break; - case 0x2: // SUB - new_pc = Rn - op2; - break; - case 0x3: // RSB - new_pc = op2 - Rn; - break; - case 0x4: // ADD - new_pc = Rn + op2; - break; - case 0x5: // ADC - c = (gdb_arch_regs[GDB_CPSR] & PS_C) != 0; - new_pc = Rn + op2 + c; - break; - case 0x6: // SBC - c = (gdb_arch_regs[GDB_CPSR] & PS_C) != 0; - new_pc = Rn - op2 + c - 1; - break; - case 0x7: // RSC - c = (gdb_arch_regs[GDB_CPSR] & PS_C) != 0; - new_pc = op2 - Rn +c - 1; - break; - case 0x8: // TST - case 0x9: // TEQ - case 0xA: // CMP - case 0xB: // CMN - break; // PC doesn't change - case 0xC: // ORR - new_pc = Rn | op2; - break; - case 0xD: // MOV - new_pc = op2; - break; - case 0xE: // BIC - new_pc = Rn & ~op2; - break; - case 0xF: // MVN - new_pc = ~op2; - break; - } - } - } - return new_pc; - case 0x1: - if ((ins & 0x02000010) == 0x02000010) { - // Undefined! - return (unsigned long)(pc+1); - } else { - if ((ins & 0x00100000) == 0) { - // STR - return (unsigned long)(pc+1); - } else { - // LDR - if ((ins & 0x0000F000) != 0x0000F000) { - // Rd not PC - return (unsigned long)(pc+1); - } else { - Rn = (unsigned long)gdb_arch_regs[(ins & 0x000F0000) >> 16]; - if ((ins & 0x000F0000) == 0x000F0000) Rn += 8; // PC prefetch! - if (ins & 0x01000000) { - // Add/subtract offset before - if ((ins & 0x02000000) == 0) { - // Immediate offset - if (ins & 0x00800000) { - // Add offset - Rn += (ins & 0x00000FFF); - } else { - // Subtract offset - Rn -= (ins & 0x00000FFF); - } - } else { - // Offset is in a register - if (ins & 0x00800000) { - // Add offset - Rn += RmShifted(ins & 0x00000FFF); - } else { - // Subtract offset - Rn -= RmShifted(ins & 0x00000FFF); - } - } - } - return *(unsigned long *)Rn; - } - } - } - return (unsigned long)(pc+1); - case 0x2: // Branch, LDM/STM - if ((ins & 0x02000000) == 0) { - // LDM/STM - if ((ins & 0x00100000) == 0) { - // STM - return (unsigned long)(pc+1); - } else { - // LDM - if ((ins & 0x00008000) == 0) { - // PC not in list - return (unsigned long)(pc+1); - } else { - Rn = (unsigned long)gdb_arch_regs[(ins & 0x000F0000) >> 16]; - if ((ins & 0x000F0000) == 0x000F0000) Rn += 8; // PC prefetch! - offset = ins & 0x0000FFFF; - reg_count = 0; - for (i = 0; i < 15; i++) { - if (offset & (1< - -#ifndef RT_GDB_HAVE_HWBP - #define RT_GDB_HAVE_HWBP 1 -#endif -#ifndef RT_GDB_HAVE_SWBP - #define RT_GDB_HAVE_SWBP 0 -#endif - -#ifndef GDB_CORTEXM_PRIORITY_MAX - #define GDB_CORTEXM_PRIORITY_MAX (1 << 6) -#endif - -#define GDB_DATA_ACCESS - -#define BREAK_INSTR_SIZE 4 -#define ARM_GP_REGS 16 -#define ARM_FP_REGS 8 -#define ARM_EXTRA_REGS 2 -#define GDB_MAX_REGS (ARM_GP_REGS + (ARM_FP_REGS * 3) + ARM_EXTRA_REGS) -#define NUMREGBYTES (GDB_MAX_REGS << 2) - -#define HBP_NUM 6 //Max hardware breakpoint -#define HWP_NUM 4 //Max hardware watchpoint - -//#define BUFMAX ((NUMREGBYTES << 1) + 10) -#define BUFMAX 400 - -#define GDB_DEBUG_REG_BASE 0xE000EDF0 -#define GDB_DEBUG_REG_DHSR 0x00 -#define GDB_DEBUG_REG_DCRSR 0x04 -#define GDB_DEBUG_REG_DCRDR 0x08 -#define GDB_DEBUG_REG_DEMCR 0x0c - -#define GDB_DEBUG_REG_DEMCR_MON_EN (1UL << 16) -#define GDB_DEBUG_REG_DEMCR_MON_PEND (1UL << 17) -#define GDB_DEBUG_REG_DEMCR_MON_STEP (1UL << 18) -#define GDB_DEBUG_REG_DEMCR_TRCENA (1UL << 24) - -#define GDB_NVIC_REG_BASE 0xE000E000 -#define GDB_NVIC_REG_SHCSR 0xD24 -#define GDB_NVIC_REG_DFSR 0xD30 - -#define GDB_NVIC_REG_SHCSR_MEMFAULTENA (1 << 16) - -#define GDB_FPB_REG_BASE 0xE0002000 -#define GDB_FPB_REG_CTRL 0x0 -#define GDB_FPB_REG_REMAP 0x4 -#define GDB_FPB_REG_COMP 0x8 - -#define GDB_FPB_REG_CTRL_KEY (1UL << 1) -#define GDB_FPB_REG_CTRL_ENABLE 1 -#define GDB_FPB_REG_COMP_ENABLE 1 -#define GDB_FPB_REG_COMP_ADDR (((1UL << 29) -1) << 2) -#define GDB_FPB_REG_COMP_REPLACE (((1UL << 32) -1) << 30) - -#define GDB_DWT_REG_BASE 0xE0001000 -#define GDB_DWT_REG_CTRL 0x0 -#define GDB_DWT_REG_COMP 0x20 -#define GDB_DWT_REG_MASK 0x24 -#define GDB_DWT_REG_FUNCTION 0x28 - -#define GDB_DWT_REG_FUNCTION_FUC (((1UL << 4) -1) << 0) - - - - -enum regnames { - GDB_R0, /*0*/ - GDB_R1, /*1*/ - GDB_R2, /*2*/ - GDB_R3, /*3*/ - GDB_R4, /*4*/ - GDB_R5, /*5*/ - GDB_R6, /*6*/ - GDB_R7, /*7*/ - GDB_R8, /*8*/ - GDB_R9, /*9*/ - GDB_R10, /*10*/ - GDB_FP, /*11*/ - GDB_IP, /*12*/ - GDB_SPT, /*13*/ - GDB_LR, /*14*/ - GDB_PC, /*15*/ - GDB_F0, /*16*/ - GDB_F1, /*17*/ - GDB_F2, /*18*/ - GDB_F3, /*19*/ - GDB_F4, /*20*/ - GDB_F5, /*21*/ - GDB_F6, /*22*/ - GDB_F7, /*23*/ - GDB_FPS, /*24*/ - GDB_CPSR = GDB_MAX_REGS-1 -}; - -typedef struct -{ - unsigned long type; // State type - unsigned long vector; // Exception vector number - unsigned long basepri; // BASEPRI - - unsigned long r4; // Remaining CPU registers - unsigned long r5; // Remaining CPU registers - unsigned long r6; // Remaining CPU registers - unsigned long r7; // Remaining CPU registers - unsigned long r8; // Remaining CPU registers - unsigned long r9; // Remaining CPU registers - unsigned long r10; // Remaining CPU registers - unsigned long r11; // Remaining CPU registers - unsigned long sp; // Remaining CPU registers - - unsigned long xlr; // Exception return LR - // The following are saved and restored automatically by the CPU - // for exceptions or interrupts. - unsigned long r0; - unsigned long r1; - unsigned long r2; - unsigned long r3; - unsigned long r12; - unsigned long lr; - unsigned long pc; - unsigned long psr; -} Gdb_SavedRegisters; - -/* arch */ -extern struct gdb_arch arch_gdb_ops; -void gdb_breakpoint(); -void gdb_get_register(unsigned long *gdb_regs); -void gdb_put_register(unsigned long *gdb_regs); -void gdb_set_register(void *hw_regs); -int gdb_arch_handle_exception(char *remcom_in_buffer, - char *remcom_out_buffer); - -int gdb_permit_data_access(unsigned long addr, unsigned long count); -void gdb_arch_exit(); -void gdb_arch_late(); - -#endif /* __CORTEXM_GDB_H__ */ diff --git a/components/gdb/libcpu/cortexm/cortexm_stub.c b/components/gdb/libcpu/cortexm/cortexm_stub.c deleted file mode 100644 index bcbdc39dd1b08af65e3f3f718176aa59a4866c2c..0000000000000000000000000000000000000000 --- a/components/gdb/libcpu/cortexm/cortexm_stub.c +++ /dev/null @@ -1,414 +0,0 @@ -/* - * CORTEXM GDB support - * arch-specific portion of GDB stub - * - * File : cortexm_stub.c - * This file is part of RT-Thread RTOS - * COPYRIGHT (C) 2006, RT-Thread Develop Team - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rt-thread.org/license/LICENSE - * - * Change Logs: - * Date Author Notes - * 2014-07-04 Wzyy2 first version - */ -#include -#include -#include - -static Gdb_SavedRegisters *regs; -unsigned long single_step_basepri = 0; - -void gdb_remove_all_hw_break(); -void gdb_enable_hw_debug(); -void gdb_disable_hw_debug(); -int gdb_set_hw_break(unsigned long, int, enum gdb_bptype); -int gdb_remove_hw_break(unsigned long, int, enum gdb_bptype); - -/*struct gdb_arch - Describe architecture specific values.*/ -struct gdb_arch arch_gdb_ops = { - /* Breakpoint instruction: */ - .gdb_bpt_instr = {0xfe, 0xde, 0xff, 0xe7}, //Little-Endian - .flags = RT_GDB_HAVE_HWBP, - .set_hw_breakpoint = gdb_set_hw_break, - .remove_hw_breakpoint = gdb_remove_hw_break, - .remove_all_hw_break = gdb_remove_all_hw_break -}; - -static struct hw_breakpoint { - int enabled; - unsigned long addr; -} breakinfo[HBP_NUM]; - -static struct hw_watchpoint { - int enabled; - unsigned long addr; - int len; - enum gdb_bptype type; -} watchinfo[HWP_NUM]; - -//The following table defines the memory areas that GDB is allow to touch -static const struct { - unsigned long start; - unsigned long end; -} data_access[] = -{ - { 0x20000000, 0x40000000-1}, // On-chip ram - { 0x60000000, 0xa0000000-1}, // External ram - { 0x00000000, 0x20000000-1}, // On-chip flash - { 0x60000000, 0xa0000000-1}, // External flash - { 0xE0000000, 0x00000000-1}, // cortex-M peripheral - { 0x40000000, 0x60000000-1}, // mcu peripheral -}; - - -int gdb_permit_data_access(unsigned long addr, unsigned long count) -{ - unsigned char i; - - for (i = 0; i < sizeof(data_access)/sizeof(data_access[0]); i++) { - if ((addr >= data_access[i].start) && (addr + count) <= data_access[i].end) { - return 0; - } - } - - return -1; -} - -/*we need to block all pending interrupts by swtting basepri - * before doing the steo - */ -void gdb_single_step() -{ - volatile unsigned long *base; - - //mask all interrupts - single_step_basepri = regs->basepri; - regs->basepri = GDB_CORTEXM_PRIORITY_MAX; - - //When MON_EN = 1, this steps the core - base = (unsigned long*)(GDB_DEBUG_REG_BASE + GDB_DEBUG_REG_DEMCR); - *base |= GDB_DEBUG_REG_DEMCR_MON_STEP; - - /* Clear any bits set in DFSR*/ - base = (unsigned long*)(GDB_NVIC_REG_BASE + GDB_NVIC_REG_DFSR); - *base = 0xffffffff; - -} - -void gdb_clear_single_step() -{ - volatile unsigned long *base; - - regs->basepri = single_step_basepri; - - /*clear single step*/ - base = (unsigned long*)(GDB_DEBUG_REG_BASE + GDB_DEBUG_REG_DEMCR); - *base &= ~GDB_DEBUG_REG_DEMCR_MON_STEP; - - // Clear any bits set in DFSR - base = (unsigned long*)(GDB_NVIC_REG_BASE + GDB_NVIC_REG_DFSR); - *base = 0xffffffff; - -} - -/** - * gdb_breakpoint - generate a breadk - * It is used to sync up with a debugger and stop progarm - */ -void gdb_breakpoint() -{ - volatile unsigned long *base; - - // Enable the FPB-FLASH PATCH BREAKPOINT - base = (unsigned long*)(GDB_FPB_REG_BASE + GDB_FPB_REG_CTRL); - *base |= GDB_FPB_REG_CTRL_KEY | GDB_FPB_REG_CTRL_ENABLE ; - - base = (unsigned long*)(GDB_DEBUG_REG_BASE + GDB_DEBUG_REG_DEMCR); - /* - * Enable the debug monitor. When enabled, the System handler priority - * register controls its priority level. - * If disabled, then all debug events go - * to Hard fault - */ - *base |= GDB_DEBUG_REG_DEMCR_MON_EN; - - // Enable DWT - *base |= GDB_DEBUG_REG_DEMCR_TRCENA ; - - //Fall into debug monitor - *base |= GDB_DEBUG_REG_DEMCR_MON_PEND; - -} - -void gdb_set_register(void *hw_regs) -{ - regs = hw_regs; -} - -void gdb_get_register(unsigned long *gdb_regs) -{ - int regno; - /* Initialize all to zero. */ - for (regno = 0; regno < GDB_MAX_REGS; regno++) - gdb_regs[regno] = 0; - - gdb_regs[GDB_R0] = regs->r0; - gdb_regs[GDB_R1] = regs->r1; - gdb_regs[GDB_R2] = regs->r2; - gdb_regs[GDB_R3] = regs->r3; - gdb_regs[GDB_R4] = regs->r4; - gdb_regs[GDB_R5] = regs->r5; - gdb_regs[GDB_R6] = regs->r6; - gdb_regs[GDB_R7] = regs->r7; - gdb_regs[GDB_R8] = regs->r8; - gdb_regs[GDB_R9] = regs->r9; - gdb_regs[GDB_R10] = regs->r10; - gdb_regs[GDB_FP] = regs->r11; - gdb_regs[GDB_IP] = regs->r12; - gdb_regs[GDB_SPT] = regs->sp; - gdb_regs[GDB_LR] = regs->lr; - gdb_regs[GDB_PC] = regs->pc; - gdb_regs[GDB_CPSR] = regs->psr; - -}; - - -void gdb_put_register(unsigned long *gdb_regs) -{ - regs->r0 = gdb_regs[GDB_R0]; - regs->r1 = gdb_regs[GDB_R1]; - regs->r2 = gdb_regs[GDB_R2]; - regs->r3 = gdb_regs[GDB_R3]; - - regs->r4 = gdb_regs[GDB_R4]; - regs->r5 = gdb_regs[GDB_R5]; - regs->r6 = gdb_regs[GDB_R6]; - regs->r7 = gdb_regs[GDB_R7]; - regs->r8 = gdb_regs[GDB_R8]; - regs->r9 = gdb_regs[GDB_R9]; - regs->r10 = gdb_regs[GDB_R10]; - regs->r11 = gdb_regs[GDB_FP]; - regs->r12 = gdb_regs[GDB_IP]; - regs->sp = gdb_regs[GDB_SPT]; - regs->lr = gdb_regs[GDB_LR]; - regs->pc = gdb_regs[GDB_PC]; - regs->psr = gdb_regs[GDB_CPSR]; - -} - - -/* It will be called during process_packet */ -int gdb_arch_handle_exception(char *remcom_in_buffer, - char *remcom_out_buffer) -{ - unsigned long addr; - char *ptr; - static int step = 0; - - if (step){ - gdb_clear_single_step(); - step = 0; - } - - switch (remcom_in_buffer[0]) { - case 'D': - case 'k': - case 'c': - /* - * If this was a compiled breakpoint, we need to move - * to the next instruction or we will breakpoint - * over and over again - */ - ptr = &remcom_in_buffer[1]; - if (gdb_hex2long(&ptr, &addr)) - regs->pc = addr; - - return 0; - case 's': - ptr = &remcom_in_buffer[1]; - if (gdb_hex2long(&ptr, &addr)) - regs->pc = addr; - - gdb_single_step(); - step = 1; - - return 0; - } - - return -1; - -} - -int gdb_set_hw_break(unsigned long addr, int len, enum gdb_bptype bptype) -{ - int i; - - if (bptype == BP_HARDWARE_BREAKPOINT) { - for (i = 0; i < HBP_NUM; i++) - if (!breakinfo[i].enabled) - break; - if (i == HBP_NUM) - return -1; - breakinfo[i].addr = addr; - breakinfo[i].enabled = 1; - } - else if (bptype == BP_WRITE_WATCHPOINT) { - for (i = 0; i < HWP_NUM; i++) - if (!watchinfo[i].enabled) - break; - if (i == HWP_NUM) - return -1; - watchinfo[i].addr = addr; - watchinfo[i].len = len; - watchinfo[i].type = BP_WRITE_WATCHPOINT; - watchinfo[i].enabled = 1; - } - else if (bptype == BP_READ_WATCHPOINT) { - for (i = 0; i < HWP_NUM; i++) - if (!watchinfo[i].enabled) - break; - if (i == HWP_NUM) - return -1; - watchinfo[i].addr = addr; - watchinfo[i].len = len; - watchinfo[i].type = BP_READ_WATCHPOINT; - watchinfo[i].enabled = 1; - } - else if (bptype == BP_ACCESS_WATCHPOINT) { - for (i = 0; i < HWP_NUM; i++) - if (!watchinfo[i].enabled) - break; - if (i == HWP_NUM) - return -1; - watchinfo[i].addr = addr; - watchinfo[i].len = len; - watchinfo[i].type = BP_ACCESS_WATCHPOINT; - watchinfo[i].enabled = 1; - } - - return 0; -} - -int gdb_remove_hw_break(unsigned long addr, int len, enum gdb_bptype bptype) -{ - int i; - - if (bptype == BP_HARDWARE_BREAKPOINT) { - for (i = 0; i < HBP_NUM; i++) - if (breakinfo[i].addr == addr && breakinfo[i].enabled) - break; - if (i == HBP_NUM) - return -1; - breakinfo[i].enabled = 0; - - } - else if (bptype == BP_WRITE_WATCHPOINT) { - for (i = 0; i < HWP_NUM; i++) - if (watchinfo[i].addr == addr && watchinfo[i].enabled && watchinfo[i].type == bptype) - break; - if (i == HWP_NUM) - return -1; - watchinfo[i].enabled = 0; - - } - else if (bptype == BP_READ_WATCHPOINT) { - for (i = 0; i < HWP_NUM; i++) - if (watchinfo[i].addr == addr && watchinfo[i].enabled && watchinfo[i].type == bptype) - break; - if (i == HWP_NUM) - return -1; - watchinfo[i].enabled = 0; - - } - else if (bptype == BP_ACCESS_WATCHPOINT) { - for (i = 0; i < HWP_NUM; i++) - if (watchinfo[i].addr == addr && watchinfo[i].enabled && watchinfo[i].type == bptype) - break; - if (i == HWP_NUM) - return -1; - watchinfo[i].enabled = 0; - - } - - return 0; -} - -void gdb_remove_all_hw_break() -{ - int i; - volatile unsigned long *base; - - // Disable hardware break - for (i = 0; i < HBP_NUM; i++) { - if (!breakinfo[i].enabled) - break; - base = (unsigned long*)(GDB_FPB_REG_BASE + GDB_FPB_REG_COMP + i * 4); - *base &= ~GDB_FPB_REG_COMP_ENABLE ; - } - - // Disable watchpoint - for (i = 0; i < HWP_NUM; i++) { - if (!watchinfo[i].enabled) - break; - base = (unsigned long*)(GDB_DWT_REG_BASE + GDB_DWT_REG_FUNCTION + i * 12); - *base &= ~GDB_DWT_REG_FUNCTION_FUC ; - } - -} - -void gdb_arch_late() -{ - gdb_remove_all_hw_break(); -} - -void gdb_arch_exit() -{ - volatile unsigned long *base; - char num = 1; - int i; - - // Install the hardware break - for (i = 0; i < HBP_NUM; i++) { - if (breakinfo[i].enabled) { - base = (unsigned long*)(GDB_FPB_REG_BASE + GDB_FPB_REG_COMP + i * 4); - - *base = GDB_FPB_REG_COMP_ADDR & ((unsigned long)(breakinfo[i].addr)); - - if (breakinfo[i].addr & 2) - *base |= (1UL << 31); //set BKPT on upper halfword - else - *base |= (1UL << 30); //set BKPT on lower halfword, - - *base |= GDB_FPB_REG_COMP_ENABLE ; - } - } - - // Install the watchpoint - for (i = 0; i < HWP_NUM; i++) { - if (watchinfo[i].enabled) { - base = (unsigned long*)(GDB_DWT_REG_BASE + GDB_DWT_REG_COMP + i * 12); - *base = watchinfo[i].addr; - - base = (unsigned long*)(GDB_DWT_REG_BASE + GDB_DWT_REG_MASK + i * 12); - while (watchinfo[i].len >> num) { - num++; - } - *base = num - 1; //DWT matching is performed as:(ADDR & (~0 << MASK)) == COMP - - base = (unsigned long*)(GDB_DWT_REG_BASE + GDB_DWT_REG_FUNCTION + i * 12); - - if (watchinfo[i].type == BP_WRITE_WATCHPOINT) - *base = (*base & ~GDB_DWT_REG_FUNCTION_FUC) + 0x05; - else if (watchinfo[i].type == BP_READ_WATCHPOINT) - *base = (*base & ~GDB_DWT_REG_FUNCTION_FUC) + 0x06; - else if (watchinfo[i].type == BP_ACCESS_WATCHPOINT) - *base = (*base & ~GDB_DWT_REG_FUNCTION_FUC) + 0x07; - - } - } - -} - diff --git a/components/gdb/libcpu/cortexm/gdb_gcc.S b/components/gdb/libcpu/cortexm/gdb_gcc.S deleted file mode 100644 index e6c5ab95e8a55923c747db8b494da5f1762934db..0000000000000000000000000000000000000000 --- a/components/gdb/libcpu/cortexm/gdb_gcc.S +++ /dev/null @@ -1,27 +0,0 @@ -.cpu cortex-m4 -.syntax unified -.thumb -.text - -.global DebugMon_Handler -.type DebugMon_Handler, %function -DebugMon_Handler: - mrs r0,psp ;// Get process stack - sub r1,r0,#(4*13) ;// Make space for saved state - msr psp,r1 ;// Ensure PSP is up to date - - mov r12,r0 ;// R12 = stack - mov r1,#1 ;// R1 = exception state type - mrs r2,ipsr ;// R2 = vector number - mrs r3,basepri ;// R3 = basepri - stmfd r0!,{r1-r12,lr} ;// Push type, vector, basepri, r4-11 - - mov r4,r0 ;// R4 = saved state pointer - bl rt_hw_debugmon_exception - - mov r0,r4 ;// R4 = saved state pointer - ldmfd r0!,{r1-r12,lr} ;// Pop type, vec, basepri, registers and LR - msr psp,r0 ;// Restore PSP - msr basepri,r3 ;// Restore basepri - - bx lr ;// Return diff --git a/components/gdb/libcpu/cortexm/gdb_handler.c b/components/gdb/libcpu/cortexm/gdb_handler.c deleted file mode 100644 index 05904224c210fbe7b923644e2b0bf26130d5a195..0000000000000000000000000000000000000000 --- a/components/gdb/libcpu/cortexm/gdb_handler.c +++ /dev/null @@ -1,11 +0,0 @@ -#include -#include - -void rt_hw_debugmon_exception(void *regs) -{ -#ifdef RT_USING_GDB - gdb_arch_late(); - gdb_handle_exception(SIGTRAP, regs); - gdb_arch_exit(); -#endif -} diff --git a/components/gdb/readme-zh.txt b/components/gdb/readme-zh.txt deleted file mode 100644 index 06cdc01c7689573dba778877d7d4aac9ae82ec22..0000000000000000000000000000000000000000 --- a/components/gdb/readme-zh.txt +++ /dev/null @@ -1,118 +0,0 @@ -说明: - -一 当前版本进度 - -1).分类 -考虑到arm各种版本的调试寄存器地址和种类都有很大不同 -所以分为两个版本,均只在GCC下编译 - - 1.基础ARM(软件断点(使用undef指令的办法),需要ram运行,模拟单步) - 2.cortex M系列(不支持M0,基于寄存器操作,支持硬件断点,数据观察点,硬件单步) - -理论上cortexA系列和cortexM的调式单元是一样的,有需要的话也可以在基础arm版本里单独为cortexA做出可选的数据断点,硬件单步 - -二 安装说明 - -1) 下载 - 下载最新RT-THREAD GDB STUB代码,并解压 - -2) 加入RT-Thread - 先将得到的components文件夹覆盖RTT根目录 - 然后若要使用BBB板测试GDB,就用BSP/beaglebone和libpcu/am335x覆盖RTT下的同名文件夹 - - 若要使用STM32F407测试GDB,就用BSP/stm32F4xx覆盖RTT下的同名文件夹,同时更改编译器为gcc - -3) 宏 - 打开RT_USING_GDB - -三 宏配置说明 - -1) RT_GDB_HAVE_HWBP - 1硬件断点 - -2) RT_GDB_HAVE_SWBP - 1软件断点 - -3) RT_GDB_MAX_BREAKPOINTS - 最大软件断点数量 - 不加默认20 - -4) RT_GDB_ICACHE - 是否使用ICACHE - 若使用了ICACHE则要开启此宏,保证断点覆盖后及时刷新 - -5) RT_GDB_DEBUG - 测试开发用 - 会打印GDB收发信息到默认串口上,以供获取数据 - -四 使用说明 - -1) 设置serial设备 - 首先需要调用 - void gdb_set_device(const char* device_name); (gdb_stub.h) - 设置相应的GDB通信端口 - PS: - 首先serial的驱动不能是中断 - 其次收发函数最好是poll的,要不就是9600,不然可能会出现问题 - 若出现问题,请打开 RT_GDB_DEBUG ,观察收发是否正常。 - -2) 进入GDB stub - 调用 - void gdb_start(); (gdb_stub.h) - 触发异常,即可进入等待状态 等待GDB连接 - 也可以将该函数加入按键中断中,可以实现外部打断程序的效果(条件有限,未测试) - -3) pc连接 - 确认GCC 打开-g选项后编译 - 然后arm-none-eabi-gdb xxxx.elf or axf - 进如GDB界面后 - set serial baud 115200(or 9600) - target remote /dev/ttyUSB0(linux) or COM1 (windows) - 即可实现GDB对接 - -PS: - BBB板默认uart4作为GDB通信口 - STM32F407默认uart6作GDB通信 - -五 移植说明 - -若要移植到不同架构上 -软件实现请参考gdb/libcpu/arm下的文件 -硬件实现请参考gdb/libcpu/cortexm下的文件 -需要rsp协议的话 请参考https://www.sourceware.org/gdb/current/onlinedocs/gdb/Remote-Protocol.html - -若要移植到已有架构的芯片上 -1) arm9,11以及cortexA - 修改udef和dabt的函数,在/libcpu/arm/am335x/trap.c里,加入ifdef GDB的内容 - 将libcpu/arm/am335x/start_gcc.s的相关异常向量汇编复制到自己的undef和dabt异常向量里 - 分配足够的栈空间给undef - -2) cortexM3以及M4 - 删除已有的debugmon_handler - 优先级分组有变化的话,重定义宏GDB_CORTEXM_PRIORITY_MAX,就是basepri的设置值,满足屏蔽中断的同时不屏蔽debugmon - 使用有需要的话,重定义cortexm_stub.c的data_acess数组,也就是允许GDB访问的地址空间 - 增大_system_stack_size,也就是MSP栈的大小 - - -六 易错或者bug(出错了看这里) - -编译器选项是否打开-g,是否使用GCC编译 -硬件断点使用超过(max-1)个后,单步可能会出现不正常 -检查串口通信是否正常,可以打开RT_GDB_DEBUG -堆栈大小是否设置合适(因为gdb要在handler模式下运行,所需要的栈大小比较大,大概0x200) -cm系列切记如果优先级分组不同于默认设置,就要重定义宏GDB_CORTEXM_PRIORITY_MAX,使抢占优先级等于1,不然单步可能会出现问题(被中断抢占) -cm系列在中断里设置断点会出现错误(目测程序还是正常工作,就是压栈的寄存器还是进入中断前的,所以返回的寄存器信息有误) -cm系列可能会因为访问不可访问的地址造成出错,有需求自己手动修改cortexm_stub.c的data_acess数组(没找到好的办法,falut后寄存器全乱了) - - -## - 嫌速度慢的话就把串口速度9600改成115200 - 不过如此就要把注册的驱动里的getc改成阻塞的,不然会收不到 - 类似 - while(!(UART_LSR_REG(uart->base) & 0x01)); - ch = UART_RHR_REG(uart->base) & 0xff; - 原先是 - if (UART_LSR_REG(uart->base) & 0x01) - { - ch = UART_RHR_REG(uart->base) & 0xff; - }