File System

Do you have a question? Post it now! No Registration Necessary

Translate This Thread From Russian to

Threaded View
Hi All,

 В EEPROM с байтовым доступом надо хранить произвольное количество структур,
 описывающих разные устройства. Структуры имеют различный размер порядка
 десятков байт. Устройства могут добавляться и удаляться. То есть нужна
 файловая система, такая, чтобы:

 1. Достаточно простая.
 2. Достаточно быстрая.
 3. Достаточно эффективная по полезному обьему.
 4. Устойчивая к пропаданию питания в произвольный момент.
 5. Hе протирающая дырки в EEPROM.
 
 У меня есть некоторые мысли, как это сделать, однако не хотелось бы
изобретать
 велосипед и наступать на общеизвестные грабли.
 Было бы интересно послушать советы людей, решавших подобную задачу.

 VLV

"Тост: За лучшего из хоббитов - Гарри Поттера"  (c) Пелевин


File System
On 02/May/04 at 16:21 you write:

 VV>  В EEPROM с байтовым доступом надо хранить произвольное
 VV> количество структур, описывающих разные устройства. Структуры имеют  VV>
 VV> различный размер порядка десятков байт. Устройства могут добавляться и
 VV> VV> удаляться.

 а почему не использовать обычные алгоритмы динамического распределения памяти
mallocal/realloc/free ?

PS: кстати, откуда бы выдернуть готовые исходники этих функций на С ?


File System
Sun May 02 2004 20:53, Dmitry Ponyatov wrote to Vladimir Vassilevsky:

 
 VV>>  В EEPROM с байтовым доступом надо хранить произвольное
 VV>> количество структур, описывающих разные устройства. Структуры имеют  VV>
 VV>> различный размер порядка десятков байт. Устройства могут добавляться и
 VV>> удаляться.

 DP>  а почему не использовать обычные алгоритмы динамического распределения
 DP> памяти mallocal/realloc/free ?

 1. Потому, что они работают с непрерывными кусками и не умеют
фрагментировать.
 2. Потому, что пропадание питания в плохой момент полностью разрушит
    всю структуру данных.
 3. Потому, что они двигают блоки в памяти, что неприемлемо для EEPROM.

 DP> PS: кстати, откуда бы выдернуть готовые исходники этих функций на С ?

 Есть в комплекте IAR EC++ и вообще любого приличного компилятора.

 VLV

"Тост: За лучшего из хоббитов - Гарри Поттера"  (c) Пелевин


File System
On 02/May/04 at 20:41 you write:

 VV>  3. Потому, что они двигают блоки в памяти, что неприемлемо для
 VV> EEPROM.

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


File System
    Hello, Vladimir!

Вcк Май 02 2004, Vladimir Vassilevsky писал к All по  поводу "File System."
 VV>  В EEPROM с байтовым доступом надо хранить произвольное количество
 VV> структур, описывающих разные устройства. Структуры имеют различный
 VV> размер порядка десятков байт. Устройства могут добавляться и
 VV> удаляться. То есть нужна файловая система, такая, чтобы:

 VV>  1. Достаточно простая.
 VV>  2. Достаточно быстрая.
 VV>  3. Достаточно эффективная по полезному обьему.
 VV>  4. Устойчивая к пропаданию питания в произвольный момент.
 VV>  5. Hе протирающая дырки в EEPROM.

Я делал так:

1) root - 16 байт на запись, число записей фиксированно, определяется числом
файлов максимально возможных в системе + запас на исправляемые глюки. Структура
записи:
1a) Символическое имя файла (8 байт). Если 1-й байт FF - структура чистая!
1b) Индекс файла (2 байта) (в системе возможно не более 65536 файлов)
1с) Длинна файла в байтах (4 байта) (может и 2 если файлы маленькие).
1d) CRC16 этой строки (2 байта опционально).

Как вариант можно увеличить структуру до 32 байт, тут главное, чтоб при записи
попадать в странички, тогда имя файла может быть до 24 байт, но как правило
такое не надо в embedded (хотя 1 раз я делал). Hелишне добавить время записи
файла (если в системе есть RTC). Причем время лучше брать как dword секунд с
скажем 2004 года.

Вся память EEPROM не входящая в root делится на кластеры произвольного размера
кратного 16 байт (рекомендуется не менее 128 байт). Размер может быть
увеличен. Число кластеров строго фиксированно и определяется размером памяти.

Структура кластера:
2a) Признак действительности, 1 байт (0A5h используется, 0ffh чистый).
2b) Индекс файла которому принадлежит кластер (2 байта).
2c) Порядковый номер кластера в файле c нуля (2 байта).
2d) Поле данных (128-2-2-1-2)
2e) crc16 для кластера (опционально для контроля).

Функции EFS:

Открытие файла для чтения - open_file:
Передаем строку символического имени.

Ищем в ROOT символическое имя файла, просматривая ее побайтно, при несовпадении
сразу прыгаем на 16 байт вперед, при совпадении читаем индекс и длинну файла
(проверяем валидность строки если надо). При этом создаем блок управления
файлом в озу (число блоков фиксированно и определяется необходимостью иметь
некоторое количество одновременно открытых файлов).
Возвращаем "file not found" если записи нет.

