大家好、我们在项目开发期间遇到了硬件断点触发问题。 请查看以下代码以设置和重置断点:
void enableBreakpoint (void)
{
extern unsigned int startBkpt;
memory_Mapped_debug_regs * regs = get_debug_regs ();
disable_interrupts_();
/*解锁 DBGLAR。 *
REGS->LOCKACCESS = 0xC5ACCE55;
/*启用监视器模式。 *
regs->DBGDSCR.bits.monitor_mode = 1;
/*禁用正在设置的断点。 *
regs->DBGBCR[5]。all = 0;
asm volatile (" DSB\n");
asm volatile (" dm\n");
asm volatile (" isb\n");
/* startFlush();*/
regs->DBGBVR[5]。all =((unsigned long)&startBkpt)& 0xFFFFFFFC;
regs->DBGBCR[5]。all = 7 |(0xF << 5);
asm volatile (" DSB\n");
asm volatile (" dm\n");
asm volatile (" isb\n");
/* startFlush();*/
asm volatile ("startBkpt:\n");
asm volatile (" nop\n");
_enable_interrupts_();
}
void disableBreakpoint (void)(空)
{
memory_Mapped_debug_regs * regs = get_debug_regs ();
disable_interrupts_();
/*禁用断点。 *
regs->DBGBCR[5]。all = 0;
/*清除 DBGBVR 寄存器。 *
regs->DBGBVR[5]。all = 0;
asm volatile (" DSB\n");
asm volatile (" dm\n");
asm volatile (" isb\n");
/* startFlush();*/
_enable_interrupts_();
}
memory_Mapped_debug_regs * get_debug_regs (空)
{
uint32T addr =_read_debug_DBGDRAR_()& 0xFFFFFFF0;
ADDR +=_READ_DEBUG_DBGDSR_()& 0xFFFFFFF0;
返回((memory_Mapped_debug_regs *) addr);
}
.def _read_debug_DBGDRAR_
asmfunc
_read_debug_DBGDRAR_
MRC P14、#0、r0、c1、c0、 0
BX LR
endasmfunc
.def _read_debug_DBGDSAR_
asmfunc
_read_debug_DBGDSAR_
MRC P14、#0、r0、c2、c0、 0
BX LR
endasmfunc
问题是即使设置了断点、也不会始终触发预取中止异常。 它看起来与可执行映像中的代码填充有关。 我发现了一些非常奇怪的解决方法、它暂时解决了这个问题、但我真的不明白它为什么起作用。
权变措施是为 enableBreakpoint 和 disableBreakpoint 创建单独的段、然后将它们与填充到32个字节对齐。 还必须创建附加函数:
extern void startFlush void;
空闪函数(空)
{
asm volatile (" nop\n");
asm volatile (" nop\n");
asm volatile (" nop\n");
asm volatile ("startFlush:\n");
asm volatile (" nop\n");
}
现在、必须在 enableBreakpoint 和 disableBreakpoint 函数中调用 startFlush (只具有在汇编中的 flushFunction 中创建的一条 nop 指令的函数)、就在 ISB 指令之后(在上面的代码中将其注释掉)。 真正奇怪的是 startFlush 函数必须与32个字节加上偏移量0xC 对齐。 这就是需要一个 FlushFunction 包装程序的原因(它被放置在单独的段中、并且还与32个字节的填充对齐。 flushFunction 中的前三个 nop 指令用于为 startFlush 创建0xC 偏移)。
未启用高速缓存。
也许有人遇到类似的问题并知道解决方法?