C或C++;选择代码块的预处理器 我试图为一个嵌入式系统编写一个生产测试软件,在那里我可以编写一个测试脚本(理想的是C++代码),其中部分在主机上执行,部分在DUT(被测试设备)上。通信是通过串行端口进行的
这里的一个重要目标是减少嵌入式端的代码大小,而不降低测试输出的可读性。所以我的0级目标,你可以说是热身练习,就是能够写出这样的东西:C或C++;选择代码块的预处理器 我试图为一个嵌入式系统编写一个生产测试软件,在那里我可以编写一个测试脚本(理想的是C++代码),其中部分在主机上执行,部分在DUT(被测试设备)上。通信是通过串行端口进行的,c++,c-preprocessor,conditional-compilation,C++,C Preprocessor,Conditional Compilation,这里的一个重要目标是减少嵌入式端的代码大小,而不降低测试输出的可读性。所以我的0级目标,你可以说是热身练习,就是能够写出这样的东西: //TestScript.cpp START_TESTS() ... const unsigned pot1res = testPotentiometer(pot1); TEST_PRINT("Potentiometer 1 test result %u", pot1res); const unsigned pot2res = test
//TestScript.cpp
START_TESTS()
...
const unsigned pot1res = testPotentiometer(pot1);
TEST_PRINT("Potentiometer 1 test result %u", pot1res);
const unsigned pot2res = testPotentiometer(pot2);
TEST_PRINT("Potentiometer 2 test result %u", pot2res);
...
END_TESTS()
它将通过预处理器的欺骗和嵌入式端的选择性编译来编译
const unsigned pot1res = testPotentiometer(pot1);
write_uart(123); //Unique id, perhaps from __COUNTER__
write_uart(pot1res);
const unsigned pot2res = testPotentiometer(pot2);
write_uart(124); //Unique id, perhaps from __COUNTER__
write_uart(pot2res);
主持人呢?
std::array gTestStrings = {
... other strings ....
TestString{123, "Potentiometer 1 test result %u", unsigned_tag},
TestString{124, "Potentiometer 2 test result %u", unsigned_tag},
... more strings ....
};
后者的目的当然是,主机软件只需侦听UART以获取唯一id,然后从gTestStrings
中查找所需参数,接收它们,并将消息打印到其测试日志中。请注意,字符串已从嵌入端完全消失
这里的嵌入端当然很简单,只需以明显的方式定义TEST\u PRINT
宏,支持varargs等应该不会太难。但是,不清楚如何定义主机端,因为宏之间的代码必须完全消失。我很确定我可以用一些模板等正确地获取unsigned_标记
标准C++17是值得赞赏的,但如果需要,GCC/Clang细节是允许的,预处理器显然将在这方面发挥重要作用。当然,宏的语法也可以在必要时进行调整。基于“使用模板对不同类型执行相同的操作””您可以简单地定义一个模板化类或方法,该类或方法根据嵌入上下文或主机上下文调用不同的实现
伪代码示例:
#include <sstream>
#include <string>
class Mock
{
protected:
// TODO : output values array / map - by - testID
public:
unsigned readPot(int const testID)
{
// TODO : return value from the values array/map
}
};
class ActualDevice
{
public:
unsigned readPot(int const testID)
{
// TODO : write/read the device
}
};
//DEVICE_IMPL must implement a method with this signature:
//unsigned readPot(int const testID)
template<typename DEVICE_IMPL>
void runTests()
{
DEVICE_IMPL device;
std::string testOutput;
//TODO : substitute with for-loop to run all tests
int testID = 1;
{
unsigned output = device.readPot(testID);
std::stringstream accum;
accum << "Test " << testID << " output = " << (int)output << std::endl;
testOutput = accum.str();
// TODO : do something with testOutput
}
}
void testHost ()
{
runTests<Mock>();
}
void testDevice()
{
runTests<ActualDevice>();
}
#包括
#包括
课堂模拟
{
受保护的:
//TODO:输出值数组/map-by-testID
公众:
无符号读取器(int const testID)
{
//TODO:从值数组/映射返回值
}
};
类实际设备
{
公众:
无符号读取器(int const testID)
{
//TODO:写入/读取设备
}
};
//设备\u IMPL必须实现具有此签名的方法:
//无符号读取器(int const testID)
模板
void运行测试()
{
装置\植入装置;
std::字符串testOutput;
//TODO:替换为for循环以运行所有测试
int-testID=1;
{
无符号输出=device.readPot(testID);
标准::stringstream accum;
累积
我并不特别喜欢这种设计——对我来说似乎不够灵活。但这样的代码可以作为模板,让您编写更好的东西。我在测试宏中添加了表达式,这样就可以在主机端删除它,并在设备端使用它。另一个选项可以是X宏:
盆栽试验
嵌入式.c
host.cpp
我不明白,您如何删除const unsigned pot2res=testpotential(pot2);
行?什么是unsigned_标记
?unsigned_标记(这里可能是一个错误的名称选择)是一个标识类型的值。例如,有时测试结果可能是一个浮点,然后我们就有了float_标记。
#ifdef __linux__ // or whatever you have there
#define START_TESTS() std::array gTestStrings = {
#define END_TESTS() };
#define TEST(expr, str) TestString{__LINE__, str, unsigned_tag},
#else
#define START_TESTS() {
#define END_TESTS() }
#define TEST(expr, ...) do{ \
const auto _val = (expr); \
write_uart(__LINE__); \
write_uart(_val); \
} while(0)
#endif
int main() {
START_TESTS()
TEST(testPotentiometer(pot1), "Potentiometer 1 test result %u");
TEST(testPotentiometer(pot2), "Potentiometer 2 test result %u");
END_TESTS()
}
X(123, pot1, "Potentiometer 1 test result %u")
X(124, pot2, "Potentiometer 2 test result %u")
START_TESTS()
...
#define X(id, pot, text) \
do { \
const unsigned potres = testPotentiometer(pot); \
write_uart(id); \
write_uart(potres); \
TEST_PRINT(text, potres); \
} while(0);
#include "pot_tests.h"
#undef X
...
END_TESTS()
std::array gTestStrings = {
... other strings ....
#define X(id, pot, text) TestString{id, text, unsigned_tag},
#include "pot_tests.h"
#undef X
... more strings ....
};