SPIFFS – (Serial Peripheral Interface Flash File System) файловая система флеш-памяти, подключаемой по последовательному периферийному интерфейсу. Простыми словами: есть микроконтроллер ESP32 (рисунок 1), у него есть встроенная перезаписываемая энергонезависимая NOR-память, в которой хранятся: настройки (Preferences), загрузчик (Bootloader), микропрограмма (скомпилированный скетч), файловая система (SPIFFS) и ещё что-нибудь, типа обновления "по воздуху" (OTA).



Рисунок 1. Функциональная блок-схема микроконтроллера ESP32


NOR-память – это такой вид энергонезависимой перезаписываемой памяти, который имеет достаточно высокую скорость считывания, относительно низкую скорость записи и стирания, в сравнении с типом памяти NAND. Встретить NOR-память большого объёма практически невозможно, обычно ограничиваются 128 МБ. В случае с ESP32 – четырьмя.


На сегодняшний день SPIFFS имеет некоторые недостатки недоработки, в их числе: отсутствие поддержки папок; не стек реального времени, поэтому одна и та же операция может занимать разное время; отсутствие возможности нахождения и исправления битых блоков. Если перечисленные недостатки для Вас некритичны, то продолжаем читать следующий пункт.


Давайте поговорим об использовании


К сожалению, из коробки память микроконтроллера не размечена под SPIFFS, для того чтобы разметить, необходимо воспользоваться плагином ESP32FS для среды разработки Arduino IDE.


После того, как плагин скачен – его необходимо установить:


  • Убедитесь, что у Вас установлена новейшая версия среды разработки Arduino IDE и драйвера для Вашего устройства на ESP32. У меня M5Stack драйвера CP210X я скачиваю по этой ссылке;
  • Скопируйте скаченную папку tool со вложенным в неё плагином в папку /Arduino/tools/ESP32FS/;
  • В macOS папка расположена по адресу ~/Documents/Arduino/;
  • Перезагрузите компьютер и проверьте в среде разработки в меню Инструменты (Tools) появится пункт ESP32 Sketch Data Upload (рисунок 2) – значит Вы всё выполнили правильно;


Рисунок 2. Меню Инструменты (Tools)


  • Обратите внимание на папку data, находящуюся рядом со скетчем. Все файлы, расположенные в данной папке, будут загружены в память устройства при форматировании;
  • Смело выбираем указанный пункт и дожидаемся окончания форматирования области памяти. Обратите внимание на то, что другие участки памяти затронуты НЕ будут, а значит микропрограмма останется в памяти устройства и будет работать. Аналогично и со скетчем, когда он будет скомпилирован в микропрограмму и загружен в устройство – файловая система затронута не будет.

Если хочется комфорта


  • Если Вы хотите трогать файлы и видеть информацию о свободном пространстве, то скачайте скетч BRIDGE и прошейте им своё устройство.


  • Так же скачайте и скомпилируйте кроссплатформенный файловый менеджер A-Explorer (рисунок 3). На GitHub бинарные файлы вскоре будут лежать в папке bin.



    Рисунок 3, a. Файловый менеджер A-Explorer под macOS



    Рисунок 3, б. Файловый менеджер A-Explorer под Windows



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


Как видите по рисунку 3 плагин разметил приблизительно 1,38 МБ памяти под SPIFFS.


Кто такой этот BRIDGE?


BRIDGE – это скетч, а прежде всего одноимённая функция, которая работает с файловой системой SPIFFS и A-Explorer является графической оболочкой для неё. Последний отправляет ту или иную команду, а данная функция её обрабатывает на самом устройстве с использованием библиотек FS и SPIFFS. Давайте посмотрим, чего есть интересного в этих библиотеках.


Начнём с рассмотрения публичных методов класса SPIFFS:


  • Метод bool begin(bool formatOnFail=false, const char * basePath="/spiffs", uint8_t maxOpenFiles=10). Данный метод пытается инициализировать экземпляр класса. Первым аргументом принимает истину или ложь на тот случай, стоит ли форматировать файловую систему, если файловая система не отформатирована. Второй аргумент принимает путь, где будет располагаться корень файловой системы. Третий аргумент определят количество одновременно открытых файлов. Последние два параметра лучше оставить дефолтными и не менять их. Если файловая система отсутствует (не был использован плагин, приведённый выше). то функцию вернёт ложь.


  • Метод bool format() проверят отформатирована ли файловая система – возвращает истину, в противном случае – ложь.


  • Метод size_t totalBytes(). Такой метод возвращает size_t-число общего количества Байт размеченных под файловую систему.


  • Метод size_t usedBytes(). Этот метод возвращает size_t-число используемых Байт в файловой системе.


  • Метод void end(). Данный метод производит деинициализацию данного класса. После вызова данного метода другие методы вызывать бессмысленно.



