Программирование Файловые системы AVR114: использование файловой системы Atmel Fri, April 19 2024  

Поделиться

Нашли опечатку?

Пожалуйста, сообщите об этом - просто выделите ошибочное слово или фразу и нажмите Shift Enter.

AVR114: использование файловой системы Atmel Печать
Добавил(а) microsin   

Здесь приведен перевод апноута AVR114: Using the ATMEL File System management for AT32UC3x, AT90USBx and ATmega32U4 [1], посвященного файловой системе Atmel для микроконтроллеров.

AVR114-Atmel-File-SystemКомпания Atmel предоставляет файловую систему (File System) для микроконтроллеров AT32UC3x, AT90USBx и ATmega32U4. Последние 2 микроконтроллера используются на макетных платах AVR-USB162, AVR-USB162MU и AVR-USB32U4 [5]. Файловая система оптимизирована для ядра AVR, и занимает мало памяти (менее 15 килобайт кода FLASH, менее 800 байт SRAM), и обладает высокой скоростью работы. Предлагаемая File System предоставляет много возможностей, такие как открытие нескольких файлов одновременно, или управление списком проигрывания (play list).

Прим. переводчика: готовый проект с исходным кодом для микроконтроллера ATmega32U4 можно скачать по ссылкам в статье [6], это архив avr115.zip. Также см. библиотеку LUFA, где есть проект TempDataLogger с похожим функционалом (логгер температуры в файл).

[2 Особенности и ограничения ATMEL File System]

2.1 Основные возможности

• Позволяет смонтировать (Mount) диски, форматированные FAT12, FAT16, FAT32.
• Поддерживает кодировку имен файлов ASCII и UNICODE.
• Позволяет открыть в одно и то же время несколько файлов (concurrent access, конкурентный доступ).
• Поддерживает формат FAT12/FAT16/FAT32.
• Поддерживается навигация по строковому пути.
• Позволяет управлять каталогами (директориями) - создание, удаление, переименовывание (create, delete, rename).
• Файловый доступ ввода/вывода совместим с DMA.
• Позволяет создавать, удалять, переименовывать, копировать файлы (create, delete, rename, copy).

2.2 Возможности, расширяемые плагинами

• Чтение текстовых файлов (кодировки ASCII, UTF16, UTF16BE, UTF8).
• Чтение плейлиста (форматы *.m3u, *.m3u8, *.pls и *.smp).
• Навигация с использованием фильтра по расширению файла.
• Плоская навигация (flat mode).
• Автоматическая навигация с возможностью повтора и случайного выбора файла.
• Интерфейс Posix.

2.3 Ограничения в использовании, которые накладываются стандартом FAT12/FAT16/FAT32

• Поддерживаемый размер диска до 2 терабайт.
• Поддерживаемый размер файла до 4 гигабайт.
• В корневой директории диска (root directory) файловых систем FAT12/16 поддерживается до 512 файловых записей*.
• В пределах одной директории поддерживается до 65535 файловых записей*.
• Нет ограничения на глубину вложенности папок (каталогов, директорий).

*Примечание: один файл может использовать больше одной записи файла, в зависимости от длины имени этого файла.

2.4 Ограничения в использовании, которые накладываются реализацией ATMEL File System

• При старте не проверяется целостность системы FAT (отсутствует FAT integrity check).
• Порядок следования файлов в списке такой, как он был при создании (не поддерживается сортировка по имени файла).
• Поддерживается только область таблицы FAT номер 2.

Примечание: по стандарту Microsoft имеется 2 копии таблицы FAT, для надежности. Сама Microsoft очень рекомендует использовать вторую копию таблицы FAT.

[3 Обзор ATMEL File System]

3.1 Общие замечания

Atmel FileSystem использует в качестве основы понятие Navigator handle. Navigator handle позволяет просмотреть одну директорию (каталог) или открыть один файл. Система поддерживает несколько handle, чтобы обеспечить одновременны просмотр нескольких папок или открытие нескольких файлов одновременно. Navigator handle очень мал по размеру и требует только 40 байт SRAM.

AVR114-FileSystem-module-organization-fig3.1

Рис. 3-1. Организация модуля Atmel FileSystem.

