2

我的应用程序/设备在 ARM Cortex M3 (STM32) 上运行,没有操作系统但有 FatFs) 并且需要访问许多资源文件(音频、图像等)

  • 代码从内部闪存(ROM,256Kb)运行。
  • 资源文件存储在外部闪存(SD 卡,4Gb)上。
  • 没有太多 RAM (32Kb),因此不能从包中 malloc 一个完整的文件。

由于用户可以访问资源文件夹以进行原子更新,我想将所有这些资源文件打包在一个(.dat、.rom、.whatever)中,这样用户就不会错误处理这些数据。

有人可以指出一个很好的解决方案吗?

我不介意在我的应用程序中重新映射 fopen、fread、fseek 和 fclose,但我不想从头开始(对序列化程序、目录、解析器等进行编码)。我的系统非常有限(没有 malloc,没有框架,只有 stdlib 和 FatFs)

感谢您给我的任何意见。

注意:我不是在寻找将资源嵌入代码(ROM)中的解决方案,因为显然它们太大了。

4

3 回答 3

1

Berendi找到了一个非常聪明的解决方案:使用现有的 fat 库递归访问它!

实现非常简单,经过大量测试,我想发布代码以递归使用 FatFs 以及用于单个文件 fat 生成的命令。

  1. 首先,让我们生成一个 100Mb 的 FAT32 文件:

dd if=/dev/zero of=fat.fs bs=1024 count=102400

mkfs.vfat -F 32 -r 112 -S 512 -v fatfile.fs

  1. 在其中创建/推送内容:

在虚拟 FAT 上回显 HelloWorld >> helloworld.txt

mcopy -i fatfile.fs helloworld.txt ::/

  1. 更改 diskio.c 文件,添加 Berendi 的代码,同时:
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();
  }
}
  1. 不要忘记添加驱动器名称的枚举和卷数:

#define _VOLUMES 2

  1. 然后挂载虚拟 FAT,并访问它:
f_mount(&VirtualFAT, (TCHAR const*)"1:/", 1);
f_open(&file, "1:/test.txt", FA_READ);

非常感谢你的帮助。

于 2016-02-10T10:21:20.027 回答
1

扩展 Joachim 上面所说的内容:

未压缩(有时)存档格式的流行选择是 cpio、tar 和 zip。这三个中的任何一个都可以正常工作。

这里有一些关于使用 TAR 或 CPIO 的更深入的评论。

柏油

我之前在带有 FatFS 的 stm32 上使用过 tar ,所以可以告诉你它有效我之所以选择它而不是 cpio 或 zip,是因为它很熟悉(大多数开发人员都见过)、易用性和丰富的命令行工具。

GNU Tar 让您可以细粒度地控制文件在存档中的放置顺序,并使用正则表达式来操作文件名 ( --xform) 或--exclude路径。你几乎可以保证你可以得到你所追求的档案,只需要 GNU Tar 和一个 makefile。我不确定对于cpioor也可以这样说zip

这意味着它适用于我的构建环境,但您的要求可能会有所不同。

CPIO

在我看来,cpio的命令行工具集比tar更糟糕/更难使用。这就是为什么我尽可能避开它的原因。但是,它的文件格式更轻一些,而且解析起来可能更简单(不是 tar 很难)。

Linux 内核项目将 cpio 用于 initramfs 映像,因此这可能是互联网上最好/最成熟的示例,您会发现将其用于此类目的。

如果您抓取任何内核源代码树,该工具usr/gen_init_cpio.c可用于从该源文件中描述的 cpio 列表文件格式生成 cpio。

提取码在init/initramfs.c.

压缩

我从来没有将 zip 格式用于这种目的。所以没有真正的评论。

于 2016-02-08T16:36:51.610 回答
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 包。请参阅此 SO 帖子,了解如何操作。也可以在带有 Cygwin 的 Windows 上工作。

于 2016-02-09T10:44:41.867 回答