ESP32: integrated FFat (FAT/exFAT) FileSystem – 6

Spread the love

ESP32 integrated FatFS FileSystem
ESP32 integrated FatFS FileSystem

We continue to explore e32 devices, very powerful microcontrollers. The possibilities offered by the integrated Flash SPI are many, but the first problem is certainly choosing an adequate filesystem, each of these has characteristics that make them unique and useful in various aspects. The default filesystem for ESP32 has officially become FAT, the most powerful and stable, but also resource-hungry, with the same files it takes up more space than SPIFFS and LittleFS.

You can find some type of ESP32 on ESP32 Dev Kit v1 - TTGO T-Display 1.14 ESP32 - NodeMCU V3 V2 ESP8266 Lolin32 - NodeMCU ESP-32S - WeMos Lolin32 - WeMos Lolin32 mini - ESP32-CAM programmer - ESP32-CAM bundle - ESP32-WROOM-32 - ESP32-S

FFat FatFS File System

Function Block diagram Espressif esp32 Wi-Fi Bluetooth Microcontroller
Function Block diagram Espressif esp32 Wi-Fi Bluetooth Microcontroller

SPIFFS is the original filesystem and is ideal for space and RAM constrained applications that utilize many small files and care about static and dynamic wear levelling and don’t need true directory support. Filesystem overhead on the flash is minimal as well.

FatFs is a generic FAT/exFAT filesystem module for small embedded systems. The FatFs module is written in compliance with ANSI C (C89) and completely separated from the disk I/O layer. Therefore it is independent of the platform. It can be incorporated into small microcontrollers with limited resource.

The FFAT module uses 8KB plus 4KB per concurrent file that can be opened. By default, it allows 10 files to be opened, which means it uses 48KB. IF you want to reduce its memory use, you can tell it to only support one file, and you will save 36KB, leaving you with only 12KB used.

if (!FFat.begin(0, "", 1)) die("Fat FS mount failed. Not enough RAM?");

Because there are directories, the open method behaves differently than SPIFFS. Whereas SPIFFS will return files in “subdirectories” when you traverse a File::openNextFile() (because they really aren’t subdirs but simply files with “/”s in their names), FFat will only return files in the specific subdirectory. This mimics the POSIX behavior for directory traversal most C programmers are used to.

In this flash memory ESP stores the program. Along with program you can store your files on it. Limitation of this memory is it has only 10000 (ten thousand) write cycles.

Sketch OTA update File system EEPROM WiFi config

Add file from IDE to FFat

This operation without an extension for the Arduino IDE is not so simple, but here we are going to explain the simpliest way.

First you must download the plugin for Arduino IDE here.

Than you must find your Shetckbook folder, so you must go to File --> Preferences, in that screen you can find at the top of window the Sketchbook location.

Sketchbook Location, additional file Arduino IDE
Preferences window

Now you must create (if not exist) the folder tools\ESP32FS\tool and add the jar file esp32fs.jar there.

Arduino IDE esp32 SPIFFS Sketch Data Upload folder jar
Arduino IDE esp32 FFat Sketch Data Upload folder jar

Now restart the IDE and on Tools menu you can find new menu line ESP32 Sketch Data Upload.

Arduino IDE esp32 SPIFFS Sketch Data Upload
Arduino IDE esp32 FFat Sketch Data Upload

This plugin was able to manage 3 type of filesystem, and can substitute the other (like SPIFFS or LittleFS), when you click on “ESP32 Sketch Data Upload” a popup ask you what operation you need to do

esp32 SPIFFS LittleFS FatFS file uploader from Arduino IDE
esp32 SPIFFS LittleFS FatFS file uploader from Arduino IDE

The partition table is different from the SPIFFS, therefore, if specified, you must select the FatFS partition scheme and, if the filesystem is not specified in the microcontroller options you have to keep in mind that from version <= 1.0.4 a filesystem will be set SPIFFS, from version 1.0.5 onwards an FFat filesystem will be set up, but you can use a simple workaround to select a different filesystem, just select the generic card and configure it as the specified card.

From ESP32 core version <= 1.0.4 a default filesystem will be set SPIFFS, from version 1.0.5 onwards will be FFat filesystem

Therefore for WeMos LOLIN32 and version 1.0.4 of the ESP32 core I will select the parameters for the FFat as you can see in this image:

esp32 select FatFS partition type
esp32 select FatFS partition type

Add mkfatfs file

If you can’t upload the data you must add mkfatfs.exe file on the relative folder.

You must download mkfatfsfs from GitHub. In my case the version for Windows 10 64bit mkfatfs.rar.

Then you must open the preferences folder

ESP32 S2 download Arduino IDE preferences folder
ESP32 S2 download Arduino IDE preferences folder

and the complete folder

<preferences folder>/packages/esp32/hardware/esp32/1.0.5/tools

where the 1.0.5 is the current version installed of esp32 core, then copy the file mkfatfs.exe and the other files in the same folder of espota and esptool.

