文章目录
前言
我写这篇文章的初衷是为了做部门内部的分享,如果能帮到更多的人,那就更好了,所以欢迎也期待你们的转载和收藏!
IAR是常用于单片机代码开发,里面有很多实用的工具,比如ielftool.exe,这个工具可以根据你的配置来生成软件代码的checksum。如下图这个工具:

checksum的直接的应用之一就是,做UL或者CE认证的时候,会要求你提供某些代码段的checksum来进行软件管控。
我在工作中就有这个应用需求,但是苦于网上的资料比较杂,很多都是用的Keil,而且很多的方法我实际使用了以后觉得并不是特别方便,所以我在这里提供一种我个人认为比较方便的方法,可以生成任意段代码checksum,并可以把这些生成的checksum放在任意位置。
另外,因为IAR每次编译只能单独生成.bin或者.hex文件而不能同时生成,所以我也会利用ielftool,提供一种同时生成bin和hex的方法。
一、配置你的开发环境
1.IAR准备
我这里使用的是IAR 9.10.1版本,IAR和KEIL都有32k的免费版license,能够满足一般产品的应用。
2.普通工程准备
弄一个文件含有main.c能编译就行了,我这里使用的是GD32E230C8T6这个芯片,也是目前我个人用的比较多的M0芯片,基础的软件就是跑个时钟中断而已,简单易用,看的更清楚。
3.ICF文件准备
这里先添加个基础的icf文件,后续会对这个进行修改。
4.BAT文件准备
先创建个HexCRC.bat.txt的空白文件,可以利用记录本来进行编辑,后续给IAR调用的时候要将.txt的后缀删掉。这个文件就是专门用来放ielftool的执行代码的。
5.别急,兄嘚
东西是不是要准备很多?别急,我在最后将提供整个项目的压缩包供你们下载,不要钱。里面包含了以上提到的文件。
二、任务目标
1.ROMs生成任务
我们有三段ROMs,第一个ROM地址从0x08000000到0x08005FFF,用来存放应用层的代码,我们把这段ROM取名为ROM_region。
第二个ROM地址从0x08008000到0x0800F6FF,用来存放UL认证代码,我们把这段ROM取名为ROMUL_region;
第三段ROM地址从0x08000000到0x0800F7FF,代表了总的代码,我们把这段ROM取名为ROMall_region;
你们是不是注意到了,第三段比一二两段的总和还多出了0x00000100的大小,而且他们之间不连续。我这么分区的原因是让你们了解,我这方法可以生成任意段的Checksum,并把任意的Checksum结果放在任意地址,不管你的地址是不是连续的。
2.Checksums生成的任务
首先,我们要为第一、二段生成他们各自的Checksum,并将Checksum放在每段ROM的最后。
然后,我们要在包含第一、二段Checksum的情况下,对整个代码段(即ROMall_region),再次进行一次整体的Checksum计算,并把结果放在ROMall_region的最后。
这么描述可能有点抽象了,我画个图给你们展示下:

我来简单解释下,三个红色涂满的小方框代表的是存放各个ROM生成的CRC,两个黄色框代表我的两个ROM分区(ROM_region和ROMUL_region),外围最大的红色框代表整体的ROM分区(ROMall_region)。
尤其需要注意的是,其中ROMall_region存放的Checksum,是要在ROM_region和ROMUL_region已经存放了Checksum以后,再进行整体计算的Checksum。
所以我们要生成一共3个Checksum。
三、开始干活
1.准备好你的工程
代码如下(没错,就是一个delay延时1ms程序,没了):
int main(void)
{
/* configure systick */
systick_config();
while(1){
delay_1ms(500);
}
}
2.修改icf文件
这个icf文件的作用就是分配ROM和RAM的空间,还可以让一些东西放在固定的位置。
那么要对这个文件做几个修改,在原有的ROM下进行增加,这里列出了所有要增加的项目:
(1)增加申明地址
添加ROMUL和ROMall的地址
define symbol __ICFEDIT_region_ROM_start__ = 0x08000000;
define symbol __ICFEDIT_region_ROM_end__ = 0x08005FFF;
define symbol __ICFEDIT_region_ROMUL_start__ = 0x08008000;
define symbol __ICFEDIT_region_ROMUL_end__ = 0x0800F6FF;
define symbol __ICFEDIT_region_ROMall_end__ = 0x0800F7FF;
(2)增加定义region
利用刚刚定义的地址,定义ROMUL和ROMall的ROM范围
define region ROM_region = mem:[from __ICFEDIT_region_ROM_start__ to __ICFEDIT_region_ROM_end__];
define region ROMUL_region = mem:[from __ICFEDIT_region_ROMUL_start__ to __ICFEDIT_region_ROMUL_end__];
define region ROMall_region = mem:[from __ICFEDIT_region_ROM_start__ to __ICFEDIT_region_ROMall_end__];
(3)对外申明地址
这个是我对他的命名,因为刚刚定义的地址,需要加上这个对外申明才能让IAR引用,如果不加,会报错。这个export关键字和C中的extern有点像,这么说应该比较好理解。
export symbol __ICFEDIT_region_ROM_start__;
export symbol __ICFEDIT_region_ROM_end__;
export symbol __ICFEDIT_region_ROMUL_start__;
export symbol __ICFEDIT_region_ROMUL_end__;
export symbol __ICFEDIT_region_ROMall_end__;
(4)定义checksum值的存放位置
在icf文件中,place at end of A{B}代表将B中的东西放在A内存的尾部。{}中的ro代表readonly只读,不能改。section .checksumUL代表叫.checksumUL的一个内存单元。这个整体意思就是将.checksumUL放在ROMUL_region 内存区域的最后。这两个数值就是我们的checksum最终的计算值。这三个checksum值在第4步会有配置。
place at end of ROM_region { ro section .checksum };
place at end of ROMUL_region { ro section .checksumUL };
place at end of ROMall_region { ro section .checksumall };
(5)将.icf放在指定位置方便IAR调用
存放在如下图的位置,为IAR的调用做准备。

