Embedded 如何在嵌入式系统上实现代码覆盖

Embedded 如何在嵌入式系统上实现代码覆盖,embedded,code-coverage,gcov,Embedded,Code Coverage,Gcov,我为非POSIX嵌入式系统编写了一个项目,所以我不能使用gcc选项——coverage(我没有读写)。我还可以做些什么来产生类似gcov的输出。我确实有一个输出功能。它可以由一个带有嵌入式跟踪的处理器、一个公开跟踪端口的电路板设计以及一个合适的硬件调试器和相关软件轻松完成。例如,许多基于Cortex-M的设备包括ARM的嵌入式跟踪宏单元(ETM),这由Keil的uVision IDE和ULINK Pro调试器支持,以提供代码覆盖率、指令/源代码级跟踪以及实时评测。硬件跟踪的优点是它是非侵入性的—

我为非POSIX嵌入式系统编写了一个项目,所以我不能使用gcc选项——coverage(我没有读写)。我还可以做些什么来产生类似gcov的输出。我确实有一个输出功能。

它可以由一个带有嵌入式跟踪的处理器、一个公开跟踪端口的电路板设计以及一个合适的硬件调试器和相关软件轻松完成。例如,许多基于Cortex-M的设备包括ARM的嵌入式跟踪宏单元(ETM),这由Keil的uVision IDE和ULINK Pro调试器支持,以提供代码覆盖率、指令/源代码级跟踪以及实时评测。硬件跟踪的优点是它是非侵入性的——代码是实时运行的

如果您没有硬件支持,您可能不得不求助于模拟。许多工具链包括一个指令级模拟器,它将执行跟踪、代码覆盖和分析,但您可能必须创建调试脚本或代码存根来模拟硬件以强制执行所有路径

第三种选择是在桌面平台上构建代码,使用存根替换目标硬件依赖项,并在上面执行测试和代码覆盖。您必须相信目标C编译器和测试系统编译器都使用相同的语义翻译源代码。这里的优点是,可用的调试工具通常优于嵌入式系统可用的调试工具。您还可以在任何硬件可用之前测试大部分代码,并且在大多数情况下执行代码的速度要快得多,可能允许进行更广泛的测试

没有POSIXAPI并不妨碍使用GCC,它只是妨碍使用GNUC库。在没有POSIX的嵌入式系统上,可以使用替代的C库,如Newlib。Newlib有一个系统移植层,在该层中实现I/O和基本堆管理。

我们的工具包含源代码,生成一个使用嵌入式编译器编译的程序,该程序将测试覆盖率数据收集到添加到程序中的“小”数据结构中。这适用于各种方言,包括ANSI、GCC、Microsoft和GreenHills

您必须将该数据结构从嵌入式执行上下文导出到PC上的文件中;这通常很容易通过一个备用串行或并行端口以及一小段特定于您的端口的自定义代码来实现。这些工具将提供测试覆盖率视图和结果文件的摘要

因此,在大多数实际情况下,您可以使用这些工具从嵌入式系统收集测试覆盖率数据。

免责声明:我工作的公司(Rapita Systems)提供了针对嵌入式应用程序的代码覆盖率解决方案

因为嵌入式系统带来了它们自己的、特殊的和广泛变化的需求,所以代码覆盖率的“最佳”解决方案也有很大差异

  • 如果您有基于跟踪的设备,比如带有ETM的ARM芯片或支持NEXUS的部件,您可以通过调试器执行覆盖,而无需仪器
  • 否则,您很可能会面临基于检测的解决方案:
    • 对于RAM有限的解决方案,一个好的解决方案是将检测写入I/O端口
    • 或者,您可以将插装记录到RAM缓冲区,并使用多种方法从目标中提取插装

当然,还有很多不同风格的代码覆盖:函数、语句、决策/分支、MC/DC

如果您的嵌入式目标由基于GCC的跨工具链支持,您可能会发现我的方法很有用

主要思想是使用适当的
gcov
选项编译代码,然后在内存中创建覆盖率信息(最终存储在
.gcda
文件中)。然后,您可以在GDB中放置适当的断点,并通过调试链接(串行、JTAG等)转储此信息


看一看我的博文——我非常详细地描述了事情。

代码覆盖在嵌入式系统上不太常见。但一个好的答案需要更多关于系统的细节。什么CPU?什么操作系统?什么编译器工具链?你只需要写函数还是读写函数?如果只是写(打开、关闭、写入),您可以创建自己的,也可以将写输出转到串行端口,以便在其他位置存储/记录。是否可以在可以使用覆盖率选项的系统上编译和运行测试?