esp32 FatFS mkfatfs position on Arduino IDE
esp32 FatFS mkfatfs position on Arduino IDE

Create data folder

On Arduino IDE do Ctrl+K to open a filebrowser on directory of the sketch.
Create a directory data where you are going to put the data you want to upload.

Sketch to upload data on FatFS on esp8266: directory structure

Set the size of FFat on Tools --> Flash size and set the size of your Microcontroller filesystem.

Upload your sketch, and than click on ESP32 Sketch Data Upload.

Now go to the example sketch to check if all is OK.

Commands

There are some standard command that you can use with this filesystem

FFat.begin(formatIfNeeded = false)
This method mounts FFat file system and It must be called before any other FS APIs are used. formatIfNeeded set to true format the filesystem if needed. Returns true if file system was mounted successfully, false otherwise.

FFat.format()
Formats the file system. Returns true if formatting was successful.

FFat.open(path, mode)
Opens a file. path should be an absolute path starting with a slash (e.g. /dir/filename.txt). mode is a string specifying access mode. It can be one of “r”, “w”, “a”. Meaning of these modes is the same as for fopen C function.
Returns File object. To check whether the file was opened successfully, use the boolean operator.

FFat.exists(path)
Returns true if a file with given path exists, false otherwise.

FFat.remove(path): Deletes the file given its absolute path. Returns true if file was deleted successfully.

FFat.rename(pathFrom, pathTo)
Renames file from pathFrom to pathTo. Paths must be absolute. Returns true if file was renamed successfully.

FFat.mkdir(path):
Create a new folder. Returns true if the directory creation succeeded, false otherwise.

FFat.rmdir(path):
Remove directory. Returns true if the directory was successfully removed, false otherwise.

FFat.totalBytes()
Return the total bytes enabled on FFat. Returns bytes.

FFat.usedBytes()
Return the total used bytes enabled on FFat. Returns bytes.

file.seek(offset, mode)
This function behaves like fseek C function. Depending on the value of mode, it moves current position in a file as follows:

  • if mode is SeekSet, position is set to offset bytes from the beginning.
  • if mode is SeekCur, current position is moved by offset bytes.
  • if mode is SeekEnd, position is set to offset bytes from the end of the file.
  • Returns true if position was set successfully.

file.position()
Returns the current position inside the file, in bytes.

file.size()
Returns file size, in bytes.

file.name()
Returns file name, as const char*.

file.close()
Close the file.

file.getLastWrite()
Epoch time of last write (use internal time to manage date).

file.isDirectory()
Return if It’s directory

file.openNextFile()
Set next file pointer in the directory.

file.rewindDirectory()
Restart the pointer to the first file of the directory.

Library

The library is placed in the builtin core, so you don’t download nothing.

Pratical examples

Here a sketch to get info and check all file in your FatFS.

/*
 *  ESP32
 *  FFat get info, read dir and show all file uploaded
 *  add a data folder to use with ESP32 Sketch data uploader
 *  by Mischianti Renzo <https://mischianti.org>
 *
 *  https://mischianti.org
 *
 */

#include "Arduino.h"
#include "FS.h"
#include "FFat.h"

void printDirectory(File dir, int numTabs = 3);

void setup()
{
	Serial.begin(115200);

	delay(500);

	Serial.println(F("Inizializing FS..."));
	if (FFat.begin()){
		Serial.println(F("done."));
	}else{
		Serial.println(F("fail."));
	}

	// To format all space in FFat
	// FFat.format()

	// Get all information of your FFat

	unsigned int totalBytes = FFat.totalBytes();
	unsigned int usedBytes = FFat.usedBytes();
	unsigned int freeBytes  = FFat.freeBytes();

	Serial.println("File sistem info.");

	Serial.print("Total space:      ");
	Serial.print(totalBytes);
	Serial.println("byte");

	Serial.print("Total space used: ");
	Serial.print(usedBytes);
	Serial.println("byte");

	Serial.print("Total space free: ");
	Serial.print(freeBytes);
	Serial.println("byte");

	Serial.println();

	// Open dir folder
	File dir = FFat.open("/");
	// Cycle all the content
	printDirectory(dir);
}

void loop()
{

}

void printDirectory(File dir, int numTabs) {
  while (true) {

    File entry =  dir.openNextFile();
    if (! entry) {
      // no more files
      break;
    }
    for (uint8_t i = 0; i < numTabs; i++) {
      Serial.print('\t');
    }
    Serial.print(entry.name());
    if (entry.isDirectory()) {
      Serial.println("/");
      printDirectory(entry, numTabs + 1);
    } else {
      // files have sizes, directories do not
      Serial.print("\t\t");
      Serial.println(entry.size(), DEC);
    }
    entry.close();
  }
}

The result of the inquity