3.添加HexCRC.bat文件
这个文件用来存放ielftool的执行命令,也有很多会告诉你在post-build command line中输入命令,但是那个真的太长了,这点IAR做的很不方便,只适合短的命令。如下图,就是一根线的长度。所以我使用.bat文件来存放文件,在post-build command line中输入调用这个.bat文件,这样就方便多了。

(1)定义.out .bin .hex文件
这里是.bat文件的语法,不用深究,依葫芦画瓢就行。这里定义了三个文件,.out .bin .hex,这个1%就是外部引用的时候用的文件名,引用这个bat文件会跟上IAR生成的名字。
比如$TARGET_DIR$\HexCRC.bat $TARGET_BPATH$,这句话就是说引用HexCRC.bat文件,输入的文件名就是IAR生成的文件名$TARGET_BPATH$,对应的就是里面的1%。
再举个例子,比方说你的工程叫Project.eww,那么你生成的就是Project.out Project.bin Project.hex
set OUT=%1.out
set BIN=%1.bin
set HEX=%1.hex
(2)ielftool语法
我们主要就是用这个工具来生成我们的checksum先拿出基本命令语法,我们逐段解析。
ielftool --fill="0xFF;ROM_Start-ROM_End" --checksum="__checksumall:4,crc32,0xffffffff;ROM_Start-ROM_End" --verbose %OUT1% %OUT2%
这里是三个命令,还是老规矩依葫芦画瓢,详细的解释可以直接去IAR官方help里面查,讲的晦涩难懂,我这里用通俗的话来解释。
ielftool 是代表调用IAR中的ielftool.exe
--fill="0xFF;ROM_Start-ROM_End"是代表没有用到的ROM使用0xFF填满,后面代表ROM的起始和结束地址范围。整句话的意思就是,在ROM_Start到ROM_End范围里,将没有用到的ROM使用0xFF来填满。
--checksum="__checksumall:4,crc32,0xffffffff;ROM_Start-ROM_End"是说给checksum预留4byte的位置,使用固定CRC32算法,计算单元为1字节(这个在IAR中有说明,没有指定的时候就是默认1字节),指定CRC初始值为0xffffffff。整句话的意思就是,现在使用CRC32给我计算指定ROM的checksum,结果要放在一个4byte的叫__checksumall的东西中。
--verbose 是表示记录所执行的操作,在build窗口输出
%OUT1% %OUT2%表示的是将.out1文件中的ROM来做我们之前提到的那一堆操作:fill,checksum,verbose,将这些做完以后,放进out2中。聪明的人就发现了,我们编译完成以后,IAR都是生成.out文件作为可执行文件,而且只有一个,所以这个out1是可以等于out2的。这样可以让.out文件的末尾直接加上checksum。
在这个项目中,根据这个语法,为了同时生成两段ROMs的checksum并放在他们各自的末尾,我们的代码应该是:
ielftool --fill="0xFF;__ICFEDIT_region_ROM_start__-__ICFEDIT_region_ROM_end__" --fill="0xFF;__ICFEDIT_region_ROMUL_start__-__ICFEDIT_region_ROMUL_end__" --checksum="__checksum:4,crc32,0xffffffff;__ICFEDIT_region_ROM_start__-__ICFEDIT_region_ROM_end__" --checksum="__checksumUL:4,crc32,0xffffffff;__ICFEDIT_region_ROMUL_start__-__ICFEDIT_region_ROMUL_end__" --verbose %OUT% %OUT%
这里面连续跟了两个–fill和–checksum,是为了分别对.out文件中的ROM进行操作,生成__checksum和__checksumUL。
ielftool支持同时多段的checksum操作,这点非常灵活和方便,所以可以鼓掌点赞了。
最后,我们来个生成整个代码段__checksumall的代码:
ielftool --fill="0xFF;__ICFEDIT_region_ROM_start__-__ICFEDIT_region_ROMall_end__" --checksum="__checksumall:4,crc32,0xffffffff;__ICFEDIT_region_ROM_start__-__ICFEDIT_region_ROMall_end__" --verbose %OUT% %OUT%
注意,这里的地址都是我们在icf文件中设置的名称。ICFEDIT_region_ROM_start-__ICFEDIT_region_ROMall_end__表示的就是整个代码段。
兄弟们,这段是核心,所以贼罗嗦,我搜了好多篇文章和自己的实践才搞定的。
(3)最后就是同时生成bin和hex文件
在IAR中,你可以使用IAR配置中的config进行配置来生成bin和hex文件,如下图:

