在模拟中对函数进行桩设定

6

我正在开发一个嵌入式C项目,它依赖于一些外部硬件。我希望暂时屏蔽访问这些部分的代码,以便在不使用任何硬件的情况下模拟系统。到目前为止,我已经使用了一些宏,但这迫使我对生产代码进行了一些修改,我想避免这种情况。

示例:

stub.h
#ifdef _STUB_HW
#define STUB_HW(name) Stub_##name
#else /*_STUB_HW*/
#define STUB_HW(name) name
#endif /*_STUB_HW*/

my_hw.c
WORD STUB_HW(clear_RX_TX)()
{ /* clear my rx/tx buffer on target HW */ }

test_my_hw.c
#ifdef _STUB_HW
WORD clear_RX_TX()
{ /* simulate clear rx/tx buffer on target HW */ }

使用这段代码,我可以通过预处理器标签_STUB_HW打开/关闭存根。

有没有一种方法可以在不改变生产代码的情况下完成此操作,并避免大量的ifdef。如果可以避免,在同一个文件中不会混合生产和测试代码。只要我能尽可能地将其保留在生产代码之外,我就不在乎测试代码的外观。

编辑:

如果可以选择/重命名函数而不替换整个文件,那就太好了。比如以nRF_##开头的所有函数都被赋予新名称,然后将test_nRF_##插入到nRF_##中。
3个回答

9

我只是创建了两个文件ActualDriver.c和StubDriver.c,它们包含完全相同的函数名称。通过对不同对象链接生产代码进行两次构建,就不会出现命名冲突。这样,生产代码中就不包含任何测试或条件代码。


实际上是一个很好的工作选项。不确定它是否是最适合我的最佳解决方案。请参见编辑。 - eaanon01
只要没有其他更好的解决方案被发现,就接受至少这么长的时间。 :) - eaanon01

1
如Gerhard所说,使用一个常见的头文件“driver.h”和单独的硬件层实现文件,其中包含实际和存根函数。
在eclipse中,我有两个目标,并且我“从构建中排除”不需要使用的driver.c文件,并确保适当的文件被包含在构建中。然后Eclipse在构建时生成makefile。
另一个要指出的问题是确保您定义了固定大小的整数,以便您的代码在溢出方面表现相同。(尽管从您的代码示例中我可以看到您正在这样做。)

1

我同意以上观点。这个标准解决方案是定义一个不透明的抽象函数集合,它们是"驱动程序"到硬件的接口,并在主程序中调用该接口。然后提供两种不同的驱动程序实现,一种用于硬件,另一种用于软件。软件变体将以某种适当的方式模拟硬件的IO效果。

请注意,如果目标是在较低级别上编写代码,即需要模拟每个硬件访问而不是整个函数,可能会有些棘手。但在这里,可以定义不同的“write_to_memory”和“read_from_memory”函数(或宏,如果对目标速度至关重要)。

无论哪种情况,都不需要更改函数名称,只需使用两个不同的批处理文件、make文件或IDE构建目标(取决于您使用的工具)。

最后,在许多情况下,更好的技术解决方案是选择一个完整的目标系统模拟器,例如QemuSimicsSystemCCoWareVaST或类似的工具。这样可以让您始终运行相同的代码,并构建一个硬件模型,该模型从软件的角度看起来像实际的硬件。虽然需要更大的前期投资,但对于许多项目来说,这是值得努力的。它基本上消除了在目标和主机上使用不同版本的构建的问题,并确保您始终使用带有部署构建选项的交叉编译器。请注意,许多嵌入式编译器套件都内置了一些基本的模拟功能。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接