mirror of
https://github.com/RT-Thread/rt-thread.git
synced 2026-10-20 18:53:15 +08:00
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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" />
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
//}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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')
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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__ */
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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__ */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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__ */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
@@ -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
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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,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");
|
||||
|
||||
Reference in New Issue
Block a user