
Файловая система во встраиваемых решениях — критическое звено. От её выбора зависят надёжность, детерминированность и задержки всей системы.
В типичном устройстве она обслуживает запись сигналов, ресурсы для дисплеев и аудиовоспроизведения, логи, файлы веб‑интерфейса и многое другое.
На практике всплывают одни и те же проблемы: дефрагментация, высокое потребление RAM, плохая детерминированность (плавающие задержки), неустойчивость к сбоям записи/питания и низкая скорость. Нередко корнем оказываются драйверы из SDK производителей чипов: они не оптимизированы для многозадачной среды и часто недоработаны под OSPI.
Я протестировал четыре файловые системы на платформе MC80 с внешней OSPI NOR Flash и разработал специализированный драйвер вместо стандартного из FSP — с полноценной поддержкой OSPI и RTOS.
Вот схема подключения OSPI NOR Flash на плате MC80

Остальная информация в статьях :
Что сравниваем
Рассмотрим четыре популярные файловые системы для малых встраиваемых систем — то есть для микроконтроллеров без MMU:
FileX совместо с LevelX;
LittleFS;
YFFS2;
STFs;
Небольшая сводка
FileX + LevelX (Azure RTOS)
Тип: блочная FAT32; exFAT. LevelX — слой выравнивания износа для NOR/NAND.
Плюсы: совместимость с FAT и USB MSD (может работать как USB диск), готовая интеграция с RTOS ThreadX. Есть опция журналирования для защиты от сбоев записи и питания.
Минусы: Без LevelX на Flash надежно работать не будет. Но это добавляет задержки. Требует кэша секторов, желательно нескольких.
LittleFS
Тип: гибридная блочно-журналируемая для NOR Flash. Особо позиционируется как устойчивая к сбоям записи и питания.
Плюсы: Встроенное выравнивагие износа, в RAM нужен только кэш размером с сектор, и два буфера размером со страницу. Быстрая инициализация.Не использует динамическую память.
Минусы: Плохо детеминирована. Большие непредсказуемые задержки. Нет интеграции с RTOS. Нет доступа через USB MSD.
YFFS2
Тип: журналируемая (log-structured) с поддержкой контроля целостности данных через ECC (Error-Correcting Code). Позиционируется как заточенная для NAND Flash, но отлично работает и с NOR Flash
Плюсы: высокая устойчивость к сбоям, быстрая инициализация. ECC для NOR может быть отключен.
Минусы: Большое потребление RAM, сильно зависящее от объема NOR Flash и гранулированности страниц. Требует явной периодической дефрагментации. Дефрагментация усложнена стратегиями. Нет интеграции с RTOS. Активно использует динамическую память. В варианте для микроконтроллеров нет доступа через USB MSD.
Тип: журналируемая, пригодна для организации файловой системы прямо во Flash памяти микроконтроллеров в особенности семейства STM32H.
Плюсы: устойчивость к сбоям, автоматическое выравнивание износа, высокий детерминизм, работает с Flash с неоднородными размерами секторов, минимальная деградация скорости по сравнению с сырой записью во Flash. Самое низкое потребление RAM. Не использует динамическую память. Простая интеграция с RTOS.
Минусы: отсутствуют директории. Требует явной периодической дефрагментации. Дефрагментация выполняться может дольше минуты. Нет доступа через USB MSD.
Драйвер для MX25UM25645GMI
В стандартной поставке FSP для микроконтроллеров семейства RA8 есть обобщённый драйвер для SPI-Flash. Он включает вариант протокола для 8-битного режима. Однако, как оказалось, разработчики не реализовали для этого режима команды стирания. При этом главная проблема, характерная для драйверов из SDK производителей чипов, — отсутствие полноценной поддержки RTOS. Из-за этого такие драйверы обычно уходят в длительные циклы программного опроса сигналов. Подобная реализация неприемлема для систем реального времени, поскольку может приводить к простоям задач всей системы управления на, казалось бы, невинных файловых операциях.
Исходный драйвер был перереботан очень серьезно. Исходники — здесь.
Однако за разочарованием от качества драйверов последовало ещё одно — периферия тоже может подвести. По даташиту MX25UM25645G кажется, что при частоте 200 МГц и 8-битной шине память должна выдавать на чтении около 200 МБ/с. На практике выяснилось, что OSPI-интерфейс в RA8 c DMA вставляет ~10 мкс паузы между 64-байтными пакетами чтения, что резко снижает пропускную способность. Прежде чем признать это ограничением платформы, я реализовал в драйвере три режима чтения: (1) по «ручным» командам OSPI, (2) прямое чтение из отображённого адресного пространства Flash, (3) то же, но через DMA.
Для исследования работы OSPI Flash разработан терминальный модуль, с которым можно работать по USB через любую терминальную программу. Вот этот.