3.2 Навигация (Navigation)

Доступ к файлу по строковому пути возможен, но navigation handle позволяет получить доступ к списку файлов. Навигация показывает содержимое директории, которое называется списком файлов (file list), и имеет простые команды типа следующий/предыдущий (next/previous), которые используются для перемещения индекса по списку. Список файлов может включать в себя директории и файлы. Когда открывается выбранный по индексу файл, то навигация замораживается (locked). См. рис. 4.2.

Navigation handle (или идентификатор навигации, navigation ID) содержит в себе следующую информацию:

• Номер диска (disk number).
• Ссылку на директорию, которая просматривается.
• Индекс - позиция в списке файлов.
• Флаг навигации lock/unlock (что соответствует файл открыт или закрыт).
• Позиция внутри файла, когда файл открыт.

AVR114-Navigation-organization-fig3.2

Рис. 3-2. Организация навигации.

Когда диск только что подмонтирован (disk mounted), то папкой по умолчанию (default directory) является корневой каталог (root directory), это папка самого верхнего уровня диска. Вы можете переместить значение индекса на подпапку и выбрать её (команда "cd folder") в качестве новой директории для просмотра. Также Вы можете выбрать поддиректорию (команда "cd .."), когда новая директория была просмотрена.

[4 Архитектура ATMEL File System]

4.1 Ядро (Core)

На рисунке 4-1 показана архитектура ядра ATMEL File System.

AVR114-Core-architecture-fig4.1

Рис. 4-1. Архитектура ядра.

4.1.1 FAT

Модуль FAT является модулем низкого уровня, и он декодирует структуру FAT. Все подпрограммы модуля являются приватными (static), и они не могут быть вызваны пользователем.

4.1.2 Навигация (Navigation)

Этот модуль предоставляет подпрограммы:

• для выбора navigator handle
• для навигации в файловом списке
• для изменения выбранной директории
• для модификации дерева директорий
• для получения информации по дискам/директориям/файлам

Все подпрограммы описаны в заголовочном файле navigation.h.

4.1.3 Доступ к файлу (File)

Этот модуль предоставляет управление файловым вводом/выводом (file I/O control):

• Передача одного байта, file_getc() - file_putc(), самая медленная работа с файлом.
• Передача через буфер в SRAM, file_read_buf() - file_write_buf(), работает быстрее.
• Прямая передача* (Direct transfer), file_read() - file_write(), работает быстрее всего.

*Примечание: Direct transfer разработана для передачи данных файла напрямую между двумя областями памяти, без необходимости копирования данных в буфер RAM (например DMA между двумя областями памяти).

Все подпрограммы описаны в заголовочном файле file.h.

4.1.4 Память, носители данных (Memory)

Интерфейс с памятью следующий:

• mem_test_unit_ready(), для проверки состояния памяти.
• mem_wr_protect(), для проверки, включена ли защита от записи (memory write protection).
• memory_2_ram(), для чтения памяти.
• ram_2_memory(), для записи в память.

Все подпрограммы описаны в заголовочном файле ctrl_access.h.

Прим. переводчика: интерфейс с памятью отделяет слой носителя данных от файловой системы. Благодаря этому носитель данных может быть абсолютно любым. Это может быть как флешка SD, подключенная через SPI, параллельная статическая память, динамическая память DDR, floppy-диск, жесткий диск и т. д. Немного (не слишком сильно) утрируя, это может быть хоть радиомодем, перфолента или даже почтовые голуби. Единственное условие - должны быть реализованы эти 4 подпрограммы, которые дают доступ к линейному адресному пространству памяти носителя.

4.1.5 Обработка ошибок (Error control)

Многие подпрограммы возвращают TRUE или FALSE. В случае возврата FALSE глобальная переменная fs_g_status содержит идентификатор ошибки, чтобы можно было получить больше информации об ошибке. Список ошибок доступен в файле fs_com.h.

4.2 Plug-In (подключаемый модуль расширения, плагин)

AVR114-Plug-In-architecture-fig4.2

Рис. 4-2. Архитектура плагинов.

4.2.1 Text reader (чтение текстовых файлов)

