【问题标题】:Testing Code for Embedded Application嵌入式应用程序测试代码
【发布时间】:2010-12-07 01:17:53
【问题描述】:

背景:

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

问题:

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

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

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

我是否需要硬件来监控设备上的 I/O 并模拟外部连接的设备?任何可以提供的指针将不胜感激。

--史蒂夫

【问题讨论】:

    标签: c testing embedded atmega


    【解决方案1】:

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

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

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

    【讨论】:

    • SRoe,我也强烈建议你抽象出更高层的逻辑、算法、功能等。努力将真正的硬件或设备特定的代码隔离到少数模块中。这将使遵循 Aaron 的建议更容易。它还将提高硬件独立位的可测试性。
    • 在主机上运行后,应该在真实的目标硬件上运行单元测试,但要模拟对外部硬件的访问。这可以捕获目标平台上的编译器和硬件错误。它甚至可能需要更高的 SIL 级别。
    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

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

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

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

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

      【讨论】:

        【解决方案4】:

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

        【讨论】:

          【解决方案5】:

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

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

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

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

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2018-07-27
            • 2022-08-26
            • 1970-01-01
            • 2011-12-13
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多