我正在进行一个固件项目,在该项目中,我必须对闪存完整性进行crc16检查。
crc是使用IAR-Xlink链接器计算的,并保存在闪存的末尾。再次,在运行时根据代码计算crc,并将其与闪存中存储的值进行比较,以检查完整性。然而,我们只能在闪存的代码段上计算crc。每当我们对代码进行一些更改时,它的大小可能会发生变化。我现在可以手动完成这个过程吗?
从.xcl链接器文件:
// ---------------------------------------------------------
// CRC16 Essentials: -H for fill,-J for checksum calculation
// ---------------------------------------------------------
-HFF
-J2,crc16,,,CHECKSUM2,2=(CODE)5C00-FF7F;(CODE)10000-0x20A13
这里我需要更改第二个代码段的结束值,它现在是0x20A13。我从.map文件中得到这个值,即我的代码在闪存中的内存范围。这是我做的第一次改变。
在这里,我需要从代码进行第二次更改:
sum = fast_crc16(sum, 0x5C00, 0xFF7F-0x5C00+1);
sum = fast_crc16(sum, 0x10000,0x20A13-0x10000+1);
//Check the crc16 values
if(sum != __checksum)
{
// Action to be taken if checksum doesn't match
}
请帮助自动化此过程!!
您可以尝试在IAR中使用__segment_begin
和__segment_size
或__segment_end
内部函数,这些函数在"C/C++编译器参考指南"中有说明,您可以从IAR EW430中的"帮助"菜单中获得。手册上说,他们使用链接器文件中定义的段,互联网上的很多人似乎都在这样使用它,但我尝试了一下,却出现了编译器错误(IAR EW430 5.40.7)。如果它以某种方式被破坏了,你可能想向IAR报告并得到修复(假设你有支持合同)。
你可以这样使用它们:
sum = fast_crc16(sum, __segment_begin("CODE"), __segment_size("CODE"));
我不知道分割段会发生什么。但是,为什么要将重置向量从校验和计算中排除?你可以从CODE的开始到结束,并包括重置向量。
我想你可以这样构建你的代码:
sum = fast_crc16(sum, __segment_begin("CODE"), (char *)__segment_begin("INTVEC") - (char *)__segment_begin("CODE") + 1);
sum = fast_crc16(sum, 0x10000, (char *)__segment_end("CODE") - 0x10000);
此外,您可能注意到,也可能没有注意到,__checksum
变量被放入内存中的任何位置。我发现它潜伏在我的DATA16_ID
段之后,这使它正好位于我的校验和代码范围的中间,而且我不知道如何自动跳过内存部分进行校验和计算。我所做的是通过为闪存中的前两个字节定义一个段并将其放入其中,将__checksum
强制到闪存中的头两个字节。
编辑:错过了第一次更改。如果您手动调整IAR链接器校验和例程的范围,那么为了能够使用编译器中的段内部函数,您需要在链接器中定义一个使用代码末尾的自定义段。
我不知道是否有任何方法可以实现自动化。您可能需要编译两次代码(ugh),一次代码段不受限制,以获得代码的结尾,然后使用脚本提取代码的末尾,然后更新链接器脚本。您可能会在预构建命令行事件上运行初始构建,然后使用不受限制的链接器文件来构建IAR项目。但这似乎很丑陋。
也许您还可以更改您的解决方案,在为应用程序保留的完整闪存上构建crc,而不仅仅是为使用的部分。
然后,您就不需要更改链接器文件或c代码,甚至引导程序也可以在不了解应用程序实际大小的情况下计算crc。