有没有办法在普通计算机上为嵌入式微控制器设计 运行 C 代码?
is there a way to run C code designed for an embedded micro-controller on a normal computer?
我有一个为 ATmega16 芯片编写的 C 代码,它充满了关键字,例如:
flash, eeprom, bit
和宏 (?) 如
interrupt [TIM1_OVF] void timer1_ovf_isr(void)
在函数签名之前。
现在我想做的是编写 运行 单元测试来验证控制器单元逻辑的正确性,我希望能够 运行 在任何计算机上进行这些测试,并且不需要代码表示的 "device"。
我搜索了很多并遇到了 "abstracting the hardware" 和 "replacing them with stubs" 种解决方案,但我不确定如何抽象出类似“中断 [TIM1_OVF]”在代码中!
我想知道是否有任何特殊工具可以为 运行 编写此类代码提供环境?
而且,如果我做错了,有人能指出我正确的方向吗?考虑到更改或重写 (!) 微控制器的代码可能不是一种选择?
非常感谢。
根据您的工具链,您可能已经有了可用的 AVR 模拟器,这将允许您在任何 PC 上 运行 进行单元测试。例如,IAR 提供 "C-SPY",一个支持终端 window 的 AVR 模拟器,可以显示显示寄存器值,可以支持中断生成等。假设您保持合理的单元大小,则不需要使这项工作有效的重要基础设施或存根接口。
运行在目标平台(使用目标编译器)上进行单元测试的一大好处是,您可以考虑由平台(字节序、字长、编译器)引起的任何特定行为或库特性等),与 运行 PC 环境中的 ning 相比。
您的示例不是 ISO C 代码,它们是特定于编译器的扩展,它们在 AVR 编译器中并不常见,更不用说架构了。在许多情况下,它们可以通过定义需要很少或不需要修改代码的宏来解决。为了使您的代码在任何情况下都可移植,甚至跨不同供应商的 AVR 编译器,在任何情况下都这样做是个好主意,尽管可能需要结合使用多种技术。
大多数编译器支持 "always include" 选项,允许从命令行包含 header 文件,并在源代码中使用显式 #include
指令。使用您的兼容性宏创建 header 并将其包含在代码中,如所描述的那样隐式地或显式地包含在代码中是一种有用的技术。例如对于您提到的问题,您可能有:
// 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
定义为字符。中断处理程序宏会将处理程序转换为 Win32 上的常规函数,但确实需要修改您的代码,但由于每个工具链都以不同的方式执行此操作,所以这也许不是坏事。
例如在这种情况下你会改变:
interrupt [TIM1_OVF] void timer1_ovf_isr(void)
{
...
}
到
INTERRUPT( TIM_OVF, timer1_ovf_isr )
{
...
}
请注意,您应该在兼容性文件中使用适当的目标宏 - 例如,我已经猜到了 IAR;您可能正在使用不同的编译器。您的编译器文档应该指定可用的预定义宏,或者 Sourceforge 上的 Pre-defined Compiler Macros "project" 是一个有用的资源。
一些转换可能会在语义上改变代码,例如在某些情况下将 __bit
交换为 char
例如如果该位被分配一个大于 1 的值,然后与 1 进行比较,嵌入式目标可能会产生 true,而在 PC 构建上则不会。它可能更好地转换为 _Bool
但您的编译器可能会发出有关隐式转换的警告。我的建议也不一定是最好的转换 - 请查阅您的编译器手册以了解精确的语义,并决定如何最好地将它们转换为标准 C 以进行测试构建。
另一种保留专有语义的方法是 运行 在 instruction-set 模拟器中使用调试器脚本进行单元测试(如果可以实现硬件交互存根),但是该方法无法使用 off-the-shelf unit-testing 框架,例如 CUnit。
我有一个为 ATmega16 芯片编写的 C 代码,它充满了关键字,例如:
flash, eeprom, bit
和宏 (?) 如
interrupt [TIM1_OVF] void timer1_ovf_isr(void)
在函数签名之前。
现在我想做的是编写 运行 单元测试来验证控制器单元逻辑的正确性,我希望能够 运行 在任何计算机上进行这些测试,并且不需要代码表示的 "device"。
我搜索了很多并遇到了 "abstracting the hardware" 和 "replacing them with stubs" 种解决方案,但我不确定如何抽象出类似“中断 [TIM1_OVF]”在代码中!
我想知道是否有任何特殊工具可以为 运行 编写此类代码提供环境?
而且,如果我做错了,有人能指出我正确的方向吗?考虑到更改或重写 (!) 微控制器的代码可能不是一种选择?
非常感谢。
根据您的工具链,您可能已经有了可用的 AVR 模拟器,这将允许您在任何 PC 上 运行 进行单元测试。例如,IAR 提供 "C-SPY",一个支持终端 window 的 AVR 模拟器,可以显示显示寄存器值,可以支持中断生成等。假设您保持合理的单元大小,则不需要使这项工作有效的重要基础设施或存根接口。
运行在目标平台(使用目标编译器)上进行单元测试的一大好处是,您可以考虑由平台(字节序、字长、编译器)引起的任何特定行为或库特性等),与 运行 PC 环境中的 ning 相比。
您的示例不是 ISO C 代码,它们是特定于编译器的扩展,它们在 AVR 编译器中并不常见,更不用说架构了。在许多情况下,它们可以通过定义需要很少或不需要修改代码的宏来解决。为了使您的代码在任何情况下都可移植,甚至跨不同供应商的 AVR 编译器,在任何情况下都这样做是个好主意,尽管可能需要结合使用多种技术。
大多数编译器支持 "always include" 选项,允许从命令行包含 header 文件,并在源代码中使用显式 #include
指令。使用您的兼容性宏创建 header 并将其包含在代码中,如所描述的那样隐式地或显式地包含在代码中是一种有用的技术。例如对于您提到的问题,您可能有:
// 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
定义为字符。中断处理程序宏会将处理程序转换为 Win32 上的常规函数,但确实需要修改您的代码,但由于每个工具链都以不同的方式执行此操作,所以这也许不是坏事。
例如在这种情况下你会改变:
interrupt [TIM1_OVF] void timer1_ovf_isr(void)
{
...
}
到
INTERRUPT( TIM_OVF, timer1_ovf_isr )
{
...
}
请注意,您应该在兼容性文件中使用适当的目标宏 - 例如,我已经猜到了 IAR;您可能正在使用不同的编译器。您的编译器文档应该指定可用的预定义宏,或者 Sourceforge 上的 Pre-defined Compiler Macros "project" 是一个有用的资源。
一些转换可能会在语义上改变代码,例如在某些情况下将 __bit
交换为 char
例如如果该位被分配一个大于 1 的值,然后与 1 进行比较,嵌入式目标可能会产生 true,而在 PC 构建上则不会。它可能更好地转换为 _Bool
但您的编译器可能会发出有关隐式转换的警告。我的建议也不一定是最好的转换 - 请查阅您的编译器手册以了解精确的语义,并决定如何最好地将它们转换为标准 C 以进行测试构建。
另一种保留专有语义的方法是 运行 在 instruction-set 模拟器中使用调试器脚本进行单元测试(如果可以实现硬件交互存根),但是该方法无法使用 off-the-shelf unit-testing 框架,例如 CUnit。