Ресурс внешнего файла во встроенной системе (язык C с FAT)

Мое приложение / устройство работает на ARM Cortex M3 (STM32), без ОС, но с FatFs) и нуждается в доступе ко многим файлам ресурсов (аудио, изображения и т. Д.)

  • Код запускается с внутренней флешки (ROM, 256Кб).
  • Файлы ресурсов хранятся на внешней флэш-карте (SD-карта, 4 Гб).
  • ОЗУ не так много (32 КБ), поэтому malloc полный файл из пакета не вариант.

Поскольку у пользователя есть доступ к папке ресурсов для атомарного обновления, я бы хотел упаковать все эти файлы ресурсов в один файл (.dat, .rom, .whothing), чтобы пользователь не обрабатывал эти данные неправильно.

Может кто-нибудь указать мне хорошее решение для этого?

Я не против переназначения fopen, fread, fseek и fclose в моем приложении, но я не хотел бы начинать с нуля (кодирование сериализатора, оглавления, анализатора и т. Д.). Моя система довольно ограничена (без malloc, без фреймворка, просто stdlib и FatFs)

Спасибо за любой вклад, который вы можете дать мне.

примечание: я не ищу решения, в котором ресурсы встроены в код (ПЗУ), поскольку очевидно, что они слишком велики для этого.

3 ответа

Решение

Должно быть возможным использовать 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. Посмотрите этот ТАК пост о том, как это сделать. Может работать на Windows с Cygwin тоже.

Беренди нашел очень умное решение: используйте существующую толстую библиотеку для рекурсивного доступа!

Реализация довольно проста, и после тщательного тестирования я хотел бы опубликовать код для рекурсивного использования FatFs и команд, используемых для генерации одного файла.

  1. Сначала давайте сгенерируем файл FAT32 размером 100 Мбайт:

дд если = / dev / zero of = fat.fs bs = 1024 count = 102400

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

  1. Создайте / вставьте в него контент:

эхо HelloWorld на виртуальной FAT >> helloworld.txt

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

  1. Измените файл diskio.c, чтобы добавить код Беренди, но также:
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);

Большое спасибо за вашу помощь.

Чтобы расширить то, что сказал Иоахим выше:

Популярные варианты несжатых (иногда) форматов архивов: cpio, tar и zip. Любой из 3 будет работать нормально.

Вот еще несколько подробных комментариев по использованию TAR или CPIO.

TAR

Я использовал tar ранее для точной цели, на stm32 с FatFS, поэтому могу сказать, что он работает. Я выбрал его вместо cpio или zip из-за его знакомства (большинство разработчиков видели это), простоты использования и богатых инструментов командной строки.

GNU Tar дает вам детальный контроль над порядком, в котором файлы помещаются в архив, и регулярные выражения для манипулирования именами файлов (--xform) или же --exclude пути. Вы можете в значительной степени гарантировать, что можете получить именно тот архив, который вам нужен, только с помощью GNU Tar и make-файла. Я не уверен, что то же самое можно сказать и о cpio или же zip,

Это означает, что он хорошо работал для моей среды сборки, но ваши требования могут отличаться.

CPIO

На мой взгляд, у cpio гораздо более / менее сложный набор инструментов командной строки, чем у tar. Вот почему я избегаю этого, когда могу. Тем не менее, его формат файла немного легче и может быть даже проще для анализа (не то, что tar сложный).

Проект ядра Linux использует cpio для образов initramfs, так что это, вероятно, лучший / самый зрелый пример в Интернете, который вы найдете при использовании его для такого рода целей.

Если вы возьмете любое исходное дерево ядра, инструмент usr/gen_init_cpio.c может использоваться для генерации cpio из формата файла списка cpio, описанного в этом исходном файле.

Код извлечения находится в init/initramfs.c,

ZIP

Я никогда не использовал формат zip для такого рода целей. Так что никаких реальных комментариев нет.

Другие вопросы по тегам