SPIFFS (Serial Peripheral Interface Flash File System) est un système de fichiers léger adapté (entre autre) aux micro-contrôleurs disposant d’une mémoire flash SPI tel que l’ESP32 et ESP8266. La librairie Arduino SPIFFS.h permet d’accéder à la mémoire flash comme s’il s’agissait d’un système de fichiers normal comme celui d’un ordinateur (en bien plus simple évidemment). On pourra lire, écrire et ajouter des données à un fichier et réaliser quelques opérations simples (formater, renommer, récupérer des informations…)
Sommaire
- 1 Présentation du système de fichier SPIFFS (SPI Flash File System)
- 2 Découverte de la librairie SPIFFS.h, API et méthodes disponibles
- 3 Comment transférer des fichiers dans la zone mémoire SPIFFS ?
- 4 Récupérer les informations de la zone SPIFFS et la liste des fichiers
- 5 Comment écrire dans un fichier par programmation avec SPIFFS.h
- 6 Comment ajouter des données à un fichier par programmation ?
- 7 Mises à jour
Présentation du système de fichier SPIFFS (SPI Flash File System)
SPIFFS (pour Serial Peripheral Interface Flash File System) est un système de fichier développé par Peter Andersson (page du projet sur GitHub) qui peut fonctionner sur n’importe quel mémoire flash NOR ou flash SPI.
La librairie développée pour les modules ESP8266 reprend l’essentiel des fonctionnalités avec quelques limitations supplémentaires du fait des limitations des micro-contrôleurs :
- Arborescence il n’y a pas d’arborescence de fichier. Les fichiers sont placés à plat dans la zone de fichier. A la place, il est possible d’utiliser le caractère “\” dans le nom de fichier pour créer une pseudo arborescence.
- Nom de fichier limité à 31 caractères utiles c’est la seconde limitation importante. Le caractère ‘\0’ est réservé et automatiquement ajouté à la fin du nom de fichier pour la compatibilité avec les chaînes de caractère du langage C. Attention, l’extension de fichier consomme en général 4 caractères sur les 31 utiles.
- Pas de message d’alerte en cas d’erreur aucun message d’erreur n’apparaîtra à la compilation ou à l’exécution si la limites de 32 caractères est dépassée. Si le programme ne fonctionne pas comme prévu, pensez à vérifier le nom de fichier.
Autres limitations utiles à connaître :
- Il ne faut pas utiliser d’espace(s) ou de caractère(s) accentué(s) dans le nom de fichier
- Il n’y a pas de file d’attente
- Le temps d’écriture est variable d’un fichier à l’autre
- SPIFFS est destiné aux petits périphériques à mémoire flash, ne dépassez pas 128 Mo de stockage
- Il n’y a pas de mécanisme de détection de blocs défectueux
Découverte de la librairie SPIFFS.h, API et méthodes disponibles
La librairie SPIFFS.h est un portage de la librairie officielle pour Arduino qui est installée en même temps que le SDK ESP32.
Les méthodes proposées sont quasiment identiques à la librairie FS.h pour ESP8266.
Les méthodes suivantes ne sont pas disponibles
API librairie FS.h | Méthode équivalente |
SPIFFS.openDir(chemin) | aucune |
SPIFFS.info(fs_info) | SPIFFS.totalBytes()
Renvoie le nombre total d’octets utilisés par le système de fichier SPIFFS. SPIFFS.usedBytes() Renvoie l’espace utilisé par le fichier spécifié en octets |
Pour accéder au système de fichier, il suffit de la déclarer au début du croquis
#include "SPIFFS.h"
Comment formatter un nom (chemin) de fichier ?
SPIFFS ne gère pas l’arborescence.
On pourra toutefois créer une pseudo arborescence en utilisant le caractère “/” dans le nom de fichier sans dépasser la limite de 31 caractères utiles.
Le chemin de fichier doit toujours commencer par le caractère “/”, par exemple /fichier.txt
Les méthodes (API) de la librairie SPIFFS.h
SPIFFS.begin()
Cette méthode monte le système de fichiers SPIFFS et doit être appelée avant que n’importe quelle autre méthode FS ne soit utilisée. Renvoie true si le système de fichiers a été monté avec succès.
Il est conseillé de monter le système de fichier dans le setup
void setup() {
// Launch SPIFFS file system | Démarre le système de fichier SPIFFS
if(!SPIFFS.begin()){
Serial.println("An Error has occurred while mounting SPIFFS");
}
}
SPIFFS.format()
Formate le système de fichier. Renvoie true si le formatage a réussi. Attention, si des fichiers sont présents dans la zone mémoire, ils seront supprimés de façon irréversible.
if (!SPIFFS.begin(true)) {
Serial.println("An Error has occurred while mounting SPIFFS");
return;
}
bool formatted = SPIFFS.format();
if ( formatted ) {
Serial.println("SPIFFS formatted successfully");
} else {
Serial.println("Error formatting");
}
SPIFFS.open(path, option)
Ouvre un fichier
path doit être un chemin absolu commençant par une barre oblique (par exemple /dir/nom_fichier.txt).
option est une chaîne spécifiant le mode d’accès. Il peut s’agir de
- “r” read, lecture seule
- “r+” lecture et écriture. Le pointeur est positionné au début du fichier
- “w” write, écriture. Le contenu existant est supprimé. Le fichier est créé s’il n’existe pas
- “w+” ouvre le fichier en lecture et à l’écriture. Le fichier est créé s’il n’existe pas, sinon il est tronqué. Le pointeur est positionné au début du fichier
- “a” append, ouvre un fichier en ajout de données. Le fichier est créé s’il n’existe pas. Le pointeur est positionné à la fin du fichier s’il existe déjà
- “a+” append, ouvre un fichier en ajout de données. Le fichier est créé s’il n’existe pas. La pointeur est positionné au début du fichier en lecture et à la fin du fichier pour l’écriture (ajout)
Renvoie l’objet File. Pour vérifier si le fichier a été ouvert avec succès, utilisez l’opérateur booléen.
Une fois que le fichier est ouvert, voici les méthodes qui permettent de le manipuler
file.seek(décalage, mode)
Cette fonction se comporte comme la fonction fseek du langage C. En fonction de la valeur de mode, le pointeur est positionné dans le fichier comme ceci
SeekSet la position est définie pour décaler les octets par rapport au début
SeekCur la position actuelle est déplacée par octets de décalage
SeekEnd la position est définie pour décaler les octets à partir de la fin du fichier
La fonction renvoie true si la position a été définie avec succès
file.position()
Renvoie la position actuelle dans le fichier en octets.
file.size()
Renvoie la taille du fichier en octets. Attention, il n’est pas possible de connaître la taille d’un dossier
File file = SPIFFS.open("/test.txt");
if(!file){
Serial.println("Failed to open file for reading");
return;
}
Serial.print("File size: ");
Serial.println(file.size());
file.close();
file.name()
Renvoie le nom du fichier dans une constante au format const char *.
file.close()
Ferme le fichier
Opérations sur les dossiers
file.isDirectory()
Il n’y a pas de différence entre fichier et dossier. La méthode isDirectory() permet de savoir si le fichier est un dossier. Il n’est pas possible de connaître la taille d’un dossier
dir.openNextFile()
Ouvre le dossier suivant
SPIFFS.exists(chemin)
Renvoie true si un fichier avec un chemin donné existe, false dans le cas contraire.
SPIFFS.totalBytes()
Renvoie le nombre total d’octets utilisés par le système de fichier SPIFFS.
SPIFFS.usedBytes()
Renvoie l’espace utilisé par le fichier spécifié en octets
SPIFFS.remove(chemin)
Supprime le fichier en fonction de son chemin absolu. Renvoie vrai si le fichier a été supprimé avec succès.
SPIFFS.rename(pathFrom, pathTo)
Renomme le fichier de pathFrom à pathTo. Les chemins doivent être absolus. Renvoie true si le fichier a été renommé avec succès.
SPIFFS.end()
Démonte le système de fichier
Comment transférer des fichiers dans la zone mémoire SPIFFS ?
Il est possible de téléverser directement des fichiers dans le système de fichier SPIFFS à l’aide du plugin pour l’IDE Arduino ESP32 Sketch Data Upload.
Pour cela, il suffit de créer un dossier nommé data au même niveau que le fichier principal du projet Arduino. Il est préférable d’éviter de créer des sous-dossiers.
En effet, le système de fichier SPIFFS ne gère pas l’arborescence de fichier. Lors du transfert, les fichiers seront mis “à plat”, c’est à dire que le fichier prendra comme nom le chemin d’accès.
Pour en savoir plus, lisez ce tutoriel qui explique tout en détail.
Récupérer les informations de la zone SPIFFS et la liste des fichiers
Voici un petit exemple de code qui permet de récupérer les informations de la zone mémoire ainsi que la liste des fichiers présents dans la zone mémoire.
#include "SPIFFS.h"
void listFilesInDir(File dir, int numTabs = 1);
void setup() {
Serial.begin(112500);
delay(500);
Serial.println(F("Inizializing FS..."));
if (SPIFFS.begin()){
Serial.println(F("SPIFFS mounted correctly."));
}else{
Serial.println(F("!An error occurred during SPIFFS mounting"));
}
// Get all information of SPIFFS
unsigned int totalBytes = SPIFFS.totalBytes();
unsigned int usedBytes = SPIFFS.usedBytes();
Serial.println("===== File system info =====");
Serial.print("Total space: ");
Serial.print(totalBytes);
Serial.println("byte");
Serial.print("Total space used: ");
Serial.print(usedBytes);
Serial.println("byte");
Serial.println();
// Open dir folder
File dir = SPIFFS.open("/");
// List file at root
listFilesInDir(dir);
}
void listFilesInDir(File dir, int numTabs) {
while (true) {
File entry = dir.openNextFile();
if (! entry) {
// no more files in the folder
break;
}
for (uint8_t i = 0; i < numTabs; i++) {
Serial.print('\t');
}
Serial.print(entry.name());
if (entry.isDirectory()) {
Serial.println("/");
listFilesInDir(entry, numTabs + 1);
} else {
// display zise for file, nothing for directory
Serial.print("\t\t");
Serial.println(entry.size(), DEC);
}
entry.close();
}
}
void loop() {
}
Ouvrez le Moniteur série pour visualiser l’occupation, l’espace disponible est les fichiers SPIFFS stockés sur la mémoire flash.
Inizializing FS...
SPIFFS mounted correctly.
File system info.
Total space: 1374476byte
Total space used: 502byte
/test.txt 11
Comment écrire dans un fichier par programmation avec SPIFFS.h
On a vu comment créer un fichier depuis un ordinateur puis le téléverser depuis l’IDE Arduino.
La librairie SPIFFS.h met à disposition plusieurs méthodes simples pour accéder et manipuler les fichiers depuis un programme Arduino. Vous pouvez utiliser toutes les méthodes listées précédemment.
Ajouter ce code juste après le ligne file.close();
file = SPIFFS.open("/test.txt", "w");
if(!file){
// File not found | le fichier de test n'existe pas
Serial.println("Failed to open test file");
return;
} else {
file.println("Hello From ESP32 :-)");
file.close();
}
Que fait ce code ?
Cette fois, on ouvre le fichier avec l’option “w” pour indiquer qu’on souhaite modifier le fichier. Le contenu précédent sera effacé
Pour écrire dans un fichier, on peut utiliser les méthodes print() ou println(). La méthode println() ajoute un retour à la ligne. On l’utilisera pour créer un tableau de données par exemple.
Ici, on actualise le contenu précédent
file.println("Hello From ESP32 :-)");
Téléverser pour visualiser ce qui se passe
Comment ajouter des données à un fichier par programmation ?
Pour ajouter des données à un fichier, il suffit d’ouvrir de fichier avec l’option “a” (append) pour ajouter des données à la fin du fichier.
Si le fichier n’existe pas, il sera automatiquement créé.
Voici un petit exemple qui enregistre un compteur chaque seconde.
void loop(){
File file = SPIFFS.open("/counter.txt", "a");
if(!file){
// File not found | le fichier n'existe pas
Serial.println("Failed to open counter file");
return;
} else {
counter+=1;
file.println(counter);
file.close();
}
delay(1000);
}
Mises à jour
02/09/2020 Première publication de l’article
- ESP32, broches GPIO et fonctions associées. I/O, PWM, RTC, I2C, SPI, ADC, DAC
- M5Stack Atomic GPS. Tracker ESP32 TinyGPS++, export GPX sur carte SD, visualisation sur Google Maps ou VSCode
- Stocker des données sur une carte micro SD. Code Arduino compatible ESP32, ESP8266
- Débuter Arduino. Recevoir des commandes depuis le port série (compatible ESP32 ESP8266)
- Fonctions C++ print•println•printf•sprintf pour Arduino ESP32 ESP8266. Combiner•formater → port série
Avez-vous aimé cet article ?