Здесь, помимо OSPI, можно проводить и многие другие тесты. Не забываем, что MC80 — боевая платформа для реальных приложений, а не для лабораторных исследований. Нам важно получать результаты в условиях реальной многозадачности, когда одновременно работают и моторы, и пользовательский интерфейс, и полевые шины.
Результаты тестов чтения 64 Кбайт из Flash с 1-битным протоколом и 60 МГц тактированием:
Скорость чтения «ручными» командами: 1 903.005 КБ/с (1 948 678 байт/с)
Скорость прямого программного чтения: 6 239.032 КБ/с (6 388 769 байт/с)
Скорость прямого чтения по DMA: 5 844.214 КБ/с (5 984 476 байт/с)
Результаты тестов чтения 64 Кбайт из Flash с 8-битным протоколом и 60 МГц тактированием:
Скорость чтения «ручными» командами: 2437.166 КБ/с (2495658 байт/с)
Скорость прямого программного чтения: 35184.166 КБ/с (36028587 байт/с)
Скорость прямого чтения по DMA: 6537.950 КБ/с (6694861 байт/с)
Отсюда видно, что переход с 1-битного на 8-битный протокол при использовании DMA не даёт ощутимого прироста. Нельзя забывать, что в устройстве в это время работают другие каналы DMA и DTC. Прямое программное чтение остаётся более чем вдвое медленнее теоретической скорости при тактировании 60 МГц. Похоже, 8-битное подключение было избыточным — пины можно было бы сэкономить.
Ниже статистика процедуры стирания всей памяти MX25UM25645GMI:
===== Block Erase Results =====
Block erase operation : SUCCESS
Total blocks erased : 512 / 512
Total size erased : 32 MB (33554432 bytes)
Total elapsed time : 2 minutes 36 seconds (156666 ms)
Overall erase speed : 209 KB/s
=== Final Statistics ===
Minimum block erase time : 246 ms
Maximum block erase time : 355 ms
Average block erase time : 299 ms
Minimum block erase speed : 180 KB/s
Maximum block erase speed : 260 KB/s
О методике тестирования
Тестирование можно организовать по-разному, в зависимости от целевого сценария использования файловой системы; здесь я не претендую на всестороннее покрытие. Кому нужны другие проверки — можно взять проект и настроить тесты под свои задачи.
Я использовал стресс-тест: циклы записи → чтения → стирания для 1000 файлов по 10 Кбайт. Такой профиль близок к моим практическим кейсам (запись телеметрии).
Т.е. 1000 файлов последовательно записывается, потом эта тысяча последовательно читается и потом последовательно стирается. При чтении проверяется целостность файлов. Тестирование каждой следующей файловой системы ведется ни чистую Flash.
Параметры платы: OSPI 8-бит, 60 МГц; частота ядра МК — 240 МГц.
Результаты File-X
FileX в конфигурации с одной таблицей FAT и без журналирования.



Результаты LittleFS



Результаты YFFS2



Результаты STfs



Сводная таблица результатов

Как видно, наилучше справляется с большим количеством файлов YFFS2.
Самая быстрая — STfs. Если запись происходит редко, то STfs — лучший вариант. Если запись происходит часто, то лучше выбрать YFFS2.
Но надо помнить, что STfs показывает высокую скорость только при записи на чистую флеш-память. Форматирование в STfs длится 153 сек. Дефрагментация после удаления записанных 1000 файлов длится 47 сек. Для сравнения форматирование FileX длится 0.5 сек независимо от того сколько мусора оставалось на диске.
А вот LittleFS вызывает тревогу: возможны неожиданные задержки, которые могут стать проблемой. И самая низкая скорость записи. Однозначно применять её мы не будем.
Как ни странно, если требования к реальному времени не слишком жёсткие, хорошо подходит блочная FileX. Её можно использовать для обновления прошивок и хранения ресурсов веб-страниц, поскольку там канал передачи данных может ограничивать скорость сильнее самой файловой системы. Кроме того, в этом случае не нужно беспокоиться о фрагментации.
Итак, выбор сделан: разбиваем флеш-память на две части. В одной будет FileX, в другой — STfs.
Да, а GitHub Copilot тут при том, что ни одна строчка кода не была введена вручную. Поэтому лицензия пока MIT.