Этот плагин позволяет открыть обычный текстовый файл в режиме только для чтения (read only). Поддерживаемые текстовые форматы ASCII, UTF16, UTF16BE и UTF8. Поддерживается множественное открытие текстового файла.

4.2.2 Play list (плейлист, список проигрывания)

Этот плагин поддерживает файловый плейлист в режиме только для чтения (read only). Поддерживаемые расширения *.m3u, *.m3u8, *.pls и *.smp. Имеется ограничение на размер плейлиста - 65535 файлов. Множественное открытие не поддерживается.

4.2.3 Automatic Navigation

Автоматическая навигация была разработана для модуля плеера/просмотрщика. Плагин строит список файлов "file list" со следующими параметрами, управляемыми пользователем:

• Фильтр по расширению файла (Extension filter).
• Ограничение области сканирования (только папка, папка и её подпапка, один диск, все диски).
• Случайный выбор файла из списка (Random feature).

4.2.4 Режим фильтрации (Filtered mode)

Этот плагин фильтрует список файлов "file list" по расширению файла от navigation module. Пример:

// Архитектура диска
folder1
|  folder3
|  |  file4.mp3
|  file5.txt
folder2
|  file6.txt
file1.mp3
file2.txt
file3.mp3
// Список файлов, предоставленный навигатором, корневая // папка (root) является "выбранной" директорией. folder1 folder2 file1.mp3 file2.txt file3.mp3
// Список файлов, предоставленный навигатором, выбранной // является папка folder1. folder3 file5.txt
// Список файлов, предоставленный плагином "FILTER navigator", // который инициализирован фильтром "*.mp3". // Папка "root" является выбранной директорией. folder1 folder2 file1.mp3 file3.mp3
// Список файлов, предоставленный плагином "FILTER navigator", // который инициализирован фильтром "*.mp3". // Папка "folder1" является выбранной директорией. folder3

4.2.5 Flat mode (режим сквозного, "плоского" просмотра)

FLAT mode игнорирует уровни папки и предоставляет список файлов со всеми файлами/папками, которые имеются в выбранной папке или подпапке. Пример:

// Архитектура диска
folder1
|  folder3
|  |  file4
|  file5
folder2
|  file6
file1
file2
file3
// Список файлов, предоставленный навигатором, корневая // папка (root) является выбранной директорией. folder1 folder2 file1 file2 file3
// Список файлов, предоставленный навигатором, выбранной // является папка folder1. folder3 file5
// Список файлов, предоставленный плагином "FLAT navigator", // выбранной является папка "root". folder1 folder3 file4 file5 folder2 file6 file1 file2 file3
// Список файлов, предоставленный плагином "FLAT navigator", // выбранной является папка "folder1". folder3 file4 file5

4.2.6 Filtered & Flat mode

Этот плагин включает в себя возможности фильтрации и плоского режима.

4.3 Интерфейс POSIX

Аббревиатура POSIX расшифровывается как Portable Operating System Interface (портируемый интерфейс с операционной системой), этот интерфейс совместим с операционной системой Unix. Этот интерфейс доступен только для чипов семейств AVR32 и UC3.

AVR114-POSIX-architecture-fig4.3

Рис. 4-3. Архитектура POSIX.

[5 Конфигурирование ATMEL File System]

5.1 Ядро

В зависимости от Вашего приложения, Вы можете оптимизировать размер ядра, если сконфигурируете следующие параметры:

• Разрешение/запрет поддерживаемых разновидностей FAT (FAT12/FAT16/FAT32).
• Разрешение/запрет поддержки UNICODE или ASCII.
• Выбор уровня доступа к файловой системе (READ / WRITE / WRITE_COMPLET*).
• Выбор размера кэша.
• Выбор максимального количества navigator handle.

*Примечание: WRITE_COMPLET включает возможность WRITE (записи) и некоторые дополнительные.

Конфигурация задается в файле conf_explorer.h:

