Ресурс внешнего файла во встроенной системе (язык 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 и команд, используемых для генерации одного файла.
- Сначала давайте сгенерируем файл FAT32 размером 100 Мбайт:
дд если = / dev / zero of = fat.fs bs = 1024 count = 102400
mkfs.vfat -F 32 -r 112 -S 512 -v fatfile.fs
- Создайте / вставьте в него контент:
эхо HelloWorld на виртуальной FAT >> helloworld.txt
mcopy -i fatfile.fs helloworld.txt:: /
- Измените файл 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(); } }
- Не забудьте добавить перечисление для имени диска и количества томов:
#define _VOLUMES 2
- Затем смонтируйте виртуальный 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 для такого рода целей. Так что никаких реальных комментариев нет.