我的应用程序/设备运行在ARM Cortex M3(STM32)上,没有操作系统,但有FatFs,需要访问许多资源文件(音频,图像等)。
由于用户有权访问用于原子更新的资源文件夹,我想将所有这些资源文件打包在一个(.dat,.rom,.whatever)中 因此,用户不会错误处理这些数据。
有人能给我一个很好的解决方案吗?
我不介意在我的应用程序中重新映射fopen,fread,fseek和fclose,但我不想从头开始(编写序列化程序,内容表,解析器等等)。我的系统非常有限(没有malloc,没有框架,只有stdlib和FatFs)
感谢您提供的任何意见。
注意:我不是在寻找一种资源嵌入代码(ROM)的解决方案,因为它们显然太大了。
答案 0 :(得分:1)
扩展约阿希姆上面所说的内容:
未压缩(有时)归档格式的流行选择是cpio,tar和zip。 3中的任何一个都可以正常工作。
以下是关于使用TAR或CPIO的一些更深入的评论。
我之前在使用FatFS的stm32上使用 tar 达到了确切的目的,所以可以告诉你它有效。我选择cpio或zip是因为它熟悉(大多数开发人员已经看过),易用性和丰富的命令行工具。
GNU Tar为您提供了对文件放置在存档中的顺序的细粒度控制,以及用于操作文件名(--xform
)或--exclude
路径的正则表达式。您几乎可以保证只需使用GNU Tar和makefile就可以获得完整的归档文件。我不确定cpio
或zip
是否可以这样说。
这意味着它适用于我的构建环境,但您的要求可能会有所不同。
在我看来, cpio 比使用 tar 更难/更难使用命令行工具。这就是为什么我尽可能避开它。但是,它的文件格式稍微轻一些,可能甚至更难解析(不是tar很难)。
Linux内核项目使用cpio作为initramfs图像,因此这可能是互联网上用于此类目的的最佳/最成熟的例子。
如果您获取任何内核源代码树,则工具usr/gen_init_cpio.c
可用于从该源文件中描述的cpio列表文件格式生成cpio。
提取代码位于init/initramfs.c
。
我从未将zip格式用于此类目的。那里没有真正的评论。
答案 1 :(得分:1)
应该可以递归使用fatfs。
驱动器0将是您的真实设备,驱动器1将是驱动器0上的文件。您可以实现像这样的disk_ *函数
#define BLOCKSIZE 512
FIL imagefile;
DSTATUS disk_initialize(BYTE drv) {
UINT r;
if(drv == 0)
return SD_initialize();
else if(drv == 1) {
r = f_open(&image, "0:/RESOURCE.DAT", FA_READ);
if(r == FR_OK)
return 0;
}
return STA_NOINIT;
}
DRESULT disk_read(BYTE drv, BYTE *buff, DWORD sector, DWORD count) {
UINT br, r;
if(drv == 0)
return SD_read_blocks(buff, sector, count);
else if(drv == 1) {
r = f_seek(&imagefile, sector*BLOCKSIZE);
if(r != FR_OK)
return RES_ERROR;
r = f_read(&imagefile, buff, count*BLOCKSIZE, &br);
if((r == FR_OK) && (br == count*BLOCKSIZE))
return RES_OK;
}
return RES_ERROR;
}
要在Linux或其他类似系统上创建文件系统映像,您需要mkfs.msdos和mtools包。 See this SO post on how to do it。也可以使用Cygwin在Windows上工作。
答案 2 :(得分:1)
Berendi 找到了一个非常聪明的解决方案:使用现有的胖库递归访问它!
实现非常简单,经过大量测试后,我想发布代码以递归使用FatFs和用于生成单个文件脂肪的命令。
dd if = / dev / zero of = fat.fs bs = 1024 count = 102400
mkfs.vfat -F 32 -r 112 -S 512 -v fatfile.fs
在虚拟FAT上回显HelloWorld>> helloworld.txt
mcopy -i fatfile.fs helloworld.txt :: /
DSTATUS disk_status () { DSTATUS status = STA_NOINIT; switch (pdrv) { case FATFS_DRIVE_VIRTUAL: printf("disk_status: FATFS_DRIVE_VIRTUAL\r\n" ); case FATFS_DRIVE_ATA: /* SD CARD */ status = FATFS_SD_SDIO_disk_status(); } }
#define _VOLUMES 2
f_mount(&VirtualFAT, (TCHAR const*)"1:/", 1); f_open(&file, "1:/test.txt", FA_READ);
非常感谢你的帮助。