Browse Source

Merge pull request #343 from wzyy2/master

[GDB stub]add GDB stub
Bernard Xiong 11 years ago
parent
commit
ec64b60c06

+ 8 - 0
bsp/beaglebone/applications/application.c

@@ -16,6 +16,10 @@
 #include <rtthread.h>
 #include <components.h>
 
+#ifdef RT_USING_GDB
+#include <gdb_stub.h>
+#endif
+
 int rt_application_init()
 {
     /* do component initialization */
@@ -23,6 +27,10 @@ int rt_application_init()
 #ifdef RT_USING_NEWLIB
 	libc_system_init(RT_CONSOLE_DEVICE_NAME);
 #endif
+#ifdef RT_USING_GDB
+    gdb_set_device("uart4");
+    gdb_start();
+#endif
 
     return 0;
 }

+ 8 - 3
bsp/beaglebone/drivers/serial.c

@@ -80,6 +80,11 @@ static rt_err_t am33xx_configure(struct rt_serial_device *serial, struct serial_
         UART_DLL_REG(base) = 26;
         UART_DLH_REG(base) = 0;
     }
+    else if (cfg->baud_rate == BAUD_RATE_9600)
+    {
+        UART_DLL_REG(base) = 0x38;
+        UART_DLH_REG(base) = 1;
+    }
     else
     {
         NOT_IMPLEMENTED();
@@ -439,7 +444,7 @@ int rt_hw_serial_init(void)
 #endif
 
 #ifdef RT_USING_UART4
-    config.baud_rate = BAUD_RATE_115200;
+    config.baud_rate = BAUD_RATE_9600;
     config.bit_order = BIT_ORDER_LSB;
     config.data_bits = DATA_BITS_8;
     config.parity    = PARITY_NONE;
@@ -450,14 +455,14 @@ int rt_hw_serial_init(void)
     serial4.ops    = &am33xx_uart_ops;
     serial4.config = config;
     /* enable RX interrupt */
-    UART_IER_REG(uart4.base) = 0x01;
+    UART_IER_REG(uart4.base) = 0x00;
     /* install ISR */
     rt_hw_interrupt_install(uart4.irq, am33xx_uart_isr, &serial4, "uart4");
     rt_hw_interrupt_control(uart4.irq, 0, 0);
     rt_hw_interrupt_mask(uart4.irq);
     /* register UART4 device */
     rt_hw_serial_register(&serial4, "uart4",
-            RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX,
+            RT_DEVICE_FLAG_RDWR,
             &uart4);
 #endif
 

+ 6 - 0
bsp/beaglebone/rtconfig.h

@@ -2,6 +2,12 @@
 #ifndef __RTTHREAD_CFG_H__
 #define __RTTHREAD_CFG_H__
 
+// <section name="RT_USING_GDB" description="Gdb Stub for rtt" default="true" >
+//#define RT_USING_GDB
+//#define RT_GDB_DEBUG
+#define RT_GDB_ICACHE
+// </section>
+
 // <RDTConfigurator URL="http://www.rt-thread.com/eclipse">
 
 // <integer name="RT_NAME_MAX" description="Maximal size of kernel object name length" default="6" />

+ 1 - 1
bsp/beaglebone/rtconfig.py

@@ -23,7 +23,7 @@ elif CROSS_TOOL == 'iar':
 if os.getenv('RTT_EXEC_PATH'):
 	EXEC_PATH = os.getenv('RTT_EXEC_PATH')
 
-BUILD = 'release'
+BUILD = 'debug'
 
 if PLATFORM == 'gcc':
     # toolchains

+ 10 - 0
bsp/stm32f40x/applications/application.c

@@ -23,8 +23,18 @@
 #include "stm32_eth.h"
 #endif
 
+#ifdef RT_USING_GDB
+#include <gdb_stub.h>
+#endif
+
 void rt_init_thread_entry(void* parameter)
 {
+    /* GDB STUB */
+#ifdef RT_USING_GDB
+    gdb_set_device("uart6");
+    gdb_start();
+#endif
+
     /* LwIP Initialization */
 #ifdef RT_USING_LWIP
     {

+ 1 - 0
bsp/stm32f40x/drivers/board.h

@@ -43,6 +43,7 @@
 //#define RT_USING_UART1
 #define RT_USING_UART2
 //#define RT_USING_UART3
+//#define RT_USING_UART6
 
 // <o> Console on USART: <0=> no console <1=>USART 1 <2=>USART 2 <3=> USART 3
 // 	<i>Default: 1

+ 6 - 5
bsp/stm32f40x/drivers/stm32f4xx_it.c

@@ -117,9 +117,10 @@ void SVC_Handler(void)
   * @param  None
   * @retval None
   */
-void DebugMon_Handler(void)
-{
-}
+//void DebugMon_Handler(void)
+//{
+    // defined in gdb/libcpu/cortexm/gdb_gcc.S
+//}
 
 /**
   * @brief  This function handles PendSVC exception.
@@ -128,7 +129,7 @@ void DebugMon_Handler(void)
   */
 //void PendSV_Handler(void)
 //{
-//    // definition in libcpu/arm/cortex-m4/context_*.S
+//    // defined in libcpu/arm/cortex-m4/context_*.S
 //}
 
 /**
@@ -138,7 +139,7 @@ void DebugMon_Handler(void)
   */
 //void SysTick_Handler(void)
 //{
-//    // definition in boarc.c
+//    // defined in boarc.c
 //}
 
 /******************************************************************************/

+ 60 - 0
bsp/stm32f40x/drivers/usart.c

@@ -69,6 +69,17 @@ struct stm32_serial_device uart3 =
 struct rt_device uart3_device;
 #endif
 
+#ifdef RT_USING_UART6
+struct stm32_serial_int_rx uart6_int_rx;
+struct stm32_serial_device uart6 =
+{
+    USART6,
+    &uart6_int_rx,
+    RT_NULL
+};
+struct rt_device uart6_device;
+#endif
+
 //#define USART1_DR_Base  0x40013804
 //#define USART2_DR_Base  0x40004404
 //#define USART3_DR_Base  0x40004804
@@ -103,6 +114,14 @@ struct rt_device uart3_device;
 #define UART3_TX_DMA        DMA1_Stream1
 #define UART3_RX_DMA        DMA1_Stream3
 
+#define UART6_GPIO_TX       GPIO_Pin_6
+#define UART6_TX_PIN_SOURCE GPIO_PinSource6
+#define UART6_GPIO_RX       GPIO_Pin_7
+#define UART6_RX_PIN_SOURCE GPIO_PinSource7
+#define UART6_GPIO          GPIOC
+#define UART6_GPIO_RCC      RCC_AHB1Periph_GPIOC
+#define RCC_APBPeriph_UART6 RCC_APB2Periph_USART6
+
 static void RCC_Configuration(void)
 {
 #ifdef RT_USING_UART1
@@ -128,6 +147,13 @@ static void RCC_Configuration(void)
     /* DMA clock enable */
     RCC_APB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE);
 #endif
+
+#ifdef RT_USING_UART6
+    /* Enable USART6 GPIO clocks */
+    RCC_AHB1PeriphClockCmd(UART6_GPIO_RCC, ENABLE);
+    /* Enable USART6 clock */
+    RCC_APB2PeriphClockCmd(RCC_APBPeriph_UART6, ENABLE);
+#endif
 }
 
 static void GPIO_Configuration(void)
@@ -168,6 +194,16 @@ static void GPIO_Configuration(void)
     GPIO_PinAFConfig(UART3_GPIO, UART3_TX_PIN_SOURCE, GPIO_AF_USART3);
     GPIO_PinAFConfig(UART3_GPIO, UART3_RX_PIN_SOURCE, GPIO_AF_USART3);
 #endif
+
+#ifdef RT_USING_UART6
+    /* Configure USART6 Rx/tx PIN */
+    GPIO_InitStructure.GPIO_Pin = UART6_GPIO_TX | UART6_GPIO_RX;
+    GPIO_Init(UART6_GPIO, &GPIO_InitStructure);
+
+    /* Connect alternate function */
+    GPIO_PinAFConfig(UART6_GPIO, UART6_TX_PIN_SOURCE, GPIO_AF_USART6);
+    GPIO_PinAFConfig(UART6_GPIO, UART6_RX_PIN_SOURCE, GPIO_AF_USART6);
+#endif
 }
 
 static void NVIC_Configuration(void)
@@ -204,6 +240,15 @@ static void NVIC_Configuration(void)
     NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
     NVIC_Init(&NVIC_InitStructure);
 #endif
+
+#ifdef RT_USING_UART6
+    /* Enable the USART6 Interrupt */
+    NVIC_InitStructure.NVIC_IRQChannel = USART6_IRQn;
+    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
+    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
+    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
+    NVIC_Init(&NVIC_InitStructure);
+#endif
 }
 
 static void DMA_Configuration(void)