В данном классе всё, ничего особо интересного нет. Давайте перейдём к классу FS и посмотрим, что оттуда нам может пригодиться.


  • Первое, что бросается в глаза, так это метод-инициализатор класса bool begin(). Данный метод не требует аргументов и вызывать его нет необходимости, т. к. мы будем использовать сразу следующий метод.


  • Метод File open(const char path, const char mode) и его брат File open(const String& path, const char* mode). Данные методы принимают по два аргумента первый из них символьный и строковый указатель на путь к файлу, а второй режим открытия, который может быть следующей константой:



FILE_READ – открыть только для чтения;


FILE_WRITE – открыть только для записи;


FILE_APPEND – открыть для дозаписи.


После того, как мы открыли файл, теперь можем произвести над ним какие-либо операции.


  • Метод size_t write(uint8_t) позволяет записать в конец файла одно 8 битное беззнаковое целое число.
  • Метод size_t write(const uint8_t *buf, size_t size) позволяет записывать ряд безнаковых целых чисел указанной длинны во втором аргументе.
  • Метод int available() подсчитывает количество символов от конца до указателя.
  • Метод int read() считывает из файла один символ и возвращает его в виде целого числа, при этом курсор смещается на единицу право.
  • Метод size_t readBytes(char *buffer, size_t length) считывает символы в буфер, указатель на который получен первым аргументом, а количество символов, переданное вторым аргументом. Возвращает количество считанные символов.
  • Метод String readString() cчитывет строку из файла.
  • Метод int peek() работает аналогично методу int read(), только курсор остаётся на месте.
  • Метод bool seek(uint32_t pos, SeekMode mode) и bool seek(uint32_t pos, SeekMode mode) устанавливает курсор в указанное место. Первым аргументом передают позицию, а вторым правило (SeekSet – установить курсор). Если успешно – возвращает истину, в противном случае – ложь.
  • Метод size_t position() возвращает позицию курсора.
  • Метод size_t size() возвращает размер файла в Байтах.
  • Метод const char * name() возвращает имя файла.
  • Метод const char * fullName() с учётом полного пути.
  • Метод bool isFile() возвращает истину, если открытый объект является файлов. В противном случае – ложь.
  • Метод bool isDirectory() возвращает истину, если открытый объект является папкой. В противном случае – ложь.
  • Метод File openNextFile() возвращает указатель на следующий файл в корне, в противном случае NULL.
  • Метод bool exists(const char* path) и bool exists(const String& path) принимает в качестве аргумента полное имя файла, и, если такой файл существует, то возвращает истину, в противном – ложь.
  • Метод bool remove(const char* path) и bool remove(const String& path) пытается удалить файл, имя которого передано аргументом. В случае успеха возвращает истину, в противном случае – ложь.
  • Метод bool rename(const char pathFrom, const char pathTo) и bool rename(const String& pathFrom, const String& pathTo); принимает полное имя файла первым аргументов, а вторым полное новое имя файла и производите переименование.

Да-да, можно взять эту функцию и запустить её в отдельном потоке в любом другом скетче


Спасибо большое за уделённое время! Буду рад, если данная статья принесёт Вам пользу.


Список литературы и (или) источников:


  • SPIFFS Filesystem здесь
  • Работа с файловой системой в аддоне ESP8266 в IDE Arduino здесь
  • Arduino ESP32 filesystem uploader здесь

Комментарии (6)


  1. Snusmumrick97
    09.01.2020 14:24

    Как запустить её в отдельном потоке?


    1. dsiberia9s Автор
      09.01.2020 16:11
      -1

      по-джентельменски


  1. FGV
    09.01.2020 15:33

    Простыми словами: есть микроконтроллер ESP32 (рисунок 1), у него есть встроенная перезаписываемая энергонезависимая NOR-память…

    Маленькое уточнение, встроенная флэш память есть только у ESP32-D2WD (который в модули продающиеся на каждом углу естественно не ставится) и обьем у нее 16Мбит, т.е. 2Мбайт. Остальные ревизии есп32 встроенного флэша не имеют, т.е. флэшка у них внешняя.


  1. ser-mk
    09.01.2020 16:00

    Если Вы хотите трогать файлы...

    Как называется этот фетиш?))


    1. dsiberia9s Автор
      09.01.2020 16:07

      файлменедмент?))


      1. dsiberia9s Автор
        09.01.2020 16:07

        файлменеджмент?))