Продолжаем работу по программированию микроконтроллера ESP32 и на данном уроке мы познакомимся с возможностью использования файловой системы SPIFFS. Хотя познакомимся — громко сказано, мы с ней уже знакомы ещё со времён работы с семейством контроллеров ESP8266.
И по аналогии работы с вышеуказанной линейкой контроллеров мы столкнулись с аналогичным неудобством. Мы вполне можем передавать по протоколу HTTP документы с нашего сервера клиенту. Только мы столкнулись с проблемой их неудобного хранения на нашем сервере, а именно при помощи массива. Хотелось бы как-то хранить их в явном виде — в виде файлов. Помочь нам в этом сможет то, что у контроллера ESP32 (как впрочем и у ESP8266) есть своя файловая система SPIFFS (Serial Peripheral Interface Flash File System). Вернее даже будет сказать, что она есть не у контроллера, а содержится в комплекте IDF. Данная файловая система размещается в свободном пространстве FLASH-памяти, а так как у нас её 4 мегабайта, а для прошивки нам много места не нужно, мы до сих пор вполне умещаемся в 500 килобайтах в начале памяти, то мы вполне можем использовать некоторое пространство для файловой системы. На всякий случай мы для прошивки оставим полностью первый мегабайт, а дальше уже будем размещать файловую систему. 1-2 мегабайта нам вполне хватит для размещения служебных файлов сервера. Также в технической документации мы можем прочитать то, что на файловую систему SPIFFS наложен ряд ограничений, как то невозможность создавать директории, ограниченный размер имени файла и т.д. Но, так как хранить нам придётся немного, мы вполне в рамках данных ограничений уместимся.
Также существует утилита для добавления в образ файловой системы файлов mkspiffs, и причём, как я уже говорил в уроке по ESP8266, у меня она корректно работает только для контроллера ESP32. Поэтому мы данной утилитой сегодня тоже воспользуемся.
А схема наша, как и в прошлом занятии, будет состоять только из отладочной платы с контроллером ESP32, подключенной к USB-порту компьютера
А проект мы возьмём из давнего урока 4, в котором мы работали с кнопкой, с именем BUTTON01 и на его основе создадим проект с именем SPIFFS.
Откроем наш проект в ESPRESSIF IDE и из файла Kconfig.projbuild удалим пункт меню по работе с ножкой, к которой была подключена кнопка (BUTTON_GPIO). Также в данном файле ножку порта по умолчанию для светодиода выберем вторую
default 48 if IDF_TARGET_ESP32S3
default 2
В функции app_main файла main.c оставим только вот эти строки (заодно прибавим задержку, тем самым дадим нормально работать другим процессам)
1 2 3 4 5 6 7 8 9 10 11 |
//------------------------------------------------------------- void app_main(void) { gpio_reset_pin(CONFIG_BLINK_GPIO); gpio_set_direction(CONFIG_BLINK_GPIO, GPIO_MODE_OUTPUT); while (1) { vTaskDelay(1000 / portTICK_PERIOD_MS); } } //------------------------------------------------------------- |
Не забываем также в конфигураторе выбрать 4 мегабайта объёма памяти FLASH
Попробуем собрать наш проект. Если всё нормально собирается, то ещё создадим заголовочный файл main.h, в который соберём все подключенные заголовочные файлы из main.c, а заодно и подключим заголовочные файлы для работы с файловой системой SPIFFS
1 2 3 4 5 6 7 8 9 10 11 12 |
#ifndef MAIN_MAIN_H_ #define MAIN_MAIN_H_ //------------------------------------------------------------- #include <stdio.h> #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "driver/gpio.h" #include "esp_spiffs.h" #include "spiffs_config.h" #include "sdkconfig.h" //------------------------------------------------------------- #endif /* MAIN_MAIN_H_ */ |
Вернёмся в main.c и удалим подключение всех заголовочных файлов, а подключим только один
1 |
#include "main.h" |
Объявим глобальный символьный массив для лога
1 2 3 4 |
#include "main.h" //------------------------------------------------------------- static const char *TAG = "main"; //------------------------------------------------------------- |
Для того, чтобы работать с файловой системой SPIFFS, нужно объявить специальный раздел в области памяти FLASH, подключенной к контроллеру, так как если мы прошьём наш проект и запустим терминал, то при загрузке мы видим следующую таблицу разделов в FLASH-памяти
Ни о каком разделе для SPIFFS здесь речь не идёт. В данном случае лучше всего объявить свою таблицу разделов. Для этого сначала идём в конфигуратор и в разделе Partition table выберем соответствующую опцию
Предложенное имя файла можно не менять, мы такой и создадим в каталоге с нашим проектом (в архиве с исходником он будет) с именем partitions.csv следующего содержания
1 2 3 4 5 6 |
# Name, Type, SubType, Offset, Size, Flags # Note: if you have increased the bootloader size, make sure to update the offsets to avoid overlap nvs, data, nvs, 0x9000, 0x6000, phy_init, data, phy, 0xf000, 0x1000, factory, app, factory, 0x10000, 1M, storage, data, spiffs, , 0xF0000, |
Мы расположим раздел spiffs с адреса 0xF0000. Адрес мы можем не указывать, компилятор его вычислит, он будет 0x110000, так ка 0x10000 плюс 1 мегабайт будет именно такое число.
Сохраним конфигуратор, пересоберём и перепрошьём наш код.
Теперь мы видим следующую таблицу разделов
Теперь мы видим наш раздел storage. Думаю, что данная работа с таблицей разделов пойдёт нам на пользу, так как мы можем теперь распределять пространство по своему усмотрению не только для работы с SPIFFS.
Ну теперь займёмся непосредственно самой файловой системой. Для начала попробуем что-нибудь создать. Для этого мы сначала объявим и проинициализируем переменную типа структуры для нашей файловой системы и в функции app_main применим специальную функцию для регистрации файловой системы
1 2 3 4 5 6 7 8 9 10 11 12 |
gpio_set_direction(CONFIG_BLINK_GPIO, GPIO_MODE_OUTPUT); ESP_LOGI(TAG, "Initializing SPIFFS"); esp_vfs_spiffs_conf_t conf = { .base_path = "/spiffs", .partition_label = NULL, .max_files = 5, .format_if_mount_failed = true }; esp_err_t ret = esp_vfs_spiffs_register(&conf); |
Если обнаружатся какие-то ошибки, то выйдем из функции с соответствующим сообщением в терминале
1 2 3 4 5 6 7 8 9 10 11 12 |
esp_err_t ret = esp_vfs_spiffs_register(&conf); if (ret != ESP_OK) { if (ret == ESP_FAIL) { ESP_LOGE(TAG, "Failed to mount or format filesystem"); } else if (ret == ESP_ERR_NOT_FOUND) { ESP_LOGE(TAG, "Failed to find SPIFFS partition"); } else { ESP_LOGE(TAG, "Failed to initialize SPIFFS (%s)", esp_err_to_name(ret)); } return; } |
Определим и выведем в терминал общий размер нашей файловой системы и размер, занятый файлами, а если не удастся, то выведем ошибку
1 2 3 4 5 6 7 8 9 10 |
return; } size_t total = 0, used = 0; ret = esp_spiffs_info(conf.partition_label, &total, &used); if (ret != ESP_OK) { ESP_LOGE(TAG, "Failed to get SPIFFS partition information (%s)", esp_err_to_name(ret)); } else { ESP_LOGI(TAG, "Partition size: total: %d, used: %d", total, used); } |
Попробуем открыть файл, а если такого нет, то создадим его
1 2 3 4 5 6 7 8 9 10 |
ESP_LOGI(TAG, "Partition size: total: %d, used: %d", total, used); } FILE* f; ESP_LOGI(TAG, "Opening file"); f = fopen("/spiffs/hello.txt", "w"); if (f == NULL) { ESP_LOGE(TAG, "Failed to open file for writing"); return; } |
Запишем в него текст и закроем
1 2 3 4 5 6 |
ESP_LOGE(TAG, "Failed to open file for writing"); return; } fprintf(f, "Hello World!\n"); fclose(f); ESP_LOGI(TAG, "File written"); |
Соберём код, прошьём контроллер и посмотрим результат в терминале
Отлично! Всё создалось и записалось.
А вот дальше мы поступим необычно и читать из файла будем не здесь. Мы попробуем с помощью утилиты mkspiffs прочитать образ файловой системы, получить файл и прочитать его в обычном блокноте, а в коде мы ещё начитаемся. Утилиту с небольшим файлом readme я прикрепил внизу страницы.
Итак открываем командную строку и в каталоге с утилитой сначала вытащим образ с помощью старого доброго esptool (не забываем отключать терминал)
Понятно, что у вас будет свой номер порта.
У меня почему-то esptool не увиделся и я его закинул в каталог с программой
после выполнения команды у нас появится файлик с образом
И теперь с помощью следующей команды извлечём из него все файлы (в нашем случае там должен быть только один) в нужный каталог, который также заранее создавать не надо. Если его нет, то он создастся
Прочитаем наш файл в блокноте
Теперь попробуем создать образ и записать его во FLASH-память. Для этого в каталог files скопируем ещё два файла, которые нам, возможно, в будущем пригодятся. Это файл со страничкой и иконку
Теперь дадим следующую команду
У нас появится ещё один файл с образом файловой системы
Запишем образ в память FLASH с помощью следующей команды
Можно, конечно, попробовать заново прочитать образ из памяти и вытащить оттуда файлы, но я это уже несколько раз проделывал, всё работает.
Вернёмся в наш проект, закомментируем создание файла и запись в него
1 2 3 4 5 6 7 8 9 10 11 12 |
/* FILE* f; ESP_LOGI(TAG, "Opening file"); f = fopen("/spiffs/hello.txt", "w"); if (f == NULL) { ESP_LOGE(TAG, "Failed to open file for writing"); return; } fprintf(f, "Hello World!\n"); fclose(f); ESP_LOGI(TAG, "File written"); */ |
Вместо этого попробуем открыть файл index.html и прочитать в терминал его содержимое
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
ESP_LOGI(TAG, "Partition size: total: %d, used: %d", total, used); } ESP_LOGI(TAG, "Opening file"); FILE* f = fopen("/spiffs/index.html", "rb"); if (f == NULL) { ESP_LOGE(TAG, "Failed to open file for reading"); return; } char str1[500]; size_t n; n = fread(str1, 1, sizeof(str1), f); fclose(f); str1[n] = 0; ESP_LOGI(TAG, "Read from file:\r\n%s", str1); |
Чтобы закончить нулём строку, мы узнали размер файла, иначе потом читалка в лог будет читать и дальше до первого нуля.
Соберём код, прошьём контроллер, включим терминал и посмотрим результат работы кода
Всё прекрасно прочиталось и отобразилось.
Итак, на данном уроке мы познакомились с файловой системой SPIFFS, научились открывать файлы, читать из них информацию, а также писать.
Всем спасибо за внимание!
Предыдущий урок Программирование МК ESP32 Следующий урок
Утилита для работы с файловой системой SPIFFS: mkspiffs
Недорогие отладочные платы ESP32 можно купить здесь Недорогие отладочные платы ESP32
Недорогие отладочные платы ESP32/ESP32-C3/ESP32-S3 можно купить здесь Недорогие отладочные платы ESP32
Логический анализатор 16 каналов можно приобрести здесь
Смотреть ВИДЕОУРОК в RuTube (нажмите на картинку)
Смотреть ВИДЕОУРОК в YouTube (нажмите на картинку)
Смотреть ВИДЕОУРОК в Дзен (нажмите на картинку)
Добавить комментарий