// Этот подключенный заголовочный файл предоставляет подпрограммы для
// работы с памятью (например memset(), memcpy_ram2ram(), ...).
#define LIB_MEM 
// Этот подключенный заголовочный файл предоставляет подпрограммы для
// доступа к диску (например ram_2_memory(), mem_wr_protect(), ...).
#define LIB_CTRLACCESS "ctrl_access.h"
// Поддерживаемые системы FAT (ENABLED разрешено или DISABLED запрещено). #define FS_FAT_12 ENABLED #define FS_FAT_16 ENABLED #define FS_FAT_32 ENABLED
// Эксплорер может поддерживать формат строки либо ASCII, либо UNICODE, // либо оба сразу. #define FS_ASCII DISABLED #define FS_UNICODE ENABLED
// Навигатор может поддержать только первый раздел (партиция диска, // DISABLED), или несколько разделов (ENABLED). #define FS_MULTI_PARTITION DISABLED
// Уровень доступа в ядре File system. Выберите что-то из этого: // - FSFEATURE_READ: все функции чтения. // - FSFEATURE_WRITE: nav_file_copy(), nav_file_paste(), nav_file_del(), // file_create(), file_open(MODE_WRITE), file_write(), file_putc(). // - FSFEATURE_WRITE_COMPLET: FSFEATURE_WRITE функции и nav_drive_format(), // nav_dir_make(), nav_file_rename(), nav_file_dateset(), // nav_file_attributset(). // - FSFEATURE_ALL: все функции. #define FS_LEVEL_FEATURES (FSFEATURE_READ | FSFEATURE_WRITE_COMPLET)
// Количество кэшей, используемых для сохранения списка кластеров файлов // (должно быть > 0). Опция интересна в случае открытия нескольких // файлов одновременно. #define FS_NB_CACHE_CLUSLIST 3
// Количество идентификаторов навигации (navigator ID), которое задает // максимальное количество одновременно открытых файлов, и количество // одновременных просмотров папок (0 < n < 256). Каждый навигатор // использует меньше 50 байт памяти SRAM. #define FS_NB_NAVIGATOR 3
// Навигатор использует следующий идентификатор навигатора (navigator ID), // чтобы открыть копирование файла 'copy file', и текущий navigator ID // для создания вставляемого файла 'paste file'. #define FS_NAV_ID_COPYFILE 2 // Должен отличаться от текущего ID, используемого // при вызове подпрограммы вставки (paste).

5.2 Конфигурация плагинов

Конфигурации Plug-In задается в файле conf_explorer.h.

5.2.1 Play list (список проигрывания)

// Навигатор, используемый для открытия файла плейлиста
#define FS_NAV_ID_PLAYLIST 2
// Интерфейс плейлиста, чтобы выделить место для хранения текущего пути,
// включаемого в плейлист. В этом примере используется библиотека alloc.
#define PLAYLIST_BUF_ALLOC( size ) malloc( size )
#define PLAYLIST_BUF_FREE( buf ) free( buf )
// Пример без использования библиотеки alloc.
#define PLAYLIST_BUF_ALLOC( size ) ((sizeof(g_buffer_512) > 512)? NULL : g_buffer_512)
#define PLAYLIST_BUF_FREE( buf )

5.2.2 Automatic Navigation (автонавигация).

// Фича "учитывать все доступные файлы" может быть запрещена, чтобы
// уменьшить время запуска.
#define FS_NAV_AUTOMATIC_NBFILE ENABLE
// Задает порядок следования файлов в списке, предоставленном плагинов
// автонавигации (nav_automatic.c).
#define NAV_AUTO_FILE_IN_FIRST // Раскомментируйте, чтобы запретить фичу
// Размер для генерации случайного выбора файла (в единицах 8 файлов)
#define NAVAUTO_MAX_RANGE_RAND 8 // 8*8 = 64 файла
// Метод вычисления случайного числа (значение байта)
#include "rand.h"
#define NAVAUTO_GET_RAND( value ) (value=rand())

5.2.3 Navigation Flat (плоская, сквозная навигация по файловой системе)

// Разрешает модули режима FLAT (nav_flat.c & navfilterflat.c)
#define NAVIGATION_MODE_FLAT // Раскомментируйте, чтобы запретить фичу

[6 Примеры использования ATMEL File System]

Примечание: все примеры подразумевают, что файловая система Atmel инициализирована так, как показано в примере "Последовательность включения/выключения (Power ON/OFF)".

6.1 Последовательность включения/выключения (Power ON/OFF)

Инициализация модуля файловой системы:

