Перейти к содержанию

Выравнивание износа

Каждый сектор флеш-памяти выдерживает ограниченное число стираний. Если программа всё время переписывает один и тот же сектор, он изнашивается за месяцы, хотя остальная память почти не тронута. Выравнивание износа распределяет стирания по всей области.

Обновлено Редакция 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 и каталог, которые меняются при каждой записи файла, быстро выработали бы свои секторы. Слой занимает часть секторов раздела под служебные данные.

Источники

  1. 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
  2. littlefs project. DESIGN.md — The design of littlefs, section «Wear leveling» (BSD-3-Clause) — выравнивание износа — распределение износа по всем блокам, чтобы ранний износ одного блока не вывел из строя всё хранилище; два способа защиты: обнаружение и замена плохих блоков и равномерное распределение износа по динамическим блокам; динамическое выравнивание учитывает только свободные блоки, статическое — все, включая занятые; littlefs реализует только динамическое и статистическое: блоки выделяются по кругу, при каждом монтировании распределитель начинает со случайного смещения
  3. Espressif. ESP-IDF Programming Guide v6.1, API Reference — Storage — Non-Volatile Storage Library — NVS лучше подходит для многих маленьких значений; большие строки и blob советуют хранить в FAT поверх библиотеки wear levelling; при обновлении или удалении пары ключ — значение данные во флеш лишь помечаются удалёнными в метаданных и остаются в памяти, это ускоряет запись
  4. Winbond. W25Q128JV 3V 128M-bit Serial Flash Memory with Dual/Quad SPI, Revision F, March 27, 2018 — разд. 2: не меньше 100 000 циклов программирования и стирания на сектор; разд. 1: 4 096 секторов по 4 КБ
  5. STMicroelectronics. DS5319 STM32F103x8, STM32F103xB datasheet, Rev 20 (July 2025) — табл. 29: ресурс встроенной флеш NEND не меньше 10 000 циклов

Нашли ошибку?