• Система автоматизации с открытым исходным кодом на базе esp8266/esp32 микроконтроллеров и приложения IoT Manager. Наша группа в Telegram

"Низкоуровневый" доступ к SPIFFS

702

New member
Здравствуйте.

Осваиваю работу с файловой системой SPIFFS. FreeRTOS SDK, без Ардуины.

Во всех примерах для работы с файлами используются потоковые функции. Я хочу использовать обычный бинарный ввод-вывод.
Нашел в АПИ низкоуровневые функции SPIFFS_open, SPIFFS_read итд. В качестве параметра им нужно передать указатель на структуру типа spiffs. Беглый просмотр исходников показал, что это описатель раздела, массив которых хранится в памяти библиотеки SPIFFS.
Но этот массив объявлен как static, и методов доступа к нему я не нашел. Можно конечно, пропатчить библиотеку: добавить функцию, возвращающую указатель; добавить поле в структуру esp_vfs_spiffs_conf и инициализировать его при регистрации; или вовсе убрать static, что уже совсем грубо.
Или скопировать исходник библиотеки к себе в проект и уже там резвиться.

Или можно как-нибудь еще?
 

exeland

Member
вот примеры работы - pellepl/spiffs
В примерах же напрямую с функциями работают. spiffs __fs - глобальная переменная прописанная test_spiffs.c
 

702

New member
вот примеры работы - pellepl/spiffs
Эти примеры есть прямо в составе SDK. Но тут придется смириться либо с частичным дублированием кода, либо с потерей возможности
потоковых операций. Пока решил при необходимости пользоваться патченной библиотекой, хотя это и некрасиво.
Но все равно спасибо.
 

702

New member
Продолжаю экспериментировать со SPIFFS.
Попытался создать свой образ размером 64 килобайта, содержаший единственный файл. Создавал при помощи mkspiffs.
В настройках проекта указал:

SPIFFS Filesystem Magic = 1,
Enable SPIFFS Filesystem Length Magic = 1
Size of per-file metadata field = 0

по рекомендациям автора mkspiffs.

Образ разместил по адресу 0xb0000. Образ нормально монтируется, приложение создает, читает и пишет файлы без проблем.
При этом файл, который изначально находился в образе открывается успешно, но при его чтении возникает ошибка.
В считанном и распакованном после работы приложения образе ровно наоборот:
"мой" файл в порядке, имена созданных приложением файлов правильные, но внутри файлов мусор.

Если создать образ при помощи spiffsgen.py с соответствующими настройками, ситуация один-в-один.

В чем может быть дело?
 

702

New member
Сам отвечаю на свой вопрос.

Путем изучения исходников и втыкания в них многочисленных отладочных сообщений (нормального описания этой самой SPIFFS нет),
а также побайтового сравнения образов, сгенеренных на ПК и приложением, выяснил, что SDK при сборке приложения игнорирует настройку
"Size of per-file metadata field = 0"
в конфиге, и всегда вставляет в структуру заголовка страницы поле, размером один байт. Оно не последнее в структуре. Соответственно, в образе, созданном без этого поля, значения последующих полей оказываются сдвинутыми и принимают непредсказуемые значения.

Решение: создавать образы с включенным полем metadata.

Вдруг кому пригодится.
 

Slacky

Member
Подниму тему. Решил загрузить spiffs с помощью mkspiffs. Все хорошо. Собрал mkspiffs. Подсунул при компиляции mkspiffs sdkconfig.h от проекта. Собралось все с теми же параметрами, как в sdlconfig. Но все равно не работает. Листинг показывает, что файлы есть, но прочитатать не могу - 0.

Код:
CONFIG_SPIFFS_MAX_PARTITIONS=3
CONFIG_SPIFFS_CACHE=y
CONFIG_SPIFFS_CACHE_WR=y
# CONFIG_SPIFFS_CACHE_STATS is not set
CONFIG_SPIFFS_PAGE_CHECK=y
CONFIG_SPIFFS_GC_MAX_RUNS=10
# CONFIG_SPIFFS_GC_STATS is not set
CONFIG_SPIFFS_PAGE_SIZE=256
CONFIG_SPIFFS_OBJ_NAME_LEN=32
CONFIG_SPIFFS_USE_MAGIC=y
CONFIG_SPIFFS_USE_MAGIC_LENGTH=y
CONFIG_SPIFFS_META_LENGTH=4
CONFIG_SPIFFS_USE_MTIME=y
Код:
$ ./mkspiffs --version
mkspiffs ver. 0.2.3-7-gf248296
Build configuration name: generic
SPIFFS ver. 0.3.7-5-gf5e26c4
Extra build flags: (none)
SPIFFS configuration:
  SPIFFS_OBJ_NAME_LEN: 32
  SPIFFS_OBJ_META_LEN: 4
  SPIFFS_USE_MAGIC: 1
  SPIFFS_USE_MAGIC_LENGTH: 1
  SPIFFS_ALIGNED_OBJECT_INDEX_TABLES: 0
C:
static esp_err_t read_file(const char *filename) {

    char buff[1024];
    size_t size;

    sprintf(buff, "%s%s%s", DIR_PATH, DELIM, filename);
    printf("%s\n", buff);

    FILE *f = fopen(buff, "rb");
    if (f == NULL) {
        ESP_LOGE(TAG, "Cannot open file %s", buff);
        return ESP_FAIL;
    }

    do {
        size = fread(buff, 1, sizeof(buff), f);
        printf("size - %d\n", size);
        if (size > 0) {
            printf(buff);
        }
    } while (size == sizeof(buff));

    fclose(f);

    return ESP_OK;
}
Ну и вывод

Код:
I (290) main.c: Initializing SPIFFS
Directory: /spiffs/html

/spiffs/html/config.html
size - 0
/spiffs/html/favicon.ico
size - 0
/spiffs/html/index.html
size - 0
/spiffs/html/log.html
size - 0
/spiffs/html/ok.html
size - 0
/spiffs/html/scripts.js
size - 0
/spiffs/html/settings.html
size - 0
/spiffs/html/style.css
size - 0
/spiffs/html/upload.html
size - 0

Used 0  bytes
Free 388548     bytes
Есть идеи куда копать?
 

Slacky

Member
Разобрался, точнее скорей потыкал, чем понял.

При
CONFIG_SPIFFS_META_LENGTH=1

все прекрано работает.
 

Slacky

Member
Вроде логично.
Вроде да, но не вполне. Если прочесть фразу целиком, то смысл все-таки немного другой. Я это понял так - при 0 все равно 1.

Я не стал разбираться по коду, когда именно меняется настройка из sdkconfig на 1. Но. В esp32 компонент spiffs один в один как и для esp8266. И в esp32 все работает из коробки, а sdkconfig в части spiffs у них одинаковый.
 
Сверху Снизу