nav_reset();

Это нужно выполнить перед остановкой модуля файловой системы:

// Если у Вас были открыты файлы, то закройте их.
// Сброс данных (flush), которые могли остаться в кэше FAT, на диск.
nav_exit();

Внимание: не подразумевается, что можно иметь две файловые системы одновременно на одном и том же диске.

Если Ваша система использует диски, общие с файловой системой Atmel File System и другой файловой системой (например EFLS или PetitFS), то Вы должны остановить Atmel File System перед тем, как перейти к использованию другой файловой системой, и заново переинициализировать Atmel File System после того, как вышли из другой файловой системы. Таким образом, чтобы избежать ошибок, нельзя использовать две разные файловые системы одновременно.

Пример: если микроконтроллер Atmel работает в режиме устройства хранения данных (Device MassStorage) USB, то Atmel File System должна быть выключена, чтобы позволить работать файловой системе хоста USB (например, работающего под управлением операционной системы Windows®) с устройством MassStorage.

6.2 Проверка состояния диска

Для проверки диска нужны две подпрограммы:

• nav_drive_set() позволяет детектировать присутствие драйвера памяти (обслуживающий носитель данных).
• nav_partition_mount() проверяет присутствие памяти (носителя данных), и пытается смонтировать раздел (mount partition).

Примечание: количество драйверов памяти может быть динамически меняющимся (например, U-Disk может иметь несколько носителей данных).

Bool check_disk( U8 lun )
{
   nav_select(0); // Выбор navigator ID
   if( !nav_drive_set(lun) )
   {
      //Носитель данных отсутствует
      printf("Driver memory no available\n");
      return FALSE;
   }
   // В этом месте память для хранения выбрана
   
   if( !nav_partition_mount() )
   {
      switch( fs_g_status )
      {
      case FS_ERR_HW_NO_PRESENT:
         //Диск отсутствует
         printf("Disk not present\n");
         break;
      case FS_ERR_HW:
         //Ошибка доступа к диску
         printf("Disk access error\n");
         break;
      case FS_ERR_NO_FORMAT:
         //Диск не форматирован
         printf("Disk no formated\n");
         break;
      case FS_ERR_NO_PART:
         //На диске нет созданных доступных разделов
         printf("No partition available on disk\n");
         break;
      case FS_ERR_NO_SUPPORT_PART:
         //Этот тип раздела не поддерживается
         printf("Partition no supported\n");
         break;
      default:
         //Другая ошибка системы
         printf("Other system error\n");
         break;
      }
      return FALSE;
   }
   // В этом месте память раздела успешно смонтирована,
   // и навигатор находится в корневой директории (root dir).
   
   return TRUE;
}

6.3 Изменение даты/времени файла

В этом примере изменяется дата создания файла и дата последнего изменения.

Bool changedate( void )
{
   // Пример модификации даты файла
   // Date = 12/25/2005 12h30mn10.5s
   const U8 _MEM_TYPE_SLOW_ date_create[]="2005122512301050";
   // Date = 07/23/2006 19h51mn30s
   const U8 _MEM_TYPE_SLOW_ date_write[]="2006072319005130";
   
   nav_select(0); // Для этой последовательности выбран navigator ID 0
   
   if( !nav_drive_set(LUN_ID_NF_DISKMASS))
      return FALSE;
   if( !nav_partition_mount() )
      return FALSE;
   // Выбор первого файла или директории
   if( !nav_filelist_set(0, FS_FIND_NEXT) )
      return FALSE;
   // Модификация даты создания
   if( !nav_file_dateset(date_create, FS_DATE_CREATION) )
      return FALSE;
   // Модификация даты последнего доступа
   if( !nav_file_dateset(date_write, FS_DATE_LAST_WRITE) )
      return FALSE;
   return TRUE;
}

6.4 Использование строкового пути (path string)

Вы можете использовать текстовый путь (в формате ASCII или UNICODE), чтобы получить доступ к нужному файлу или пути. Подпрограмма nav_setcwd() принимает путь в виде строки по следующим правилам (примеры):

