Keil MDK自带了一个FCARM工具,用于将一个web服务器所需的网页文件(html、图片等)转成一个数据包,这样可以省去文件系统。也可以用于在代码里嵌入一些二进制文件,如图片、字库等。本文介绍其用法。
首先要设置FCARM工具的运行参数:
Output File:不管有几个二进制文件,最后会合到一个文件里,这里设置输出结果的C文件名。
Add Output File to Group:结果文件放到哪个组里,按需设置。
Image Files Root Folder:所有原始二进制文件要放到一个目录里。如果在项目根目录就不写,子目录就写目录名。
添加位图或其它二进制文件到项目中。为了方便后续操作,最好将二进制文件添加到一个单独的Group里。
点Add后会让你确认文件类型,是Image File就对了。
然后就可以正常编译项目了,会先调用FCARM工具将二进制文件转成C:
FCARM uses the following Files via command file '.\Auto_FcArm_Cmd.inp':
test.bin,
test.bmp
TO bin.c RTE NOPRINT
custom translating @.\Auto_FcArm_Cmd.inp...
Custom: C:\Keil_v5\ARM\Bin\FCARM.exe @.\Auto_FcArm_Cmd.inp
FCARM FILE CONVERTER V2.54
Completed2File(s),Ratio100%
项目结果如下:
注:为了避免每次都重新生成bin.c,可以将二进制文件放到一个单独的Group里。当二进制文件没有更新时,将该组设成Exclude from building。有更新时再设回来编译一次。
生成的bin.c如下:
/*------------------------------------------------------------------------------
* uVision/ARM development tools
* Copyright (C) 2015 ARM Ltd and ARM Germany GmbH. All rights reserved.
*------------------------------------------------------------------------------
* Name: bin.c
* Purpose: ROM Image generated from user specified files.
* Note: Generated by FCARM FILE CONVERTER V2.54, do not modify!
*----------------------------------------------------------------------------*/
#include<stddef.h>
#include<stdint.h>
/* File information */
typedefstruct _imageFileItem {
uint32_t id;/* Name identifier (CRC32 value of file name) */
constuint8_t*data;/* Data start address in ROM */
} imageFileItem;
#define IMAGE_FILE_COUNT 2U
/* Last-Modified: Mon, 10 Aug 2015 08:20:40 GMT */
constuint32_t imageLastModified =1439194840U;
staticconstuint8_t imageFileData[244940U]={
/*-- File: test.bin, 122470 bytes --*/
0xFFU,0xD8U,0xFFU,0xE0U,0x00U,0x10U,0x4AU,0x46U,0x49U,0x46U,0x00U,0x01U,0x02U,
0x00U,0x00U,0x01U,0x00U,0x01U,0x00U,0x00U,0xFFU,0xE1U,0x04U,0x0EU,0x45U,0x78U,
。。。。。。。。
0xC6U,0xB7U,0xFEU,0xDEU,0xB5U,0xFFU,0x00U,0xE8U,0x8EU,0x7EU,0xF5U,0xE6U,0x7FU,
0x81U,0x3FU,0xB7U,0x7FU,0xFEU,0x4BU,0x2FU,0xE9U,0xFFU,0xD9U,
/*-- File: test.bmp, 122470 bytes --*/
0xFFU,0xD8U,0xFFU,0xE0U,0x00U,0x10U,0x4AU,0x46U,0x49U,0x46U,0x00U,0x01U,0x02U,
0x00U,0x00U,0x01U,0x00U,0x01U,0x00U,0x00U,0xFFU,0xE1U,0x04U,0x0EU,0x45U,0x78U,
。。。。。。。。
0xC6U,0xB7U,0xFEU,0xDEU,0xB5U,0xFFU,0x00U,0xE8U,0x8EU,0x7EU,0xF5U,0xE6U,0x7FU,
0x81U,0x3FU,0xB7U,0x7FU,0xFEU,0x4BU,0x2FU,0xE9U,0xFFU,0xD9U
};
staticconst imageFileItem imageFileTable[2U+1U]={
{0xD4E67E90U,&imageFileData[0U]},
{0xE15D2443U,&imageFileData[122470U]},
{0x00000000U,&imageFileData[244940U]}
};
/*
* Calculate 32-bit CRC (Polynom: 0x04C11DB7)
* Parameters:
* crc32: CRC initial value
* val: Input value
* Return value: Calculated CRC value
*/
staticuint32_t crc32_8bit (uint32_t crc32,uint8_t val){
uint32_t n;
crc32 ^=((uint32_t)val)<<24U;
for(n =8U; n; n--){
if(crc32 &0x80000000U){
crc32 <<=1U;
crc32 ^=0x04C11DB7U;
}else{
crc32 <<=1U;
}
}
return(crc32);
}
/*
* Get file information from ROM image
* Parameters:
* name: File name
* data: Pointer where file data pointer will be written
* Return value: File size
*/
uint32_t imageFileInfo (constchar*name,constuint8_t**data){
uint32_t id, n;
if((name == NULL)||(data == NULL))return0U;
id =0xFFFFFFFFU;
for(;*name; name++){
id = crc32_8bit(id,*name);
}
for(n =0U; n < IMAGE_FILE_COUNT; n++){
if(imageFileTable[n].id == id){
*data = imageFileTable[n].data;
return(imageFileTable[n+1].data - imageFileTable[n].data);
}
}
return0U;
}
可以看到所有的文件转成一个大数组imageFileData和一个索引表imageFileTable。索引方法是将文件名用CRC32转成一个32位的数值做id。用imageFileInfo()函数可以将文件名字符串转成id值,并查表找到对应数据起始位置。如果觉得这样太繁琐,可以将数组内容复制到需要的地方,而这个bin.c不必参与build。