Inizializing FS...
done.
File sistem info.
Total space:      1478656byte
Total space used: 81920byte
Total space free: 1396736byte

			/bombo.png		44236
			/colori.svg		19086
			/other/
				/other/bn.svg		8493

Here a Sketch with more practical commands, write a string to a file, read all the contents of the file, go to the ninth byte of the file and read the data from there.

/*
 *  ESP32
 *  FFat write, read and seek file
 *  by Mischianti Renzo <https://mischianti.org>
 *
 *  https://mischianti.org/
 *
 */
#include "Arduino.h"
#include "FFat.h"

void setup()
{
  Serial.begin(115200);

  delay(500);

  Serial.println(F("Inizializing FS..."));
  if (FFat.begin()){
    Serial.println(F("done."));
  }else{
    Serial.println(F("fail."));
  }

  // To remove previous test
  // FFat.remove(F("/testCreate.txt"));

  File testFile = FFat.open(F("/testCreate.txt"), "w");

  if (testFile){
    Serial.println("Write file content!");
    testFile.print("Here the test text!!");

    testFile.close();
  }else{
    Serial.println("Problem on create file!");
  }

  testFile = FFat.open(F("/testCreate.txt"), "r");
  if (testFile){
    Serial.println("Read file content!");
    /**
     * File derivate from Stream so you can use all Stream method
     * readBytes, findUntil, parseInt, println etc
     */
    Serial.println(testFile.readString());
    testFile.close();
  }else{
    Serial.println("Problem on read file!");
  }

  testFile = FFat.open(F("/testCreate.txt"), "r");
  if (testFile){
    /**
     * mode is SeekSet, position is set to offset bytes from the beginning.
     * mode is SeekCur, current position is moved by offset bytes.
     * mode is SeekEnd, position is set to offset bytes from the end of the file.
     * Returns true if position was set successfully.
     */
    Serial.println("Position inside the file at 9 byte!");
    testFile.seek(9, SeekSet);

    Serial.println("Read file content!");
    Serial.println(testFile.readString());
    testFile.close();
  }else{
    Serial.println("Problem on read file!");
  }


}

void loop()
{

}

Here the result of the sketch

Inizializing FS...
done.
Write file content!
Read file content!
Here the test text!!
Position inside the file at 9 byte!
Read file content!
test text!!

Thanks

  1. ESP32: pinout, specs and Arduino IDE configuration
  2. ESP32: integrated SPIFFS Filesystem
  3. ESP32: manage multiple Serial and logging
  4. ESP32 practical power saving
    1. ESP32 practical power saving: manage WiFi and CPU
    2. ESP32 practical power saving: modem and light sleep
    3. ESP32 practical power saving: deep sleep and hibernation
    4. ESP32 practical power saving: preserve data, timer and touch wake up
    5. ESP32 practical power saving: external and ULP wake up
    6. ESP32 practical power saving: UART and GPIO wake up
  5. ESP32: integrated LittleFS FileSystem
  6. ESP32: integrated FFat (Fat/exFAT) FileSystem
  7. ESP32-wroom-32
    1. ESP32-wroom-32: flash, pinout, specs and IDE configuration
  8. ESP32-CAM
    1. ESP32-CAM: pinout, specs and Arduino IDE configuration
    2. ESP32-CAM: upgrade CamerWebServer with flash features
  9. ESP32: use ethernet w5500 with plain (HTTP) and SSL (HTTPS)
  10. ESP32: use ethernet enc28j60 with plain (HTTP) and SSL (HTTPS)
  11. How to use SD card with esp32
  12. esp32 and esp8266: FAT filesystem on external SPI flash memory
  1. Firmware and OTA update management
    1. Firmware management
      1. ESP32: flash compiled firmware (.bin)
      2. ESP32: flash compiled firmware and filesystem (.bin) with GUI tools
    2. OTA update with Arduino IDE
      1. ESP32 OTA update with Arduino IDE: filesystem, firmware, and password
    3. OTA update with Web Browser
      1. ESP32 OTA update with Web Browser: firmware, filesystem, and authentication
      2. ESP32 OTA update with Web Browser: upload in HTTPS (SSL/TLS) with self-signed certificate
      3. ESP32 OTA update with Web Browser: custom web interface
    4. Self OTA uptate from HTTP server
      1. ESP32 self OTA update firmware from the server
      2. ESP32 self OTA update firmware from the server with version check
      3. ESP32 self-OTA update in HTTPS (SSL/TLS) with trusted self-signed certificate
    5. Non-standard Firmware update
      1. ESP32 firmware and filesystem update from SD card
      2. ESP32 firmware and filesystem update with FTP client
  1. Integrating LAN8720 with ESP32 for Ethernet Connectivity with plain (HTTP) and SSL (HTTPS)
  2. Connecting the EByte E70 to ESP32 c3/s3 devices and a simple sketch example
  3. ESP32-C3: pinout, specs and Arduino IDE configuration


Spread the love

Leave a Reply

Your email address will not be published. Required fields are marked *