@@ -346,4 +391,19 @@ void rt_hw_usart_init()
     /* enable interrupt */
     USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);
 #endif
+
+#ifdef RT_USING_UART6
+    USART_InitStructure.USART_BaudRate = 9600;
+    USART_InitStructure.USART_WordLength = USART_WordLength_8b;
+    USART_InitStructure.USART_StopBits = USART_StopBits_1;
+    USART_InitStructure.USART_Parity = USART_Parity_No;
+    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
+    USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
+    USART_Init(USART6, &USART_InitStructure);
+
+    /* register uart6 */
+    rt_hw_serial_register(&uart6_device, "uart6",
+        RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_STREAM,
+        &uart6);
+#endif
 }

+ 3 - 0
bsp/stm32f40x/rtconfig.h

@@ -2,6 +2,9 @@
 #ifndef __RTTHREAD_CFG_H__
 #define __RTTHREAD_CFG_H__
 
+/* RT_GDB_STUB */
+//#define RT_USING_GDB
+
 /* RT_NAME_MAX*/
 #define RT_NAME_MAX	   8
 

+ 1 - 1
bsp/stm32f40x/stm32_rom.ld

@@ -10,7 +10,7 @@ MEMORY
     DATA (rw) : ORIGIN = 0x20000000, LENGTH =  128k /* 128K sram */
 }
 ENTRY(Reset_Handler)
