我有一个为ATmega16芯片编写的C代码,它充满了以下关键字:
flash, eeprom, bit
和宏(?)喜欢
interrupt [TIM1_OVF] void timer1_ovf_isr(void)
来自功能签名。
现在我要做的是编写和运行单元测试,验证控制器单元逻辑的正确性,我希望能够在任何计算机上运行这些测试而不需要具有“设备”代码代表。
我搜索了很多并且遇到了“抽象硬件”和“用存根替换它们”的解决方案,但我不确定如何抽象出像“中断[TIM1_OVF] 之类的东西“在代码中!
我想知道是否有任何特殊工具可以提供运行这些代码的环境?
而且,如果我做错了,有人能指出我正确的方向吗?给改变或重写(!)微控制器的代码可能不是一个选项?
非常感谢。
答案 0 :(得分:2)
您的示例不是ISO C代码,它们是特定于编译器的扩展,它们在AVR编译器中并不常见,更不用说架构了。在许多情况下,可以通过定义需要很少或不需要修改代码的宏来解决它们。为了使您的代码在任何情况下都可以移植,甚至在不同供应商的AVR编译器中,在任何情况下都可以这样做,尽管可能需要组合技术。
大多数编译器支持"始终包括"允许从命令行中包含头文件的选项,源中包含显式#include
指令。使用兼容性宏创建标头,并在代码中隐式描述或显式包含它是一种有用的技术。例如,对于您提到的问题,您可能有:
// compatability.h
#if !defined COMPATABILITY_INCLUDE
#define COMPATABILITY_INCLUDE
#if defined __IAR_SYSTEMS_ICC__
#define INTERRUPT( irq, handler ) __interrupt [irq] void handler(void)
#elif defined _WIN32
#define INTERRUPT( irq, handler ) void handler(void)
#define __flash const
#define __eeprom const
#define __bit char
#else
#error Unknown toolchain/environment
#endif
#endif
这将从Win32代码中删除内存位置限定符,并将__bit
定义为char。中断处理程序宏将在Win32上将处理程序转换为常规函数,但确实需要修改代码,但由于每个工具链都以不同方式执行,因此这可能不是坏事。
例如,在这种情况下,您将更改:
interrupt [TIM1_OVF] void timer1_ovf_isr(void)
{
...
}
到
INTERRUPT( TIM_OVF, timer1_ovf_isr )
{
...
}
请注意,您应该在兼容性文件中使用approapriate目标宏 - 例如,我已经在IAR中猜到了;您可能正在使用不同的编译器。您的编译器文档应指定可用的预定义宏,或者Pre-defined Compiler Macros" project"在Sourceforge上是一个有用的资源。
某些转换可能会在语义上更改代码,例如在某些情况下为__bit
交换char
,例如,如果为该位指定的值大于1,然后与1进行比较,则嵌入式目标可能会产生真实,而在PC构建它不会。最好将其转换为_Bool
,但您的编译器可能会发出有关隐式转换的警告。我的建议可能不一定是最好的转换 - 请参阅编译器的手册以了解精确的语义,并决定如何最好地将它们转换为标准C以进行测试构建。
保留专有语义的替代方法是使用调试器脚本在指令集模拟器中运行单元测试(如果可用于实现硬件交互的存根),但是该方法使得无法使用现成的单元测试框架比如CUnit。
答案 1 :(得分:1)
根据您的工具链,您可能已经安装了AVR模拟器,这样您就可以在任何PC上运行单元测试。例如,IAR提供“C-SPY”,一个支持终端窗口的AVR模拟器,可以显示show register值,可以支持中断生成等。假设您保持单位大小合理,您不需要重要的基础设施或存根接口使这项工作。
在目标平台(使用目标编译器)上运行单元测试的一大好处是,您可以解释由平台引起的任何特定行为(字节序,字大小,编译器或库特性等),与在PC环境中运行相比。