• "name" для доступа к файлу или каталогу в пределах текущего каталога
• "nam*" для поиска первого файла или каталога в текущей директории, который удовлетворяет указанной маске имени (wildcard)
• в пути разделители '\' and '/' эквивалентны, и поддерживаются одинаково
• "name\" для поиска каталога в текущем каталоге, и входа в этот каталог
• "name2.txt" для поиска файла в текущем каталоге
• "\name2.txt" для поиска файла в корневом каталоге (root directory)
• обозначение текущего пути в виде "./" поддерживается, но его использование необязательно
• поддерживается навигация на уровни выше "../../"
• поддерживается "A:\", здесь 'A' соответствует disk 0

Bool search_path( void )
{
   const _MEM_TYPE_SLOW_ U8 path[]="dir1/file.txt";
   
   nav_select(0); // Выбор свободного навигатора
   
   // Выбор диска и монтирование его
   nav_drive_set(1);
   nav_partition_mount();
   // В этом месте навигатор находится в корневом каталоге (root dir)
   
#if( (FS_ASCII == ENABLED) && (FS_UNICODE == ENABLED) )
   nav_string_ascii(); // Выбор формата имени ASCII
#endif
   // поиск файла "dir1/file.txt" в текущей директории на disk 1
   if( !nav_setcwd( (FS_STRING)path , TRUE, FALSE ) )
      return FALSE;
   return TRUE;
}

6.5 Ускорение множественной записи (multi-write) файлов

6.5.1 Обзор multi-write

В случае множества вызовов file_write_buf() или file_putc() (например, при выводе в файл лога file), выполнение может замедлиться, потому что количество обращений к диску на запись очень важно для построения таблицы FAT. Если Вы записываете данные в файл несколько раз, и при этом вызовы записи разделены (как с примером записи в лог), то может быть интересным построение таблицы FAT файла более эффективной последовательностью кода.

Каждый вызов подпрограмм file_write_buf() или file_putc() (например, для записи в лог) требует резервирования места в таблице FAT, см. Пример A.

Чтобы увеличить эффективность, Atmel советует создать резервирование необходимого места FAT за одну предварительную последовательность, перед выполнением других команд, см. Пример B. Этот пример даст более эффективную подпрограмму записи. См. раздел 6.5.4.

6.5.2 Пример A

Этот пример показывает обычную последовательность заполнения файла:

Bool fill_file( void )
{
   const UNICODE _MEM_TYPE_SLOW_ name[50]={'l','o','g','.','b','i','n',0};
   U16 u16_nb_write;
   memset(g_trans_buffer, 0x55, FILL_FILE_BUF_SIZE);
   
   if( !nav_drive_set(LUN_DISK) ) // Вход в диск
      return FALSE;
   if( !nav_partition_mount() ) // Монтирование раздела диска
      return FALSE;
   if( !nav_file_create((const FS_STRING)name) ) // Создание файла
      return FALSE;
   if( !file_open(FOPEN_MODE_W) ) // Открыть файл в режиме записи, и принудительно
                                  // задать его размер 0.
      return FALSE;
      
   for( u16_nb_write=0; u16_nb_write<FILL_FILE_NB_WRITE; u16_nb_write++ )
   {
      // Здесь при каждой записи в файл происходит также выделение места 
      // в FAT, и если у нас несколько буферов для записи, то выполнение
      // может замедлиться.
      if( !file_write_buf( g_trans_buffer , FILL_FILE_BUF_SIZE ))
      {
         file_close();
         return FALSE;
      }
   }
   file_close();
   return TRUE;
}

6.5.3 Пример B

Этот пример позволяет ускорить обращения на запись с помощью подпрограммы предварительного выделения.

