嵌入式系统上的外部文件资源(带FAT的C语言)

时间:2016-02-08 14:37:03

标签: c embedded stm32 fatfs

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

  • 代码从内部闪存(ROM,256Kb)运行。
  • 资源文件存储在外部闪存(SD卡,4Gb)上。
  • RAM(32Kb)不多,所以malloc包中的完整文件不是一个选项。

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

有人能给我一个很好的解决方案吗?

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

感谢您提供的任何意见。

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

3 个答案:

答案 0 :(得分:1)

扩展约阿希姆上面所说的内容:

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

以下是关于使用TAR或CPIO的一些更深入的评论。

TAR

我之前在使用FatFS的stm32上使用 tar 达到了确切的目的,所以可以告诉你它有效。我选择cpio或zip是因为它熟悉(大多数开发人员已经看过),易用性和丰富的命令行工具。

GNU Tar为您提供了对文件放置在存档中的顺序的细粒度控制,以及用于操作文件名(--xform)或--exclude路径的正则表达式。您几乎可以保证只需使用GNU Tar和makefile就可以获得完整的归档文件。我不确定cpiozip是否可以这样说。

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

CPIO

在我看来, cpio 比使用 tar 更难/更难使用命令行工具。这就是为什么我尽可能避开它。但是,它的文件格式稍微轻一些,可能甚至更难解析(不是tar很难)。

Linux内核项目使用cpio作为initramfs图像,因此这可能是互联网上用于此类目的的最佳/最成熟的例子。

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

提取代码位于init/initramfs.c

ZIP

我从未将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和用于生成单个文件脂肪的命令。

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

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

         

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

    1. 创建/推送内容:
    2.   

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

           

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

      1. 更改diskio.c文件,添加Berendi的代码,但也包括:
      2. 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. 不要忘记为驱动器名称和卷数添加枚举:
        2.   

          #define _VOLUMES 2

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

            非常感谢你的帮助。