我可以以编程方式检测草图中的变化吗?

Can I programmatically detect changes in a sketch?

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

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

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

显然,最好的解决方案是阻止其他团队进行更新,但假设出于办公室政治的原因这不可能,我想知道是否有任何方法可以在 Arduino 草图上以编程方式 "reflect"。显然草图将占用一定数量的字节,并且该草图文件将具有唯一的文件哈希。我在想,是否有某种方法可以将字节数、文件哈希或最后修改时间作为预处理器指令注入到理想的代码中。像这样:

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

但据我所知,这大概就是这样。有没有办法为 Arduino 代码编写自定义预处理器指令或宏?特别是那些可以检查草图文件本身的?这可能吗?或者是否已经存在某种方式来以编程方式以一种或另一种方式跟踪更改?

冒险回答。

  • 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"

很抱歉,我没有看到可以解决您的问题的魔法棒。我会投入大量资金来培训为什么版本控制可以拯救你(似乎你已经有了 war 个故事)

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

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

这是为了查找bootloader;但我认为像这样的东西可以用于确定整个代码的某种签名。

我做了一个快速实验,我在其中添加了如下内容:

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

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

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

我不crystal 清楚 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;这样的东西怎么样?查看 compiler/IDE,或者为什么这看起来与程序内存区域没有什么不同。

最后一点:

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

这些函数访问 SRAM,所以也许,通过一些调整,您可以在 那个 内存上执行 CRC,但这似乎有点问题,因为您必须用变量进行计算……在 SRAM 中!但如果代码相同,即使进行这样的计算,也有可能。再一次,我在这里陷入困境,所以如果 AVR 大神对此有异议,请用一个丑陋的事实来摧毁这个理论!