// Заполнение файла размером > 1MB
#define FILL_FILE_NB_WRITE 855L
#define FILL_FILE_BUF_SIZE 120L
Bool fill_file_fast( void )
{
   const UNICODE _MEM_TYPE_SLOW_ name[50]={'l','o','g','_','f','a','s','t','.','b','i','n',0};
   _MEM_TYPE_SLOW_ Fs_file_segment g_recorder_seg;
   U16 u16_nb_write;
   memset(g_trans_buffer, 0x55, FILL_FILE_BUF_SIZE);
   if( !nav_drive_set(LUN_DISK) ) // Вход в диск
      return FALSE;
   if( !nav_partition_mount() ) // Монтирование раздела диска
      return FALSE;
   if( !nav_file_create( (const FS_STRING) name )) // Создание файла
      return FALSE;
   if( !file_open(FOPEN_MODE_W) ) // Открыть файл в режиме записи, и принудительно
                                  // задать его размер 0.
      return FALSE;
      
   // Определение размера сегмента для prealloc (в единицах 512 байт)
   // Внимание: Вы можете выделить больше памяти в случае, когда не знаете
   // общий размер.
   g_recorder_seg.u16_size = (FILL_FILE_NB_WRITE*FILL_FILE_BUF_SIZE + 512L)/512L;
   // ****PREALLLOC****** сегмент для заполнения
   if( !file_write(&g_recorder_seg) )
   {
      file_close();
      return FALSE;
   }
   
   // Проверка размера выделенного сегмента
   if( g_recorder_seg.u16_size < ((FILL_FILE_NB_WRITE*FILL_FILE_BUF_SIZE + 512L)/512L) )
   {
      file_close();
      return FALSE;
   }
   // Закрыть/открыть файл, чтобы сбросить его размер
   file_close(); // Закрывает файл. Эта подпрограмма не удаляет предыдущее выделение.
   if( !file_open(FOPEN_MODE_W) ) // Открыть файл в режиме записи, 
                                  // что сбросит его размер в 0
      return FALSE;
   for( u16_nb_write=0; u16_nb_write<FILL_FILE_NB_WRITE; u16_nb_write++ )
   {
      // В этом месте список кластеров файла уже выделен и подпрограмма записи
      // будет работать быстрее.
      if( !file_write_buf( g_trans_buffer, FILL_FILE_BUF_SIZE) )
      {
         file_close();
         return FALSE;
      }
   }
   file_close();
   return TRUE;
}

6.5.4 Статистика использования

Вот результаты работы следующего примера (можно наглядно увидеть, насколько оптимальнее работает Пример B):

Создание файла 100.2 килобайта (буфер 120 байт * количество записей 855) на диске 256 мегабайт (размер кластера FAT16 4 килобайта):

• С примером A, количество обращений на запись в тот же самый сектор FAT 50 раз максимум и в среднем 25 раз.
• С примером B, количество обращений на запись в тот же самый сектор FAT 2 раза максимум и в среднем 1 раз.

Создание файла 1.1 мегабайта (буфер 120 байт * количество записей 10000) на диске 256 мегабайт (размер кластера FAT16 4 килобайта):

• С примером A, количество обращений на запись в тот же самый сектор FAT 255 раз максимум и в среднем 147 раз.
• С примером B, количество обращений на запись в тот же самый сектор FAT 2 раза максимум и в среднем 1 раз.

Внимание: важно знать, что время создания FAT зависит от используемого типа FAT. Выделение пространства FAT работает быстрее в FAT12 и FAT16, чем в FAT32. Если у Вас размер диска < 2 гигабайт, то Вы можете принудительно использовать обычный FAT (FAT12 и FAT16), когда вызываете nav_drive_format(FS_FORMAT_FAT). Формат FAT32 требует для записи большее количество (в 4 раза) секторов в таблице FAT, чем FAT16, для того же самого размера файла и того же самого размера диска.

6.6 Копирование диска на другой диск

Этот пример использует 3 навигатора (navigator handle):

• для просмотра диска-источника (source disk)
• для просмотра диска-назначения (destination disk)
• для фичи copy/paste, navigator задан как FS_NAV_ID_COPYFILE в заголовке conf_explorer.h