-_system_stack_size = 0x100;
+_system_stack_size = 0x200;
 
 SECTIONS
 {

+ 23 - 0
components/gdb/SConscript

@@ -0,0 +1,23 @@
+Import('rtconfig')
+from building import *
+
+comm = 'libcpu/' + rtconfig.ARCH
+if (rtconfig.CPU == 'cortex-m4') or (rtconfig.CPU == 'cortex-m3'):
+    comm = 'libcpu/cortexm'
+
+cwd = GetCurrentDir()
+if rtconfig.PLATFORM == 'armcc':
+	src = Glob('*.c') + Glob(comm + '/*.c') + Glob(comm + '/*_rvds.S')
+
+if rtconfig.PLATFORM == 'gcc':
+	src = Glob('*.c') + Glob(comm + '/*.c') + Glob(comm + '/*_gcc.S')
+
+if rtconfig.PLATFORM == 'iar':
+	src = Glob('*.c') + Glob(comm + '/*.c') + Glob(comm + '/*_iar.S')
+
+
+CPPPATH = [cwd, cwd + '/' + comm]
+
+group = DefineGroup('gdb', src, depend = ['RT_USING_GDB'], CPPPATH = CPPPATH)
+
+Return('group')

+ 1005 - 0
components/gdb/gdb_stub.c

@@ -0,0 +1,1005 @@
+/*
+ * 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 <jason.wessel@windriver.com>
+ *
+ * Copyright (C) 2000-2001 VERITAS Software Corporation.
+ * Copyright (C) 2002-2004 Timesys Corporation
+ * Copyright (C) 2003-2004 Amit S. Kale <amitkale@linsyssoft.com>
+ * Copyright (C) 2004 Pavel Machek <pavel@suse.cz>
+ * Copyright (C) 2004-2006 Tom Rini <trini@kernel.crashing.org>
+ * 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 <mingo@redhat.com>
+ *
+ * Contributors at various stages not listed above:
+ *  Jason Wessel ( jason.wessel@windriver.com )
+ *  George Anzinger <george@mvista.com>
+ *  Anurekh Saxena (anurekh.saxena@timesys.com)
+ *  Lake Stevens Instrument Division (Glenn Engel)
+ *  Jim Kingdon, Cygnus Support.
+ *
+ * Original KGDB stub: David Grothe <dave@gcom.com>,
+ * Tigran Aivazian <tigran@sco.com>
+ *
+ * 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 <rtthread.h>
+#include <rthw.h>
+#include <string.h>
+#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<size; i++) {
+        *(dst_ptr++) = *(src_ptr++);
+    }
+
+    gdb_mem_fault_handler = (void *)0;
+    return 0;
+err:
+    gdb_mem_fault_handler = (void *)0;
+    return -1;
+}
+
+/*
+ * GDB remote protocol parser:
+ */
+static int hex(char ch)
+{
+    if ((ch >= '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;
+
+    /*
+     * $<packet info>#<checksum>.
+     */
+    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 $<data>#<checksum> */
+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, &regno)){
+            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, &regno) && *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);
+}
+

