这篇文章将要记录如何配置IAR调用外部工具实现对编译完成后自动对生成的hex文件进行合并、对bin文件进行额外操作。
问题背景:
我们目前的项目在STM32平台上开发,具备远程无线升级功能,即通过GPRS网络实现远程IAP,IAP过程中使用的是bin文件(因为bin文件不包含地址,处理比较简单)。因此,在项目编译后我们就需要两个文件,一个是设备出厂时的烧录文件,该文件为hex个数,一个是设备部署后远程升级时用的bin文件。而出厂hex文件又有两个文件合并而成,分别是BOOT.hex: 用户启动代码,用于引导和远程升级,由BOOT工程编译得到;APP.hex :用户应用代码,有APP工程编译得到。同时,APP.bin: 用户应用代码二进制格式,通过APP工程编译得到。
所以每次重新编译app工程或者boot工程后都要进行一次复制粘贴,而且IAR链接时只能生成一种文件,hex或者bin,选择生成hex时就会删除bin,选择bin又会删除hex。因此要得到这两个文件需要编译连接两次。
另外,升级时我们需要知道bin文件的大小,CRC32校验码,烧录的起始地址,为了操作方便一个比较好的办法是将这三个信息都放到bin文件内部,所以编译生成bin文件后也要对该文件进行处理。
为了简化人工操作,减少出错几率,我就动手编写了一个脚本,每次编译连接完成后自动将APP.hex转为APP.bin,并且将APP.hex和BOOT.hex进行合并。
需要解决的问题:
1.写一个Python脚本,实现BOOT.hex和APP.hex的合并,主要涉及到文件的拷贝
2.写一个Python脚本,计算APP.bin文件的CRC32校验,计算文件内容长度,将这些数据以二进制形式写入到新的bin文件中,且要求高字节在前。
3.将py脚本转换为windows可执行的exe,使用py2exe,具体方法请参考这里。
4.IAR的设置
容易出错的问题:
实现的功能很简单,没有什么容易出错的地方,但是路径的问题还是比较麻烦,发现运行路径和脚本所在路径不一致。
实现步骤(本文主要讲IAR的设置):
1.convertAPP.py 如下:
import ConfigParser
import os
defcont_file_size(filename):
”’count file size
count and print total bytes of the file.”’
‘r’)
try:
allData = fObj.read()
print ‘%s is %d Bytes’
finally:
fObj.close()
defget_file_size(filename):
”’get file size
count and return total bytes of the file.”’
‘r’)
try:
allData = fObj.read()
finally:
fObj.close()
return
defread_config(filename):
”’read configure from the config
config
global
global
# read configuration form config.ini
config = ConfigParser.ConfigParser()
# with open(“config.ini”,’r+’) as cfgfile:
# config.readfp(cfgfile)
‘r+’)
config.readfp(cfgfile)
“info”,“resFile”)
“info”,“dstFile”)
cfgfile.close()
defcopy_data(resFile,dstFile):
”’combine these two files
append resource.txt content to file poem.txt”’
‘r’)
‘a’)
1024)
# print ”’The first content readed
while
fDst.write(poem)
1024)
else:
# print ‘The file read over.’
pass
fDst.close()
fRes.close()
print‘Change to ‘ + os.getcwd() # print current work directory
read_config(‘config.ini’)
cont_file_size(resFile)
cont_file_size(dstFile)
print“Append data from %s to %s…”
copy_data(resFile,dstFile)
print‘New %s is %d Bytes now’
print‘Please use %s to download.’
2.formatBIN.py文件如下:
import os
import binascii
import struct
import ConfigParser
defread_config(filename):
”’read configure from the config
config
global
global
global
# read configuration form config.ini
config = ConfigParser.ConfigParser()
with open(“config.ini”,‘r+’) as
‘\nopen)
config.readfp(cfgfile)
# cfgfile
config.readfp(cfgfile)
“bin”,“resFile”)
“bin”,“dstFile”)
cfgfile.close()
defcomputeFileCRC(filename):
global
try:
1024 * 64
“rb“)
‘\nopen
str1 = f.read(blocksize)
0
while len(str1) != 0:
0xffffffff
str1 = f.read(blocksize)
f.close()
except:
print “compute file crc
return 0
return
defcreatNewFile(oldFile,newFile):
global
0x800c000
crc = computeFileCRC(oldFile)
“L”,addr)[::-1]
“L”,crc)[::-1]
with open(newFile,‘wb‘) as
‘\nopen
with open(oldFile,‘rb‘) as
print ‘open %s’
allData = oldF.read()
dataSize = len(allData)
print ‘File: %s %d Bytes’
print ‘CRC: 0x%08x’
print ‘Addr: 0x%08x’
“L”,dataSize)[::-1]
newF.write(parsedata_addr)
newF.write(parsedata_dataSize)
newF.write(parsedata_crc)
newF.write(allData)
print ‘%s has been created.’
print‘Change to ‘
with“log.txt”,‘w’) as log:
‘config.ini’)
creatNewFile(resFile,dstFile)
3.配置文件config.ini
[info]
resfile = BOOT.hex
dstfile = APP.hex
[bin]
resfile = APP.bin
dstfile = APP.bin1
4.IAR的配置
在IAR中调用外部工具有多种方法,方法一,作为一个外部工具进行配置,这个工具在所有工程中可以使用;方法二,在工程属性中进行配置,编译完成后自动调用外部程序,该方法对单个工程有效。
方法一:
step1:
step2:
如上设置就可以实现了,同时config.ini需要放置到Output目录下。
这里需要注意的是如果不指定 Initial Directory,则脚本的运行目录是IAR工程文件所在的目录。
方法二:
step1:
step2:
由于脚本的运行目录是IAR工程文件所在目录,所以config.ini需要放置到$PROJ_DIR$目录下,也就是 .eww 文件所在目录,且需要使用相对路径指定相应的文件。
config.ini文件内容如下:
[info]
resfile = ..\\Output\\BOOT.hex
dstfile = ..\\Output\\APP.hex
[bin]
resfile = ..\\Output\\APP.bin
dstfile = ..\\Output\\APP.bin1
这样就可以在每次编译完成后自动调用formatBIN.exe对APP.bin进行处理了。
方法2有一个问题就是不能将工具打印信息回显到IAR中,如果出错IAR会提示有一个错误。