Библиотека FatFS: appnotes, указания по использованию |
Добавил(а) microsin | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
В этой статье собраны общие рекомендации и указания, как использовать в своих проектах библиотеку FatFS.
[Как портировать библиотеку FatFS на другие платформы] Основные замечания Для модуля FatFs имеются следующие условия для портирования.
Функции, которые могут понадобиться для портирования Вам необходимо предоставить только низкоуровневые функкции ввода/вывода диска (low level disk I/O), необходимые для модуля FatFs, и ничего более. Если рабочий модуль диска для Вашей платформы уже есть, то нужно написать только функции склейки, чтобы подключить их к модулю FatFs. Если такого модуля нет, то нужно портировать любой уже имеющийся дисковый модуль или написать его с нуля. Не всегда нужно реализовывать все функции их списка дискового модуля. Например, функция записи не нужна для конфигурации только для чтения (read-only). Следующая таблица показывает, какие функции нужны в зависимости от выбранных опций конфигурации.
[Использование/расход памяти - Memory Usage (R0.09)]
В таблице перечислены примеры расхода памяти на некоторых целевых системах при соответствующих указанных условиях. Объем памяти указан в байтах, V обозначает количество смонтированных томов, и F означает количество открытых файлов. Все примеры при компиляции оптимизированы на размер генерируемого кода (optimezed in code size). Ниже перечислены опции конфигурации FatFS для этих примеров. _FS_READONLY 0 (R/W), 1 (R/O) _FS_MINIMIZE 0 (полный функционал), 3 (минимизированный функционал) _USE_STRFUNC 0 (запрещены строковые функции) _USE_MKFS 0 (запрет функции f_mkfs) _USE_FORWARD 0 (запрет функции f_forward) _USE_FASTSEEK 0 (запрет возможности быстрого позиционирования fast seek) _CODE_PAGE 932 (кодовая страница Japanese Shift-JIS) _USE_LFN 0 (зепрещены длинные имена LFN) _MAX_SS 512 (фиксированный размер сектора) _FS_RPATH 0 (запрет отностительных путей) _VOLUMES D (количество используемых логических дисков) _MULTI_PARTITION 0 (один раздел на драйв - Single partition per drive) _FS_REENTRANT 0 (запрет реэнтрантности - reentrancy) _FS_SHARE 0 (запрет контроля совместного использования файлов - sharing control) [Сокращение размера модуля библиотеки] Следующая таблица показывает, какие функции API будут удалены соответствующими опциями конфигурации - для уменьшения размера кода модуля FatFS.
[Длинное имя файла (Long File Name, LFN)] Модуль FatFs терерь поддерживает длинные имена файлов и папок (LFN), начиная с ревизии 0.07. Два различных имени файла, SFN (Short File Name, короткое имя файла) и LFN (Long File Name, длинное имя файла) - являются прозрачными для вызовов файловых функций, за исключением функции f_readdir. Для разрешения возможности LFN нужно установить опцию _USE_LFN в значение 1, 2 или 3, и добавить в проект функции преобразования Unicode - ff_convert() и ff_wtoupper(). Включенная возможность поддержки LFN требует некоторой дополнительной памяти для рабочего буфера. Размер буфера можно сконфигурировать опцией _MAX_LFN - в соответствии с имеющимся количеством доступной памяти. Размер длинного имени может достигать до 255 символов, при этом _MAX_LFN должна быть установлена в значение 255 (полнофункциональная поддержка LFN). Если размер рабочего буфера недостаточен для предоставленного имени файла, то файловая функция завершится с кодом ошибки FR_INVALID_NAME. Когда опция LFN включена вместе с опцией реэнтрантности (re-entrant feature), то опция _USE_LFN должна быть установлена в 2 или 3. В этом случае файловая функция выделяет рабочий буфер в стеке или в куче heap. Рабочий буфер занимает (_MAX_LFN + 1) * 2 байт.
Когда включена опция LFN, размер кода модуля увеличится в зависимости от выбранной кодовой страницы. Таблица справа показывает на некоторых кодовых страницах (кодировках имен), сколько байт кода нужно дополнительно, когда возможность LFN включена. Жители Восточной Азии имеют десятки тысяч символов. К сожалению, это требует огромной таблицы для двунаправленного преобразования OEM-Unicode, и размер модуля значительно увеличится, что отображено в таблице. Как следствие, FatFs с включенной возможностью LFN, с DBCS не может быть реализована на большинстве 8-битных микроконтроллеров. Это одна из причин, по которой автор библиотеки длительное время не был заинтересован в реализации LFN. Внимание! Когда включена опция LFN (разрешены длинные имена, в файле ff.h задано #define _USE_LFN 1), поля lfname и lfsize в структуре FILINFO должны быть предварительно инициализированы до вызова функций, использующих переменную типа FILINFO (например, переменную FILINFO использует функция f_stat). Поле lfname является указателем на буфер, в котором будет сохранена строка с длинным именем файла. Поле lfsize содержит размер для этого буфера строки, указанный в единицах TCHAR. Этот указатель должен указывать на валидный буфер в RAM, иначе все функции, которые используют переменную FILINFO (например f_stat) могут привести к непрогнозированному поведению программы (обычно Data Abort или зависание). Кроме того, для доступа к файлам даже при включенных длинных именах нужно использовать короткое имя файла (поле fname), так как если имя файла по размеру меньше 8.3, то длинное имя будет пустым (0 == strlen(lfname)). Для дополнительной информации см. также описание функции f_readdir. Пример кода, где есть инициализация полей lfname и lfsize, дан в описании функции f_stat. Имейте в виду, что возможность LFN на файловой системе FAT запатентована корпорацией Microsoft. Не так обстоит дело с FAT32. Когда в коммерческих продуктах разрешена опция LFN, может потребоваться лицензия от Microsoft - в зависимости от места применения. API библиотеки FatFS поддерживает по умолчанию кодировку ANSI/OEM, однако FatFS можно также переключить в поддержку кодировки Unicode. Для более подробной информации см. описание системы именования файлов FatFS. [Re-entrancy (повторный вход в процедуру, реэнтрантность)] Операции с файлами на разных томах всегда являются реэнтрантными и могут работать одновременно. Файловые операции на одном и том же томе по умолчанию не реэнтрантные, однако это можно сконфигурировать для потокозащищенного режима (thread-safe) опцией _FS_REENTRANT. Для этого случая нужны также зависящие от операционной системы функции управления объектом синхронизации - ff_cre_syncobj, ff_del_syncobj, ff_req_grant и ff_rel_grant, которые должны быть добавлены в проект. Когда файловая функция вызвана на томе, который используется любой другой задачей, файловая функция будет приостановлена (suspended) до того момента, пока другая задача не освободит файловую функцию. Если время ожидания превысит период, заданный опцией _TIMEOUT, то файловая функция оборвет выполнение с ошибкой FR_TIMEOUT. Возможность отслеживания таймаута может не поддерживаться на некоторых RTOS (Real Time OS, операционная система реального времени). Для функций f_mount и f_mkfs есть исключение. Эти функции не реэнтрантные на одном и том же томе. Когда используются эти функции, то все остальные задачи должны закрыть соответствующие файлы на томе и избегать доступа к этому тому. Имейте в виду, что эта секция описывает реэнтрантность модуля FatFs самого по себе, однако низкоуровневые дисковые функции слоя ввода/вывода (low level disk I/O) должны быть также реэнтрантными. [Двойной доступ к файлу (Duplicated File Access)] Модуль FatFs по умолчанию не поддерживает управление одновременным доступом к файлу. Это разрешается когда файл открыт только в режиме чтения. Двойное открытие файла в режиме записи всегда запрещено, и открытый файл не должен быть переименован или удален, иначе стуктура FAT тома может быть испорчена. Управление совместным доступом может быть доступно, когда опция _FS_SHARE установлена в 1 или бОльшее значение. Это значение указывает количество файлов, которые могут быть обработано одновременно. Когда совместный доступ разрешен, то любая попытка нарушения совместного доступа при открытии (open), переименовании (rename) или удалении (remove) приведет к завершению файловой функции с ошибкой FR_LOCKED. Если количество открытых файлов превысит _FS_SHARE, то функция f_open function завершится с ошибкой FR_TOO_MANY_OPEN_FILES. Для получения хорошей производительности чтения/записи файлов на малых встраиваемых системах разработчик firmware должен представлять себе, как происходит этот процесс в модуле FatFs. Данные файла на диске передаются внутри f_read в следующей последовательности (см. рисунки 1..3). Рис. 1. Чтение сектора в случае отсутствия выравнивания (короткое) - Sector miss-aligned read (short) Рис. 2. Чтение сектора в случае отсутствия выравнивания (длинное) - Sector miss-aligned read (long) Рис. 3. Чтение сектора при выравнивании - Sector aligned read Файловый буфер ввода/вывода (file I/O buffer) означает буфер сектора для чтения/записи блока данных на секторе. Буфер сектора может быть либо отдельным для каждого файлового объекта (file object, т. е. файл), или общий используемый буфер сектора, привязанный к объекту файловой системы (file system object). Опция конфигурации _FS_TINY определяет, какой буфер сектора используется для передачи данных файла. Когда выбран маленький буфер - tiny buffer (1), затраты памяти уменьшаются до 512 байт на каждый файловый объект. В этом случае модуль FatFs использует только буфер сектора объекта файловой системы для передачи данных и доступа к каталогу FAT/директориям. Недостаток конфигурации tiny buffer следующая: данные FAT кешируются в буфере сектора, и они должны быть потеряны при передаче данных файла и должны быть перезагружены на каждой границе кластера. Однако такое решение может подойти для большинства приложений с точки зрения незначительного снижения производительности при значительном экономии расхода памяти. Рис. 1 показывает блок данных сектора передается через буфер I/O. На длинных передачах, как показано на рис. 2, промежуточные передаваемые данные (соответствующие одному или нескольким секторам) попадают напрямую в буфер приложения. Рис. 3 показывает случай, когда передаваемые данные выровнены на границу сектора. В этом случае, буфер I/O файла не используется. На прямой передаче максимальное количество секторов будет прочитано функцией disk_read за один раз, однако если мультисекторная передача не пересекает границу кластера, даже если кластеры идут непрерывно друг задругом. Поэтому если взять на вооружение выровненный по секторам доступ на чтение/запись, которое позволяет избежать буферизированную передачу данных, то быстродействие чтения/записи возрастет. Помимо этого эффекта, кешированные данные FAT не будут сбрасываться (flush) при передачи данных файла в конфигурации tiny, так что может быть достигнута та же производительность, как и в не tiny конфигурации, причем с малыми затратами памяти. [Носители памяти Flash (Flash Memory Media)] Чтобы добиться максимальной производительности записи на физическом носителе flash, таких как SDC и CFC, эти носители должны управляться в соответствии с их характристиками. Использование многосекторной записи (Mutiple-Sector Write) Рис. 6. Сравнение методов записи - многосекторная и односекторная (Multiple/Single Sector Write)Пропускная способность носителей памяти flash ухудшается при одиночном записи сектора (single sector write) и увеличивается пропорционально количеству секторов на одну транзакцию записи. Этот эффект сильнее проявляется на шине с высокой тактовой частотой и скорость часто возрастает больше чем в 10 раз. Количество транзакций записи также влияет на время жизни носителя памяти (life time). Таким образом, программа приложения должна осуществлять запись блоками как можно бОльшего размера - чем блок больше, тем лучше. Идеальный размер блока равен размеру кластера, или степени числа 2 байт, и байтовое смещение дожно быть выровнено по границе блока. Само собой, все слои между программой приложения и физическим носителем должны поддерживать возможность многосекторной записи, однако в большинстве случае open-source драйверы диска не уделяют этому достаточное внимание. Не разделяйте зароос на многосекторную запись на одиночные записи секторов, иначе получите плохую скорость записи. Обратите внимание, что модуль FatFs и сопутствующий пример драйверов диска поддерживают многосекторные чтение/запись. Принудительная очистка памяти (Forcing Memory Erase) Когда происходит удаление файла с помощью функции f_remove, то кластеры, в которых были записаны данные удаленного файла, помечаются как свободные (free) в каталоге FAT. Однако секторы данных, содержащие в себе данные файла, не прикладываются к любому процессу, так что данные остаются занятыми на носителе данных как live blocks. Если данные будут принудительно стерты (erased) при удалении файла, то количество свободных блоков на носителе увеличится. Эту операцию очистки можно опустить до момента следующей записи, тогда в этот момент при записи сработает внутренняя операция очистки блока. Если установить принудительную очистку при удалеAs the result the write performance might be improved. To enable this feature, set _USE_ERASE to 1. Note that this is a feature with expectation of internal process of the flash memory media. It may not always effective and f_remove function will take a time on removing a large file. [Критическая секция кода (Critical Section)] Если операция записи на файловой системе FAT прервана по причине любой случайной ошибки (такой как выключение питания, некорректное извлечение диска или невосстановимая ошибка диска), то структура FAT может быть повреждена. На рисунках ниже показаны критические секции приложения, использующего библиотеку FatFs.
Прерывание в красной области может вызвать перекрестную ссылку (cross link); в результате изменяемый объект может быть потерян. Возможен один или более вариантов, перечисленных ниже, когда прерывание возникает в желтой области.
Все перечисленные случаи не влияют на файлы, которые открыты не в режиме записи. Чтобы уменьшить риск потери данных, критические секции можно минимизировать, как показано на рис. 5 - путем уменьшения времени, когда файл находится в режиме записи, или путем правильного использования функции f_sync. [О лицензировании библиотеки FatFs] Это копия лицензии FatFs, которая включена в исходные коды библиотеки. /*----------------------------------------------------------------------------/ / FatFs - FAT file system module R0.09 (C)ChaN, 2011 /-----------------------------------------------------------------------------/ / FatFs module is a generic FAT file system module for small embedded systems. / This is a free software that opened for education, research and commercial / developments under license policy of following trems. / / Copyright (C) 2011, ChaN, all right reserved. / / * The FatFs module is a free software and there is NO WARRANTY. / * No restriction on use. You can use, modify and redistribute it for / personal, non-profit or commercial products UNDER YOUR RESPONSIBILITY. / * Redistributions of source code must retain the above copyright notice. / /-----------------------------------------------------------------------------/ Перевод лицензии: "FatFs - модуль файловой системы FAT, версия R0.09 (C)ChaN, 2011. Модуль FatFs является программным модулем обычной файловой системы FAT, предназначенным для малых встраиваемых систем на микроконтроллерах. Это свободное программное обеспечение, которое открыто для обучения, исследования и коммерческих разработок при условии соблюдения следующих правил. Все права на библиотеку FatFs принадлежат ChaN. На эту библиотеку НЕ ДАЕТСЯ НИКАКИХ ГАРАНТИЙ. Нет ограничений на использование. Вы можете использовать и распространять код библиотеки для персональных, некоммерческих или коммерческих продуктов ПОД ВАШЕЙ СОБСТВЕННОЙ ОТВЕТСТВЕННОСТЬЮ. Распространяемый исходный код библиотеки должен содержать в себе указанные выше лицензионные замечания.". Таким образом, лицензия FatFs является одной из разновидностей лицензии BSD, однако есть одно большое отличие. Поскольку FatFs предназначена для встраиваемых проектов, то условия распространения в двоичной форме (такой как встраиваемый код, HEX-файл или двоичная библиотека) не определены с целью увеличения удобства использования. Документация дистрибутивов может как включать в себя FatFs и её лицензионный документ, так и не включать его. Разумеется, лицензия FatFs совместима с проектами, выпущенными под защитой лицензии GNU GPL. Когда библиотека распространяется с любой модификацией, лицензия может быть также изменена на GNU GPL или лицензию BSD-стиля. [Ссылки] 1. FatFs Module Application Note - указания по применению библиотеки FatFs (оригинал статьи на английском языке). |