+ 131 - 0
components/gdb/gdb_stub.h

@@ -0,0 +1,131 @@
+/*
+ * 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 <rtthread.h>
+#include <arch_gdb.h>
+
+
+#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__ */

+ 105 - 0
components/gdb/hal_stub.c

@@ -0,0 +1,105 @@
+/*
+ * 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 <rtthread.h>
+#include <rthw.h>
+#include "gdb_stub.h"
+
+#ifdef RT_USING_SERIAL
+#include <rtdevice.h>
+#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;
+}
+

+ 90 - 0
components/gdb/libcpu/arm/arch_gdb.h

@@ -0,0 +1,90 @@
+/*
+ * 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 <rtthread.h>
+
+
+#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__ */

+ 499 - 0
components/gdb/libcpu/arm/arm_stub.c

@@ -0,0 +1,499 @@
+/*
+ * 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 <rtthread.h>
+#include <rthw.h>
+#include <gdb_stub.h>
+#include <arch_gdb.h>
+
+#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<<i)) reg_count++;
+                        }                    
+                        if (ins & 0x00800000) {
+                            // Add offset
+                            Rn += reg_count*4;
+                        } else {
+                            // Subtract offset
+                            Rn -= 4;
+                        }
+                        return *(unsigned long *)Rn;
+                    }
+                }
+            } else {
+                // Branch
+                if (ins_will_execute(ins)) {
+                    offset = (ins & 0x00FFFFFF) << 2;
+                    if (ins & 0x00800000)
+                        offset |= 0xFC000000;  // sign extend   
+                    new_pc = (unsigned long)(pc+2) + offset;
+                    // If its BLX, make new_pc a thumb address.
+                    if ((ins & 0xFE000000) == 0xFA000000) {
+                        if ((ins & 0x01000000) == 0x01000000)
+                            new_pc |= 2;
+                        new_pc = MAKE_THUMB_ADDR(new_pc);
+                    }
+
+                    return new_pc;
+                } else {
+                    // Falls through
+                    return (unsigned long)(pc+1);
+                }
+            }
+        case 0x3:  // Coprocessor & SWI
+            if (((ins & 0x03000000) == 0x03000000) && ins_will_execute(ins)) {
+                // SWI
+                // TODO(wzyy2) some problems.
+                extern unsigned long vector_swi;
+                return vector_swi;
+            } else {
+                return (unsigned long)(pc+1);
+            }
+        default:
+            // Never reached - but fixes compiler warning.
+            return 0;
+    }
+}

+ 158 - 0
components/gdb/libcpu/cortexm/arch_gdb.h

@@ -0,0 +1,158 @@
+/*
+ * CORTEXM GDB support
+ * arch-specific portion of GDB stub
+ * 
+ * File      : arch_gdb.h(cortexm)
+ * 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 <rtthread.h>
+
+#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__ */

+ 414 - 0
components/gdb/libcpu/cortexm/cortexm_stub.c

