Выравнивание износа
Каждый сектор флеш-памяти выдерживает ограниченное число стираний. Если программа всё время переписывает один и тот же сектор, он изнашивается за месяцы, хотя остальная память почти не тронута. Выравнивание износа распределяет стирания по всей области.
Обновлено Редакция GAW
Выравнивание износа (wear leveling) — способ записи во флеш-память, при котором стирания распределяются по всем секторам области, а не приходятся на один и тот же. Ресурс флеш-памяти задан на сектор: по даташитам, не меньше 100 000 циклов стирания у SPI-флеш W25Q128JV и 10 000 у встроенной флеш STM32F103. Сектор, который стирают при каждом сохранении, исчерпывается первым — и вместе с ним приходит в негодность хранилище, хотя остальная память почти не изношена.
Как это работает
Программа обращается к логическим адресам, а слой выравнивания решает, в какой физический сектор их положить. Когда логический сектор переписывают, данные уходят в другой, свободный физический сектор, а старый освобождается для будущих записей. Таблица соответствия хранится в той же флеш-памяти. Насколько слой переживает пропадание питания, зависит от реализации: в ESP-IDF, например, режим Performance при сбое во время стирания теряет 4 096 байт данных, а режим Safety — нет (подробнее ниже).
По описанию littlefs, алгоритмы бывают двух видов:
| Вид | Какие блоки участвуют | Плюсы и минусы |
|---|---|---|
| Динамическое | только свободные | просто, но блоки с неизменными данными не изнашиваются и не помогают остальным |
| Статическое | все, включая занятые | износ ровнее, но нужно переносить неизменные данные |
littlefs реализует только динамическое выравнивание, причём статистическое: износ не учитывается, блоки выделяются по кругу, а после каждого монтирования распределитель начинает со случайного места. Кроме того, littlefs проверяет запись, обнаруживает плохие блоки и переносит данные из них — для NAND-флеш это обязательная часть работы.
Выравнивание износа в ESP-IDF
В ESP-IDF есть отдельный компонент wear_levelling. Он работает поверх раздела из таблицы разделов и чаще всего — под файловой системой FAT. По документации, лучшая производительность — с сектором 4 096 байт, но тогда нужен буфер в ОЗУ. Для экономии памяти есть режимы с сектором 512 байт:
- Performance — содержимое стираемого сектора держится в ОЗУ; если питание пропадёт в этот момент, 4 096 байт данных потеряются;
- Safety — данные сначала сохраняются во флеш, и после сбоя питания их можно восстановить при следующей загрузке.
Компонент не кэширует данные: к возврату из функции записи флеш-память уже обновлена. Часть секторов раздела он занимает под служебную информацию, поэтому доступный объём меньше размера раздела. Хранилище настроек NVS устроено иначе: по документации ESP-IDF, при изменении значения старая запись лишь помечается удалённой и остаётся во флеш, а новая пишется в свободное место, так что переписывания на месте нет и здесь. Для больших файлов документация NVS сама советует FAT поверх слоя wear levelling.
Когда без него можно обойтись
Если данные записывают редко — калибровку при производстве, настройки раз в месяц, — ресурса одного сектора хватает с огромным запасом. Выравнивание нужно для журналов, счётчиков и файловых систем, которые меняют одни и те же структуры при каждой записи. Для байтовых настроек часто проще взять EEPROM или FRAM, у которых ресурс выше и стирать секторами не нужно.
Частые вопросы
Зачем нужно выравнивание износа?
Ресурс флеш-памяти считают на сектор: у W25Q128JV не меньше 100 000 циклов стирания, у встроенной флеш STM32F103 — 10 000. Если программа раз в минуту стирает один и тот же сектор, 10 000 циклов кончатся меньше чем за семь суток (своя оценка: 10 000 минут — около 6,9 суток). Если те же записи распределить по 100 секторам, на каждый придётся в сто раз меньше стираний.
Чем динамическое выравнивание износа отличается от статического?
По описанию littlefs, динамическое выравнивание распределяет запись только по свободным блокам, а блоки с неизменными данными так и остаются нетронутыми. Статическое учитывает все блоки и время от времени переносит и неизменные данные, чтобы их блоки тоже приняли свою долю стираний. littlefs реализует только динамический вариант — так проще и меньше кода.
Нужно ли выравнивание износа для FAT на SPI-флеш ESP32?
Да, ESP-IDF монтирует FAT на внутренней SPI-флеш через компонент wear levelling: функция esp_vfs_fat_spiflash_mount_rw_wl создаёт этот слой сама. Без него таблица FAT и каталог, которые меняются при каждой записи файла, быстро выработали бы свои секторы. Слой занимает часть секторов раздела под служебные данные.
Источники
- Espressif. ESP-IDF Programming Guide v6.1, API Reference — Storage — Wear Levelling API (ESP32) — флеш-память, в том числе SPI-флеш ESP32, организована секторами с ограниченным числом циклов стирания; компонент wear levelling распределяет износ по секторам равномерно; работает через компонент разделов и совместно с FAT FS; сектор FAT 4 096 байт — лучшая производительность, но нужно ОЗУ; режимы с сектором 512 байт: Performance (данные сектора в ОЗУ, при пропадании питания 4 096 байт теряются) и Safety (данные сначала сохраняются во флеш, после сбоя восстанавливаются); данные не кэшируются в ОЗУ; часть секторов раздела занята служебными данными; API wl_mount, wl_erase_range, wl_write, wl_sector_size; перед записью область стирают wl_erase_range
- littlefs project. DESIGN.md — The design of littlefs, section «Wear leveling» (BSD-3-Clause) — выравнивание износа — распределение износа по всем блокам, чтобы ранний износ одного блока не вывел из строя всё хранилище; два способа защиты: обнаружение и замена плохих блоков и равномерное распределение износа по динамическим блокам; динамическое выравнивание учитывает только свободные блоки, статическое — все, включая занятые; littlefs реализует только динамическое и статистическое: блоки выделяются по кругу, при каждом монтировании распределитель начинает со случайного смещения
- Espressif. ESP-IDF Programming Guide v6.1, API Reference — Storage — Non-Volatile Storage Library — NVS лучше подходит для многих маленьких значений; большие строки и blob советуют хранить в FAT поверх библиотеки wear levelling; при обновлении или удалении пары ключ — значение данные во флеш лишь помечаются удалёнными в метаданных и остаются в памяти, это ускоряет запись
- Winbond. W25Q128JV 3V 128M-bit Serial Flash Memory with Dual/Quad SPI, Revision F, March 27, 2018 — разд. 2: не меньше 100 000 циклов программирования и стирания на сектор; разд. 1: 4 096 секторов по 4 КБ
- STMicroelectronics. DS5319 STM32F103x8, STM32F103xB datasheet, Rev 20 (July 2025) — табл. 29: ресурс встроенной флеш NEND не меньше 10 000 циклов
Нашли ошибку?
Смотрите также
- Сектор и страница флеш-памятиНаименьшая стираемая область флеш: страницы STM32F1, секторы STM32F4, W25Q
- NAND-флеш-памятьСтраницы и блоки NAND, плохие блоки, ECC и чем NAND отличается от NOR
- NVS (хранилище ESP32)Хранилище пар «ключ — значение» во флеш-памяти ESP32
- Таблица разделов ESP32Карта флеш-памяти ESP32: где приложение, NVS, OTA и данные
- EEPROMЭнергонезависимая память для настроек и калибровки