Bool copydisk( void )
{
   const UNICODE _MEM_TYPE_SLOW_ name[50];
   U8 u8_folder_level = 0;
   
//trace("Монтирование драйва\n");
   //** Используется 3 навигатора: 
   // 0 для просмотра диска-источника SD (стандартная карта SD)
   // 1 для просмотра диска-назначения NF (носитель NandFlash)
   // 2 используется подпрограммой копирования файла
   nav_select( 0 );

   if( !nav_drive_set(LUN_ID_MMC_SD) )
      return FALSE;
   if( !nav_partition_mount() )
      return FALSE;
   nav_select( 1 );
   if( !nav_drive_set( LUN_ID_NF_DISKMASS ))
      return FALSE;
   if( !nav_partition_mount() )
      return FALSE;

   // Цикл для сканирования и создания ВСЕХ папок и файлов
   while(1)
   {
      // В текущем каталоге нет каталогов, так что переход в родительский
      // каталог дисков SD и NandFlash
      while(1)
      {
//trace("Поиск файлов в каталоге\n");
         // Выбор SD заново
         nav_select( 0 );
         if( nav_filelist_set( 0 , FS_FIND_NEXT ) )
            break; // найден следующий файл и каталог

         // В текущем каталоге нет других каталогов или файлов, так что
         // делается переход на родительский каталог дисков SD и NandFlash.
         if( 0 == u8_folder_level )
         {
            // конец обновления каталога
//trace("End of copy\n");
            return TRUE; //********* КОПИРОВАНИЕ ОКОНЧЕНО **************
         }

//trace("Перейти в родительскую папку\n");
         // Пометка: подпрограмма nav_dir_gotoparent() переходит в родительский каталог
         // и выбирает дочерний каталог в списке
         u8_folder_level--;
         if( !nav_dir_gotoparent() )
            return FALSE;
         // Выбор навигатора NandFlash, и переход в тот же самый каталог, что и на SD
         nav_select( 1 );
         if( !nav_dir_gotoparent() )
            return FALSE;
      } // конец while (1)
      
      if( nav_file_isdir())
      {
//trace("Найден каталог - создание каталога & и переход в него (CD)\n");
         //** В этом месте найден и выбран новый каталог
         // Получение имени текущего выбора (= имени каталога на SD)
         if( !nav_file_name( (FS_STRING)name, 50, FS_NAME_GET, FALSE) )
            return FALSE;
         // Войти в каталог (на SD)
         if( !nav_dir_cd() )
            return FALSE;
         u8_folder_level++;
         // Выбор диска NandFlash
         nav_select( 1 );
         // Создание каталога на диске NandFlash
         if( !nav_dir_make((FS_STRING)name) )
         {
            if( FS_ERR_FILE_EXIST != fs_g_status )
               return FALSE;
            // в этом месте ошибка, такое имя уже есть
         }
         // В этом месте навигатор выбрал каталог на NandFlash
         if( !nav_dir_cd() )
         {
            if( FS_ERR_NO_DIR == fs_g_status )
            {
               // FYC -> копирование невозможно, потому что имя файла совпадает 
               // с именем каталога
            }
            return FALSE;
         }
         // здесь каталог создан, и навигаторы вошли в этот каталог
      }
      else
      {
//trace("Файл найден - копирование файла\n");
         //** Здесь найден и выбран новый файл
         // Получение имени текущего выбора (= имени файла на SD)
         if( !nav_file_name((FS_STRING)name, 50, FS_NAME_GET, FALSE) )
            return FALSE;
         if( !nav_file_copy() )
            return FALSE;
         // Вставить (PASTE) файл в текущий каталог диска NandFlash
         nav_select( 1 );
         while( !nav_file_paste_start((FS_STRING)name) )
         {
            // Ошибка
            if( fs_g_status != FS_ERR_FILE_EXIST )
               return FALSE;
//trace("удаление файла\n");
            // Файл существует, тогда он будет удален
            if( !nav_file_del( TRUE ) )
               return FALSE;
            // здесь снова попробуем вставить (retry PASTE)
         }
         // Запуск копирования
         {
            U8 status;
            do{
               status = nav_file_paste_state(FALSE);
            }while( COPY_BUSY == status );
            if( COPY_FINISH != status )
               return FALSE;
         }
      } // если каталог или файл
   } // конец внешнего while(1)
}

[Ссылки]

1. AVR114: Using the ATMEL File System management for AT32UC3x, AT90USBx and ATmega32U4 site:atmel.com.
2. Библиотека EFSL.
3. Библиотека FatFS: модуль файловой системы FAT.
4. Библиотека Petit FatFS: модуль файловой системы FAT.
5. Макетные платы с интерфейсом USB.
6. AVR115: сбор данных с использованием Atmel File System

 

Добавить комментарий


Защитный код
Обновить

Top of Page