@@ -0,0 +1,414 @@
+/*
+ * 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 <rtthread.h>
+#include <rthw.h>
+#include <gdb_stub.h>
+
+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;
+
+        }   
+    }
+
+}
+

+ 27 - 0
components/gdb/libcpu/cortexm/gdb_gcc.S

@@ -0,0 +1,27 @@
+.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

+ 11 - 0
components/gdb/libcpu/cortexm/gdb_handler.c

@@ -0,0 +1,11 @@
+#include <rtthread.h>
+#include <gdb_stub.h>
+
+void rt_hw_debugmon_exception(void *regs)
+{
+#ifdef RT_USING_GDB
+    gdb_arch_late();
+    gdb_handle_exception(SIGTRAP, regs);
+    gdb_arch_exit();
+#endif
+}

+ 118 - 0
components/gdb/readme-zh.txt

@@ -0,0 +1,118 @@
+说明: 
+
+一 当前版本进度
+
+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;
+		    }

+ 22 - 2
libcpu/arm/am335x/start_gcc.S

@@ -33,7 +33,7 @@
 .equ I_Bit,           0x80            @ when I bit is set, IRQ is disabled
 .equ F_Bit,           0x40            @ when F bit is set, FIQ is disabled
 
-.equ UND_Stack_Size,  0x00000000
+.equ UND_Stack_Size,  0x00000200
 .equ SVC_Stack_Size,  0x00000100
 .equ ABT_Stack_Size,  0x00000000
 .equ FIQ_Stack_Size,  0x00000000
@@ -135,7 +135,15 @@ vector_undef:
     sub     sp, sp, #72
     stmia   sp, {r0 - r12}          @/* Calling r0-r12                  */
     add     r8, sp, #60
-    stmdb   r8, {sp, lr}            @/* Calling SP, LR                  */
+
+    mrs     r1, cpsr
+    mrs     r2, spsr
+    orr     r2,r2, #I_Bit|F_Bit
+    msr     cpsr_c, r2
+    mov     r0, r0
+    stmdb   r8, {sp, lr}           @/* Calling SP, LR                  */
+    msr     cpsr_c, r1             @/* return to Undefined Instruction mode  */
+
     str     lr, [r8, #0]            @/* Save calling PC                 */
     mrs     r6, spsr
     str     r6, [r8, #4]            @/* Save CPSR                       */
@@ -144,6 +152,12 @@ vector_undef:
 
     bl      rt_hw_trap_udef
 
+    ldmia    sp, {r0 - r12}         @/* Calling r0 - r2  */
+    mov      r0, r0
+    ldr      lr, [sp, #60]          @/* Get PC   */
+    add      sp, sp, #72
+    movs     pc, lr                 @/* return & move spsr_svc into cpsr */
+
     .align  5
 .globl vector_swi
 vector_swi:
@@ -169,6 +183,12 @@ vector_dabt:
 
     bl      rt_hw_trap_dabt
 
+    ldmia    sp, {r0 - r12}         @/* Calling r0 - r2  */
+    mov      r0, r0
+    ldr      lr, [sp, #60]          @/* Get PC   */
+    add      sp, sp, #72
+    movs     pc, lr                 @/* return & move spsr_svc into cpsr */
+
     .align 5
 .globl vector_resv
 vector_resv:

+ 18 - 0
libcpu/arm/am335x/trap.c

@@ -18,6 +18,10 @@
 #include "am33xx.h"
 #include "interrupt.h"
 
+#ifdef RT_USING_GDB
+#include "gdb_stub.h"
+#endif
+
 /**
  * @addtogroup AM33XX
  */
@@ -55,6 +59,13 @@ void rt_hw_show_register (struct rt_hw_register *regs)
  */
 void rt_hw_trap_udef(struct rt_hw_register *regs)
 {
+
+#ifdef RT_USING_GDB
+    regs->pc -= 4; //lr in undef is pc + 4
+    if (gdb_undef_hook(regs))
+        return;
+#endif
+
 	rt_hw_show_register(regs);
 
 	rt_kprintf("undefined instruction\n");
@@ -114,6 +125,13 @@ void rt_hw_trap_pabt(struct rt_hw_register *regs)
  */
 void rt_hw_trap_dabt(struct rt_hw_register *regs)
 {
+
+#ifdef RT_USING_GDB
+    if (gdb_mem_fault_handler) {
+        regs->pc = (unsigned long)gdb_mem_fault_handler; 
+        return;
+    }
+#endif
 	rt_hw_show_register(regs);
 
 	rt_kprintf("data abort\n");