但是这里每次只能点一个,就是说你每次只能生成一个hex或者bin,我在日常的应用中就是这样,生产那里同时要bin和hex,我每次都要先生成bin再生成hex,很不方便。
这里其实是IAR用了ielftool.exe工具进行的生成。这里生成的顺序是,先由IAR编译生成可执行文件.out,再由ielftool.exe将.out文件生成.bin文件或者是.hex文件。那么既然如此,我们就可以利用这个特性来用.bat帮我们同时生成.bin和.hex。
第一步,要将上图配置中的generate additional output的勾勾弄掉,避免他重复为我们生成.bin文件。
第二步,编写如下代码:
:: get bin file
ielftool --bin --verbose %OUT% %BIN%
:: get hex file
ielftool --ihex --verbose %OUT% %HEX%
这里就是利用刚生成的.out文件,生成bin和hex的全部过程,编译以后,就可以在文件夹里看到如下图三个文件:

最后,贴上整个的.bat代码段给你们,并将做好的.bat文件放在上图的路径中,方便IAR调用:
:: set BIN and HEX file for getting them in the same time
set OUT=%1.out
set BIN=%1.bin
set HEX=%1.hex
:: this is for two ROMs fill and calculate the ROMs' CRC.
:: fill and calculate CRC for two ROMs
ielftool --fill="0xFF;__ICFEDIT_region_ROM_start__-__ICFEDIT_region_ROM_end__" --fill="0xFF;__ICFEDIT_region_ROMUL_start__-__ICFEDIT_region_ROMUL_end__" --checksum="__checksum:4,crc32,0xffffffff;__ICFEDIT_region_ROM_start__-__ICFEDIT_region_ROM_end__" --checksum="__checksumUL:4,crc32,0xffffffff;__ICFEDIT_region_ROMUL_start__-__ICFEDIT_region_ROMUL_end__" --verbose %OUT% %OUT%
:: calculate all ROMs CRC
ielftool --fill="0xFF;__ICFEDIT_region_ROM_start__-__ICFEDIT_region_ROMall_end__" --checksum="__checksumall:4,crc32,0xffffffff;__ICFEDIT_region_ROM_start__-__ICFEDIT_region_ROMall_end__" --verbose %OUT% %OUT%
:: get bin file
ielftool --bin --verbose %OUT% %BIN%
:: get hex file
ielftool --ihex --verbose %OUT% %HEX%
4.配置IAR来调用上面两个文件:
(1)调用icf文件
没啥可说的,看图~~
文件要放在指定的位置~~

配置中填写$PROJ_DIR$\..\GD32E230x8.icf:

(2)调用bat文件
也没啥可说的,看图~~
文件也要放在指定的位置~~

配置中填写$TARGET_DIR$\HexCRC.bat $TARGET_BPATH$:

(3)添加特殊语句
在extra options中填入如图:

这里做个简要的说明,附上整个代码段:
--keep __checksum
--keep __checksumUL
--keep __checksumall
--place_holder __checksum,4,.checksum,4
--place_holder __checksumUL,4,.checksumUL,4
--place_holder __checksumall,4,.checksumall,4
其中–keep 命令用于强制保留定义的符号__checksum,指示链接器不要进行优化而将其丢弃。
其中–place_holder 命令在Flash中预留位置,用于存放生成的checksum。
他的详细语法,如果是CRC32,就按照我的这个配置就好了:
–place_holder symbol[,size[,section[,alignment]]]
symbol:要创建的符号名称;
size:要保留的字节数;
section:使用的section名;
alignment:section对齐字节;
总结
自此,你编译工程,就可以啦!
我们通过STM32 ST-LINK Utility来看看生成的结果:
开头:

第一个checksum:

第二个checksum:

总体的checksum:

可以看到,没用到的ROM都是用F来填充的,说明了fill命令的作用!
最后附上整个工程给你们~~
可以直接在https://gitcode.net/weixin_42744495/iar-ielftool-checksum 下载相关工程包~~
That’s all~~
拜咦~
1228

被折叠的 条评论
为什么被折叠?



