嵌入式系统中的硬件断点与软件断点

Hardware breakpoints vs Software breakpoints in embedded systems

我的理解是,插入软件断点涉及用软件中断指令替换要执行的代码中的下一条指令,这将导致 CPU 在到达该指令时停止。

硬件断点涉及将要执行的断点之后的下一条指令的地址放入寄存器中,当地址匹配时,通过使用硬件比较器,这会导致 CPU 停止(如果我错了请纠正我)。

我感到困惑的是,例如,在使用硬件调试器通过 JTAG 调试电路板时,我们是否只使用硬件断点?或者 JTAG 也可以使用软件断点吗?

GDB是只能和软件断点一起使用,还是可以和JTAG一起使用?对不起,如果问题有点宽泛。

"correct me if I'm wrong"

设置断点指令上,而不是在它之后 - 中断发生在指令执行之前,而不是在指令执行之后 - 否则在跳转、调用或分支指令上设置断点将失败。

"do we only use hardware breakpoints when using a hardware debugger to debug a board via JTAG for example?"

JTAG 是片上调试的简单通信接口(并用于其他目的,例如在线存储器和 FPGA 编程和边界扫描)。

虽然它可能因 ARM Cortex-M 上的体系结构而异,但您可以从目标代码访问片上调试寄存器并设置硬件断点。 Yoiu 还可以使用 BKPT 指令(与您建议的 SWI 相反)在您的代码中放置软件断点。

Or can JTAG use software breakpoints also?

正如我所说,JTAG只是片上调试的一个通信接口,但是通过片上调试,你可以直接设置任何RAM的内容,所以JTAG connected debugger software 运行ning在开发主机上可以临时修改RAM中的代码来设置软件断点(通过将目标指令替换为BKPT,然后当断点是hit, 恢复到原始指令以便可以执行。软件断点对于来自 ROM 的代码 运行ning 并不是那么简单,尽管一些调试器支持无限的 ROM 断点(需要付出代价)- 此类硬件的制造商会这样做不一定公开他们使用的方法。

在 JTAG 和片上调试在甚至低端部件上广泛可用之前,使用了在线仿真和 ROM 仿真器等技术。这些通常是昂贵且复杂的解决方案。

Is GDB only used with software breakpoints, or can it be used also in conjunction with JTAG?

GDB 有多种使用方式。它需要一个 "debug stub" - 一个将调试器软件映射到可用硬件的软件层 - 其性质将取决于所使用的调试接口和目标设备。例如,当使用 UART 或以太网端口时,存根实际上是目标本身的代码 运行ning(例如 Linux 的 gdbserver)。在那种情况下,它不太可靠,因为软件错误可能会阻止调试端口驱动程序实际 运行ning,尤其是在缺乏 MMU 保护的目标中。更简单的 JTAG 设备通过开发主机上的存根 运行ning 与 GDB 接口,例如常用的 OpenOCD 软件。更昂贵的 JTAG 调试硬件可能 运行 JTAG 硬件本身的存根——例如 Abatron 的 bdi2000。无论哪种方式,调试存根都将能够根据目标功能使用硬件和软件断点。

断点定义

在本文的上下文中,让我们就断点的统一定义达成一致。这里讨论的断点是我们希望处理器停止的程序位置,以便我们可以进行某种调试。可能还有其他类型的断点,例如由数据访问触发的断点,但在本文中,我们将仅讨论程序断点,即应用程序代码中每次遇到该代码时我们希望停止的位置。

硬件与软件断点

硬件断点和软件断点有什么区别?嗯,显而易见的答案是 "A hardware breakpoint is implemented in hardware" 和 "A software breakpoint is implemented in software"。但这到底是什么意思,它的后果是什么?为什么我会选择一个而不是另一个?

硬件断点

硬件断点实际上是由集成到设备中的特殊逻辑实现的。您可以将硬件断点视为一组连接到程序地址总线的可编程比较器。这些比较器使用特定的地址值进行编程。当代码正在执行时,程序地址总线上地址中的所有位都与编程到比较器中的位匹配,硬件断点逻辑会向 CPU 生成一个信号以停止。 使用硬件断点的优点是它可以在任何类型的内存中使用。在讨论了软件断点之后,这可能更有意义。当我们讨论软件断点时,我们会发现它们只能在 Volatile 内存中使用。无论执行的代码是在 RAM 还是 ROM 中,都可以使用硬件断点,因为对于硬件断点逻辑来说,没有区别。它只是匹配 PAB 上的地址并在找到地址时停止 CPU。 HWBP 的缺点是,因为它们是在硬件中实现的,所以可用的数量有限。可用的 HWBP 数量因架构而异,但在大多数情况下只有 2-8 个可用。找出有多少设备的最简单方法是在 CCS 中连接到它并继续设置 HWBP,直到您收到一条错误消息,指出有 none 可用。

软件断点

如前所述,软件断点是在软件中实现的。但那是怎么做到的呢?实际上有两种不同的实现。 一些设备在它们的操作码定义中保留一个指定的位来指示软件断点。例如,在 C6000 系列的一种架构中,所有指令都是 32 位长,并且保留第 28 位以指示软件断点,因此该指令集中的所有指令都将第 28 位设为零。在这种情况下,当在 CCS 中设置软件断点时,它实际上会修改该位置指令的操作码并将第 28 位设置为 1。仿真逻辑随后会在第 28 位为 1 时监视程序操作码,并且发生这种情况时停止 CPU 。请注意,这是少数情况。大多数架构不会这样做。原因是它限制了指令集的灵活性。此外,它不适用于具有可变长度指令的体系结构,因此它也限制了代码密度。 更流行的实现软件断点的方法也复杂得多。在这种情况下,有一个指定的断点操作码。通常,操作码是 8 位。每当设置断点时,该位置指令的前 8 位将被删除并替换为该 8 位断点操作码。然后将指令的原始 8 位存储在断点 table 中。每当遇到断点时,CPU 就会停止,CCS 会用指令的原始 8 位替换断点操作码。当重新开始执行时,CCS 必须做一些小动作,因为实际 CPU 流水线中的指令不正确。它仍然有断点操作码。因此 CCS 刷新 CPU 管道,然后将其中挂起的指令重新获取到它们的原始状态,下一个要执行的函数是设置断点的函数。同时,CCS 用断点操作码重新加载该位置的指令,以便下次遇到此代码时,它会再次停止。 SWBP 的优点是它们的数量不受限制,因此您可以将它们放在任意多的地方。缺点是不能像ROM/FLASH一样把它们放在非易失性内存中,因为CCS不能把操作码写到这个位置。

http://processors.wiki.ti.com/index.php/How_Do_Breakpoints_Work