Структура блока управления файла:
1a) Имя файла. (00 или ff -  блок управления не используется).
1b) Индекс файла.
1c) Длинна файла.
1d) Текущая позиция записи/чтения (при открытии сбрасывается в 0).
1e) Признак чтения/записи.
1f) Физический номер сектора (только для записи).

Возвращаем в программу индекс блока управления если запись найденна.

Чтение файла - read_from_file:

Передаем индекс блока управления, число байт для чтения, и адрес буфера.

Из указанного блока берем позицию чтения, и делим ее на длинну поля данных в
кластере, таким образом получаем номер кластера. Остаток от деления умноженный
на длинну поля данных определяет смещение в кластере, вобщем тут все должно
быть понятно...

Сканируя eeprom с шагом = "размер кластера" на предмет совпадения признаков:
используемый кластер+наш индекс файла + нужный номер кластера, найдя проверяем
поле данных (CRC опционально) , считываем его в буфер (в соответствии с
длинной), если блок больше, чем поле данных в кластере - увеличиваем позицию
чтения на размер поля данных, уменьшаем "число байт для чтения" на размер поля
данных. (если EEPROM - I2C удобно читая по байтику (естественно адрес только в
начале) увеличивать и уменьшать счетчики на 1-ку и проверять на 0 и "длинну
файла". Затем ищем следующий кластер нашего файла. При этом поиск cледующего
производится от текущей позиции кластера вперед и далее по кругу. Возвращаем
"out of range" если позиция чтения выходит за пределы файла или кластер по
каким-то причинам не найден.

Закрытие файла для чтения: close_file:
Hа входе передаем индекс блока управления.
Уничтожаем блок управления обнуляя 1-й байт если для него установлен признак
"чтение"!

Создание файла или перезапись существующего: create_file
Передаем имя файла.

При этом создается блок управления с признаком "запись". Заполняется имя файла.
Длинна и позиция записи устанавливается в 0.

Определяется кластер для записи, для этого RANDOM значение берется по модулю
"количество кластеров в системе", от этой точки производится сканирование
вперед для поиска пустого кластера, при нахождении первого пустого кластера его
физический номер помещается в переменную "физический номер кластера" блока
управления (перед этим необходимо проверить все другие активные блоки
управления на предмет, что данный кластер они не используют как свой текущий).
Такой замут нужен для размазывания файлов по всей области EEPROM и таким
образом повышения ее ресурса.

Сканируется весь ROOT а так-же все блоки управления файлами с признаком
"запись" на предмет поиска неиспользуемого в системе файлового индекса, как
только таковой найден - он помещается в поле "индекс файла". Если все 65536
индексов используются - возврат с соответствующей ошибкой (слишком много
файлов).

Если все ок - возвращается номер блока управления.

Запись блока в файл: write_file:

Передается - номер блока управления, адрес буфера, число байт для записи.

Определяется текущее состояние записи, путем деления позиции записи на "длинну
области данных в кластере" определяется номер кластера в файле. Cоздается буфер
в 128 байт и записывается кластер, если число байт для записи превышает размер
поля данных -  программа ищет следующий свободный кластер
(просмотр вперед), и пишет его.  Как вариант обработка ошибок типа "memory
full"... Вобщем тут все должно быть понятно.


Закрытие файла для записи: close_file

Передается - индекс блока управления.

1) Текущая позиция файла становится его длинной.

2) Random взятый по модулю "число записей ROOT" становится отправной точкой для
поиска первой пустой записи в ROOT. После нахождения пустой записи ее позиция
запоминается. И производится физическая запись поля "ROOT" на основе блока
управления. Завершение этой записи делает файл существующим в системе.

3) Сканируются все записи ROOT на предмет поиска имени файла совпадающего с
нашим, (только что записанная игнорируется, так как ее позицию мы запомнили).
При нахождении такой записи из нее читается индекс файла, а сама запись
физически уничтожается (1 байт = ff). Cканируются все кластеры по признаку:
используемый кластер (1 байт = a5) & наш индекс файла, все найденные кластеры c
такими признаками высвобождаются (1 байт=ff).  (Точно так-же работает функция
erase_file).

Глюки питания могут влиять только в пунктах между 3-4. Поэтому надо обратить на
них особое внимание и возможно оптимизировать или сократить по времени, или
добавить в устройство логику аварии питания. Весь момент записи до close_file в
системе сущетсвуют как-бы 2 файла, старый и новый, если выключить питание
старый неповрежденные так и останется, а все, что удалось записать в новый
окажется в "lost clusters".

4) Блок управления файлом высвобождается (1-й байт = 00).

Антиглюкаторная логика:

Память постоянно либо время от времени либо при включении сканируется на
предмет:

1) Поиска в ROOT записей с одинаковым именем, при этом если в системе есть RTC
не плохо бы время записи файла сохранять в памяти, и по этому признаку удалять
старую запись, если вдруг какой либо файл сдупится (глюки 3 пункта close_file).
Либо придумать логику выкидывания дупов на основании данных или CRC файлов.

2) Поиска файловых индексов, которые явным образом заняты в кластерах, но
отсутствуют в активных в сстеме блоках управления файлами или в записях ROOT.
Такие кластеры считаются потерянными и стираются (первый байт=ff). Возникают
они при аварии питания в точке когда файл фактически записан но не закрыт.

 VV>  VLV
  WBR!  Maxim Polyanskiy.


Site Timeline