背景:
我正在利用Atmel AVR atmega2560开发一个大型项目。该项目包含许多基于硬件的功能(7个SPI设备,2个I2C,2个RS485 MODBUS端口,大量模拟和数字I / O)。我为所有这些设备开发了“驱动程序”,为主应用程序循环提供了访问所需数据的接口。
问题:
我正在开发的项目最终必须符合SIL标准。
我希望能够测试代码并提供良好的代码覆盖率。但是,我无法找到任何信息来开始我应该如何设置这样的测试框架。
我的想法是,我可以拥有一套自动化测试,可以测试未来的错误修复和功能添加,以确定它们是否会破坏代码。问题是我不明白如何在芯片上测试代码。
我是否需要硬件来监控设备上的I / O并模拟外部连接的设备?任何可以提供的指针都将受到高度赞赏。
- 史蒂夫
答案 0 :(得分:12)
这是一个非常好的问题 - 嵌入式开发人员的共同关注点。不幸的是,大多数嵌入式开发人员并不像您那样关注并且仅在真实硬件上测试代码。但正如另一个答案所指出的,这基本上可以测试代码的名义功能,而不是角落/错误情况。
这个问题没有一个简单的解决方案。但是,有一些准则和技术可以做得相对较好。
首先,将代码分成几层。一层应该是“硬件不可知的” - 即函数调用。不要要求用户直接写入HW寄存器。另一个(下层)处理HW。可以“模拟”该层以测试更高级别。如果没有HW,则无法真正测试较低级别,但它不会经常更改并且需要深度HW集成,所以这不是问题。
“测试工具”将是您的所有高级HW不可知代码,具有专门用于测试的“假”低级别。这可以模拟硬件设备的正确和不正确的功能,从而允许您在PC上运行自动化测试。
答案 1 :(得分:3)
永远不要对真实硬件进行单元测试。始终模拟您的I / O接口。否则,您无法模拟错误条件,更重要的是,您无法依靠测试成功。
所以你需要的是将你的应用程序拆分成可以独立测试的各种部分。模拟器(或模拟)这些测试所需的所有硬件并在开发PC上运行它们。
这应该涵盖您的大多数代码,并留给您驱动程序。尝试在没有硬件的情况下尽可能多地使用驱动程序代码。对于其余部分,您必须想办法让代码在硬件上运行。这通常意味着您必须创建一个带有响应信号等的外部设备的测试台。由于这很脆弱(如“您的测试无法自动完成此工作”),您必须在准备硬件后手动运行这些测试。
答案 2 :(得分:1)
Vectorcast是一个商业工具,可以在具有代码覆盖率的硬件上运行单元测试。
答案 3 :(得分:0)
你有JTAG连接器吗?您可以使用JTAG来模拟芯片上的错误情况。
答案 4 :(得分:0)
我喜欢分开任务。例如,当我为Atmel AVR创建一个循环缓冲区时,我在Code :: Blocks中编写了所有内容,并使用常规GCC编译器而不是AVR GCC编译器编译它,然后我为它创建了一个单元测试。我使用了一个特殊的头文件来提供我想要使用的正确数据类型(例如uint8_t)。我发现了单元测试的错误,修复了它们,然后将固定的代码转移到AVR Studio并集成它。之后,我使用写入支持函数和ISR使缓冲区适合有用的代码(即,从缓冲区弹出一个字节,将其推入UART数据输出寄存器,将字符串常量附加到缓冲区以获取printf函数等)。然后我使用AVR模拟器确保调用我的ISR和函数,并且正确的数据显示在寄存器中。之后我将它编程到芯片上并且工作得很好。
与AVR Studio相比,我更喜欢Code :: Blocks的调试功能,所以我尽可能使用上述方法。当我不能,我通常只处理硬件。例如,我有一个自动产生方波的计时器。我能做的最好的事情就是看到模拟器中的针位被弄乱了。在那之后,我只需要勾起一个范围并确保。
我喜欢在调试问题时使用多级方法。例如,对于时钟,第一层是“将探针放在时钟引脚上,看看那里是否有信号”。如果没有,探测uC上的引脚并寻找信号。然后,我在我的一个UART中编写了一个调试接口,在那里我可以查看特定的寄存器值,并确保它们是它们应该是的。因此,如果它不起作用,下一步是“调用寄存器值并确保它是正确的。”
每当您计划调试时,请尝试提前四步。这里应该有+ 5V,但如果没有呢?写入调试接口是一种切换引脚的方法,看看是否会改变它。如果那不起作用怎么办?做其他事情等等。你遇到了一个问题,你会遇到'我没有想法为什么这个不行!!!!'但希望你事先能弄清楚原因。