15

背景:

我正在使用 Atmel AVR atmega2560 开发一个大型项目。该项目包含大量基于硬件的功能(7 个 SPI 设备、2 个 I2C、2 个 RS485 MODBUS 端口、大量模拟和数字 I/O)。我为所有这些设备开发了“驱动程序”,它们为主应用程序循环提供了一个访问所需数据的接口。

问题:

我正在开发的项目最终必须满足 SIL 标准。

我希望能够测试代码并提供良好的代码覆盖率。但是,我找不到任何信息让我开始了解如何设置这样的测试框架。

我的想法是我可以拥有一套自动化测试,这将允许对未来的错误修复和功能添加进行测试,以查看它们是否会破坏代码。问题是我不明白如何在芯片上测试代码。

我是否需要硬件来监控设备上的 I/O 并模拟外部连接的设备?任何可以提供的指针都将受到高度赞赏。

——史蒂夫

4

5 回答 5

12

这是一个非常好的问题——嵌入式开发人员普遍关心的问题。不幸的是,大多数嵌入式开发人员并不像您那样关心,只在真实硬件上测试代码。但正如另一个答案指出的那样,这基本上可以测试代码的标称功能,而不是角落/错误情况。

这个问题没有单一而简单的解决方案。但是,存在一些指导方针和技术,可以做得相对较好。

首先,将您的代码分层。一层应该是“与硬件无关的”——即函数调用。不要要求用户直接写入硬件寄存器。另一个(较低的)层处理硬件。可以“模拟”该层以测试更高级别。没有硬件就无法真正测试较低级别,但它不会经常更改并且需要深度硬件集成,所以这不是问题。

“测试工具”将是您所有与硬件无关的高级代码,其中包含专门用于测试的“假”较低级别。这可以模拟硬件设备的正确和错误功能,从而允许您在 PC 上运行自动化测试。

于 2009-10-16T15:29:00.923 回答
3

永远不要在真实硬件上或针对真实硬件运行单元测试。总是模拟你的 I/O 接口。否则,您将无法模拟错误条件,更重要的是,您无法依靠测试来成功。

因此,您需要将您的应用程序拆分为可以独立测试的各个部分。模拟器(或模拟)这些测试所需的所有硬件,并在开发 PC 上运行它们。

这应该涵盖您的大部分代码,并为您留下驱动程序。尝试使尽可能多的驱动程序代码在没有硬件的情况下工作。剩下的,你必须想办法让代码在硬件上运行。这通常意味着您必须创建一个带有响应信号等的外部设备的测试台。由于这很脆弱(如“您的测试无法使其自动工作”),您必须在准备好硬件后手动运行这些测试。

于 2009-10-15T14:15:10.513 回答
1

Vectorcast是一种商业工具,用于在具有代码覆盖率的硬件上运行单元测试。

于 2009-10-15T14:47:06.363 回答
0

有 JTAG 连接器吗?您可以使用 JTAG 来模拟芯片上的错误情况。

于 2009-10-16T15:37:09.493 回答
0

我喜欢把任务分开。例如,当我为我的 Atmel AVR 制作一个循环缓冲区时,我将其全部写入 Code::Blocks 并使用常规 GCC 编译器而不是 AVR GCC 编译器对其进行编译,然后为它创建一个单元测试。我使用了一个特殊的头文件来提供我想要使用的正确数据类型(例如 uint8_t)。我在单元测试中发现了错误,修复了它们,然后将修复的代码转移到 AVR Studio 并集成它。之后,我使用编写的支持函数和 ISR 将缓冲区放入有用的代码中(即,从缓冲区弹出一个字节,将其推入 UART 数据输出寄存器,将字符串常量附加到缓冲区以用于 printf 函数等)。然后我使用 AVR 模拟器来确保我的 ISR 和函数被调用,并且正确的数据显示在寄存器中。

与 AVR Studio 相比,我更喜欢 Code::Blocks 的调试功能,所以我尽可能使用上述方法。当我不能时,我通常只处理硬件。例如,我有一个自动产生方波的计时器。我能做的最好的就是看到针头在模拟器中被旋转。在那之后,我只需要连接一个范围并确保。

我喜欢在调试问题时使用多层次的方法。例如,对于时钟,第一层是“在时钟引脚上放置一个探针,看看那里是否有信号”。如果没有,请探测 uC 上的引脚并寻找信号。然后,我在我的一个 UART 中编写了一个调试接口,我可以在其中查看特定的寄存器值并确保它们是它们应该是的。因此,如果它不起作用,下一步就是“调用寄存器值并确保它是正确的”。

每当您计划调试时,请尝试提前四个步骤左右。这里应该有+5V,但如果没有怎么办?在调试界面中写入一种切换引脚的方法,看看是否会改变它。如果这不起作用怎么办?做其他事情,等等等等。你会遇到“我不知道为什么这该死的东西不起作用!!!!” 但希望你能事先弄清楚原因。

于 2009-10-19T19:27:21.310 回答