(rt-thread gdb)cm系列的GDB移植
2014-08-06 15:07
633 查看
cm版本已经更新,关于项目的更多说明
见https://code.csdn.net/wzyy2/gdbstub4rtt/tree/master/readme-zh.txt
移植主要分三个主要的实现和debug模式
ps : CM0的断点设置有所不同,不能运行
关于debugmon和halt的区别,见以下图
简单的说debugmon可以按照一般的异常处理,而halt是直接停机内核
关于debugmon和halt debug的办法,见以下两张图
使用 debug monitor的办法就是置位DEMCR寄存器的MON_EN
软件唤起debug monitor的办法是置位DEMCR寄存器的MON_PENDING
寄存器说明见Cortex-M3 Technical Reference Manual 10.2.4 Debug Exception and Monitor Control Register
.A set of address matching tags, that reroute accesses into flash to a special part of SRAM. This permits patching flash locations for breakpointing and quick fixes orchanges.
FPB可以被编程用来实现断点功能,他有一个比较器,当地址,有两个选择,一是将该地址指向指定的ram地址,二是在该地址设置BKPT指令,因为我们要用的是断点功能,自然是设置断点了
FPB的使用有两个使能位,一个是总开关
设置断点的办法如上,把要设置地址的28-2位写入FPB_COMP的28-2位,要在高半字设置断点需要置位BIT31,低半字则置位BIT30
更多功能及寄存器说明见Cortex-M3 Technical Reference Manual 11.4 FPB
待更
更多功能及寄存器说明见Cortex-M3 Technical Reference Manual 11.5 DWT
.When MON_EN= 1, this steps the core. When MON_EN= 0, this bitis ignored. This is the equivalent to C_STEP. Interrupts are only stepped according to the priority of the monitor and settings of PRIMASK, FAULTMASK, or BASEPRI
这里有很重要的一点就是我们要通过basepri来屏蔽中断
之所以要屏蔽中断是因为设置单步的目的的是为了到达当前函数的下一行
而不是在中断里单步
如果不屏蔽的话,调试模式返回后会先去执行中断
然后我们就要淹没在无止境的systick里出不来了
还有一个地方就是GDB_CORTEXM_PRIORITY_MAX
如果优先级分组有更改要更改这个宏
我们设置basepri的目的是屏蔽低优先级的中断,同时不屏蔽debugmon
debugmon的默认优先级是0,所以至少要保证GDB_CORTEXM_PRIORITY_MAX的抢占优先级要大于0
不然可能出现单步之后无法进入调试模式的情况
寄存器说明见Cortex-M3 Technical Reference Manual 10.2.4 Debug Exception and Monitor Control Register
见https://code.csdn.net/wzyy2/gdbstub4rtt/tree/master/readme-zh.txt
移植主要分三个主要的实现和debug模式
ps : CM0的断点设置有所不同,不能运行
Debug Monitor(调试监控器)
CM系列可以脱离JTAG调试的主要基础就是debugmon模式关于debugmon和halt的区别,见以下图
简单的说debugmon可以按照一般的异常处理,而halt是直接停机内核
关于debugmon和halt debug的办法,见以下两张图
使用 debug monitor的办法就是置位DEMCR寄存器的MON_EN
软件唤起debug monitor的办法是置位DEMCR寄存器的MON_PENDING
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; //Fall into debug monitor *base |= GDB_DEBUG_REG_DEMCR_MON_PEND;
寄存器说明见Cortex-M3 Technical Reference Manual 10.2.4 Debug Exception and Monitor Control Register
1.断点(breakpoint)
CM断点的主要实现是使用Flashpatch and Breakpoint(FPB):.A set of address matching tags, that reroute accesses into flash to a special part of SRAM. This permits patching flash locations for breakpointing and quick fixes orchanges.
FPB可以被编程用来实现断点功能,他有一个比较器,当地址,有两个选择,一是将该地址指向指定的ram地址,二是在该地址设置BKPT指令,因为我们要用的是断点功能,自然是设置断点了
FPB的使用有两个使能位,一个是总开关
// 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_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 ;
设置断点的办法如上,把要设置地址的28-2位写入FPB_COMP的28-2位,要在高半字设置断点需要置位BIT31,低半字则置位BIT30
更多功能及寄存器说明见Cortex-M3 Technical Reference Manual 11.4 FPB
2.观察点(watchpoint)
CM观察点的主要实现是使用Data Watchpoint and Trace(DWT)待更
/** * 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; }
// 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; } }
更多功能及寄存器说明见Cortex-M3 Technical Reference Manual 11.5 DWT
3.单步(singlestep)
单步主要实现是DEMCR寄存器的MON_STEP位.When MON_EN= 1, this steps the core. When MON_EN= 0, this bitis ignored. This is the equivalent to C_STEP. Interrupts are only stepped according to the priority of the monitor and settings of PRIMASK, FAULTMASK, or BASEPRI
/*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;
这里有很重要的一点就是我们要通过basepri来屏蔽中断
之所以要屏蔽中断是因为设置单步的目的的是为了到达当前函数的下一行
而不是在中断里单步
如果不屏蔽的话,调试模式返回后会先去执行中断
然后我们就要淹没在无止境的systick里出不来了
还有一个地方就是GDB_CORTEXM_PRIORITY_MAX
#ifndef GDB_CORTEXM_PRIORITY_MAX #define GDB_CORT 4000 EXM_PRIORITY_MAX (1 << 6) #endif
如果优先级分组有更改要更改这个宏
我们设置basepri的目的是屏蔽低优先级的中断,同时不屏蔽debugmon
debugmon的默认优先级是0,所以至少要保证GDB_CORTEXM_PRIORITY_MAX的抢占优先级要大于0
不然可能出现单步之后无法进入调试模式的情况
寄存器说明见Cortex-M3 Technical Reference Manual 10.2.4 Debug Exception and Monitor Control Register
相关文章推荐
- 移植完RT-Thread之后,串口输出rtc not configured,please configure with set_date and set_time
- RT-thread移植(基于STM32F4xx)
- rt-thread移植STM32F103C8
- RT-Thread移植到STM32F103ZET6具体操作步骤(利用keil5新建工程,添加RT-Thread源码到工程)
- RT-Thread 学习笔记(十三)--- 开启基于RTGUI的LCD显示功能(3)<触屏屏驱动移植和测试>
- 移植 RT-Thread 到MB9BF218S
- RT-Thread_1.2.0+lwip+rtgui0.8.0 移植心得
- 移植FreeModbus+ModbusMaster+STM32至RT-Thread(3、4阶段)
- stm32 移植rt_thread
- (rt-thread gdb)异常向量的设置以及ARM下单步调试的实现
- 移植rt-thread到esp8266笔记
- RT Thread 在STM32f10x 平台上的移植
- RT-Thread在S3C2410下的移植(1)
- RT-thread-2.0.1移植(基于STM32F4xx)
- rt-thread针对rx62N的移植
- 移植FreeModbus+ModbusMaster(主机)+STM32至RT-Thread(初步)
- STM32移植RT-Thread后的串口在调试助手上出现:(mq != RT_NULL) assert failed at rt_mq_recv:2085和不能接收数据问题讨论
- rt-thread 内核移植
- 在龙芯1C上移植硬浮点FPU到RT-Thread
- 移植FreeModbus+ModbusMaster(主机)+STM32至RT-Thread(1、2阶段)