如何在IAR Embedded Workbench中充分利用各种类型的断点
随着嵌入式产品功能越来越丰富,嵌入式软件越来越复杂,开发人员花费在调试上的时间在整个软件开发周期中的比例越来越高。为了更有效地调试,开发人员需要掌握对应的调试工具。断点作为最基本的调试功能,开发人员在调试时都会使用到。
本文主要介绍如何在IAR Embedded Workbench中充分利用各种类型的断点来提高开发人员调试的效率。
断点的概念非常简单,因为它的作用是在指定指令之前中断程序的执行。实现方式可以是硬件或软件。然而,简单并不意味着它不能被用于复杂的调试组合中,以达到用简单的方式解决BUG的目的。事实上,很难想象如果没有断点,开发人员如何进行调试。但如何充分地利用各种类型的断点呢?
要更好地使用各种类型的断点,开发人员不能仅靠经验或者直觉,需要借助一些先进的开发工具来完成,它们可以帮助开发人员去了解不同断点的特点和价值。例如,在 IAR Embedded Workbench 工具中,开发人员可以充分利用以下不同类型的断点:
- 代码断点 (Code breakpoints)
- 条件代码断点 (Conditional code breakpoints)
- 数据断点 (Data breakpoints)
- 数据日志断点 (Data Log breakpoints)
- 日志断点 (Log breakpoints)
- 功率断点 (Power breakpoints)
- Trace开始和停止断点 (Trace Start and Stop breakpoints)
代码断点 (Code breakpoints)
代码断点是最简单的断点。开发人员只需要选择C 代码或者反汇编窗口中的汇编指令并设置断点即可。一旦断点被触发,程序就会暂停。此时,开发人员就可以检查变量、标志和寄存器的值。换句话说,开发人员现在拥有了完全控制权限。
代码断点的数量受限于MCU硬件断点的数量,如果代码在RAM中运行,开发人员可以利用软件断点,软件断点的数量则可以是无限的。即使数量有限,例如对于 Arm Cortex-M,有 6 到 8 个断点,但开发人员也可以保存断点位置并在需要时禁用和启用断点。只需要选择显示View ->Breakpoints window ,就可以选中/清除方框,也就是启用或禁用断点。
在这种情况下,可以有 6 到 8 个以上的断点,但不能同时都激活。
默认情况下,IDE 会设置代码断点。如果开发人员有一个 I-jet 仿真器,就可以在右键点击代码行时明确地选择一个 Flash 断点。如果开发人员已经用完了现有全部硬件断点,这招会很有用。注意断点符号中的“F”说明该断点是Flash断点。IAR Embedded Workbench for Arm 的 7.60 或更高版本中提供 Flash 断点功能。
条件代码断点 (Conditional Code breakpoints)
条件断点是代码断点与一些标志或变量(作为条件)的组合。设置好断点后,开发人员可以再次使用View ->Breakpoints window 来查看所有断点,也可以通过右键点击并选择Edit option来设置额外参数。
使用的语法类似于 C 语言的语法,包括 ==、>= 和 <=。例如,如果想让应用在计数器等于 10 的时候停止在断点,则可以使用“counter==10”。
当需要在一个中断例程内设置断点时,这非常有用。如果没有条件,调试就没有那么方便,因为程序每次在断点触发的时候都会停止。使用标志或变量作为条件可以简化操作。此外,还可以进一步使用跳过计数器和条件检查,如true或changed。
如果在调试RTOS相关的程序时,勾选对应的RTOS调试插件之后:
调试时,在Edit Breakpoint对话框中,会出现Task…选项,点击可以编辑Task specific的条件代码断点:可以设置只有某个具体的任务是active时才触发断点:
数据断点 (Data breakpoints)
相比其他断点,数据断点有些不同,因为它们监测对特定内存地址、标志、变量或寄存器的读写访问。数据断点使用非常直截了当,只需右键点击标志或变量,然后选择选项Set Data Breakpoint即可。默认情况下,读和写的访问将被监测。如果开发人员想增加额外的设置,可以通过View->Breakpoints window和Edit option来完成。除了访问之外,还可以监测数据是否匹配。这意味着只有当数据匹配时,写或读的访问才会触发停止。选择“Edit”按钮,可以打开一个额外的窗口,可以选择绝对地址甚至是源代码行。如果是一个变量或标志,建议使用自动大小。如果需要监测更大的范围,应手动设置所需的大小。
数据断点对于调试被应用破坏的标志和变量非常有用。一旦出现了读写访问,应用就会停止。另一种用法是堆栈溢出调查,只需要在堆栈大小的 80-90% 处设置一个数据断点,当溢出接近时,就可以停止应用,并一步步找到问题的根源。
数据日志断点 (Data Log Breakpoints)
除了可监测读写访问的数据断点外,开发人员还可以使用数据日志断点。使用这些断点的目的是监测并以图形方式绘制特定变量或内存地址的值跟随时间的变化,这就能更轻松地比较多个变量,观察中断触发的情况。
仿真器选项提供了Timeline、Data Log和Data LogSummary,如下图所示:
日志断点 (Log Breakpoints)
除了代码断点和数据断点之外,开发人员还可以使用日志断点。这是一个特殊的断点,因为它只会暂时停止应用来打印一条信息。只有当断点被触发时,它才会显示选定的信息。
每当断点被触发,一条信息就会显示在Debug Log窗口中。配合计数器,我们就可以知道应用源代码的特定部分运行了多少次。
功率断点 (Power breakpoints)
得益于 IAR Embedded Workbench 的功率调试技术,开发人员可以监控能耗并将其与源代码关联起来。可以帮助了解整个应用的能耗。这个概念也使得添加功率断点成为可能。可以设置一个阈值,比如 25mA,一旦能耗超过这个值,调试器就会暂停程序运行。
设置阈值的操作非常简单。只需要打开 I-jet -> PowerLog window,然后设置数值和对应的操作。
这个功能很有用,可以保证不出现任何耗电浪涌或高于指定值的情况,而且通过这种分析,电池的使用寿命也会延长,开发人员可以放心让其应用长时间运行。虽然时间轴窗口不是必须的,但它能提供实时的能耗信息。
Trace开始和停止断点 (Trace Start and Stop breakpoints)
最后要介绍的是Trace开始和停止断点。如果开发人员使用先进的仿真器,比如 I-jet Trace for Arm Cortex-M 或 I-jet Trace for Cortex-A/R/M,就可以利用这些断点。这在分析应用特定部分时特别有用。Trace开始和Trace停止断点简单易用,只需在代码行中右键点击并决定跟踪的开始和结束位置即可。Trace缓冲区将只保存应用中指定代码行之间的指令。
另外,开发人员也可以从Timeline上的Trace指令中得到函数调用的图形概览,这些函数调用信息是在Trace开始和停止断点之间捕获的。
虽然 I-jet Trace 仿真器比标准 JTAG/SWD 仿真器更强大,但有时如果记录包含所有正常信息时,Trace调试变得很麻烦。为了避免收集数以百万计的非必要指令,使Trace调试变得简单明了,IAR Embedded Workbench 提供了Trace开始和停止断点的功能。
总结
本文主要介绍了如何在IAR Embedded Workbench中充分利用各种类型的断点,开发人员可以根据不同的使用场景来设置对应的断点,从而提高调试效率。