我可以通过编程方式检测草图中的更改吗?

时间:2015-09-15 21:31:37

标签: c arduino preprocessor-directive

在工作中,我们有一个定期更改的Arduino草图。简而言之,它在串行端口上来回通信。在大多数情况下,我们的软件开发团队控制代码;但是,我们公司还有其他一些团队定期对草图进行最后一分钟的更改,以满足特定客户的需求。

这显然是非常有问题的,因为这意味着我们可能会在不同的地方部署不同版本的草图,而不会意识到这一点。我们的软件开发人员非常擅长使用源代码控制,但其他团队并不那么自律。

提出的一个想法是对版本号进行硬编码,以便某个串行命令通过报告预定义的版本号来响应。但问题是,如果他们决定进行其他更改,我们的其他团队可能同样无法更新版本号。

显然,最好的解决方案是切断其他团队的更新,但假设出于办公室政治原因这是不可能的,我想知道是否有任何方式可以通过编程方式"反映&# 34;在Arduino草图上。显然草图将占用一定数量的字节,而草图文件将具有唯一的文件哈希。我在想是否有某种方法可以将字节数,文件哈希值或上次修改时间作为预处理程序指令获取,这些指令可以注入到理想的代码中。像这样:

// pseudocode
const String SKETCH_FILE_HASH = #filehash;
const int SKETCH_FILE_SIZE = #filesize;
const int SKETCH_LAST_UPDATED = #modified;

但据我所知,这与此有关。有没有办法为Arduino代码编写自定义预处理程序指令或宏?特别是可以检查草图文件本身的那些?这甚至可能吗?或者是否有某种方式已经存在以编程方式跟踪某种方式的变化?

2 个答案:

答案 0 :(得分:1)

冒险回答。

  • SKETCH_FILE_HASH:你必须在外部预先计算并作为标志传递。我想你正在使用arduino IDE,这是不可行的
  • SKETCH_FILE_SIZE:同样的回答
  • SKETCH_LAST_UPDATED:您可以使用__TIME__获取包含编译时间的字符串。

我会做什么,考虑到政治部分。

  • 嵌入了与您的版本控制相关联的关键字(例如svn:id用于颠覆,几乎所有VCS都提供此功能)
  • 嵌入编译时间
  • 更改官方版本(SW团队控制的版本)使用实际工具链而不是IDE并将其放在jenkins上:您将能够使用编译标记!

嵌入像

这样的代码
#ifndef BUILD_TYPE
  #define BUILD_TYPE "Unsupported"
#endif

在您的持续构建过程中,使用-DBUILD_TYPE="HEAD""Release"

对不起,我没有看到魔法棒解决你的解决方案。我已经投入大量资金进行培训,为什么版本控制可以拯救你(似乎你已经有了战争故事)

答案 1 :(得分:0)

我自己正在看这个问题,并发现了这个:

https://gist.github.com/jcw/1985789#file-bootcheck-ino

这是查找引导加载程序;但我认为像这样的东西可以用来确定整个代码的某种签名。

我做了一个快速实验,在那里我添加了类似的内容:

Serial.print("Other...");
Serial.println(CalculateChecksum(0, 2048));

在void setup()中,并且 能够根据更改一小段代码(字符串)获得CRC的不同值。

这不是一个明确的解决方案;我尝试了CalculateChecksum(0,32767),依此类推,如果我定义了一个类似int a = 101的整数;并将其更改为int a = 102;校验和是一样的。只有当我更改了一个字符串(即添加一个空格)时,这个值才会改变。

我对Arduino中分配内存的方式不太清楚;我知道有程序存储器(32,256字节)和全局变量存储器(2048字节),所以我确信有一些方法可以做到这一点。

在另一个实验中,我使用了pgm_read_byte()函数,如果我创建一个简单的内存转储函数:

void MemoryDump (word addr, word size) {
  word dataval = ~0;
  // prog_uint8_t* p = (prog_uint8_t*) addr;
  uint8_t* p = (uint8_t*) addr;
  for (word i = 0; i < size; ++i)
    {
    dataval = pgm_read_byte(p++);
    Serial.print(i);
    Serial.print(" ->");
    Serial.print(dataval,HEX);
    Serial.print(" ");
    Serial.print(dataval);
    Serial.print(" ");
    if(dataval>32)
    {
    Serial.print(char(dataval));
    }
    else
    {
    Serial.print("***");
    }
    Serial.print("\n");
    }
}

...我输入了一句话: Serial.println(F( “12345fghijklmnopqrstuvwxyz”));

因为F()将字符串放在程序存储器中,你会在那里看到它。

如上所述,读取SRAM是一个问题:

http://forum.arduino.cc/index.php?topic=220125.0

我不是编译器之神,所以我不知道像a = 101这样的东西;查看编译器/ IDE,或者为什么这与程序存储区没有什么不同。

最后一点:

http://playground.arduino.cc/Code/AvailableMemory

这些函数可以访问SRAM,所以通过一些调整,你可以在那个内存上做一个CRC,但这似乎有点问题,因为你必须做一个用SRAM中的变量计算!但是如果代码是相同的,即使进行这样的计算,它也许是可能的。再次,我在这里深水,所以如果一个AVR上帝对此有疑问,请用一个丑陋的事实破坏这个理论!