ESP32 Flash Memory (Save Permanent Data) – Arduino IDE

In this tutorial, you’ll learn how to access the ESP32 Flash Memory for read and write operations in Arduino IDE. It’s one way of doing it without using any additional libraries which can be suitable for simple applications that don’t require having a file system whatsoever.

In a previous EEPROM Library Tutorial, we discussed how the EEPROM library works and that it’s actually using the Flash memory NVS driver under the hood to emulate and provide the same functionality that we expect from an EEPROM library. However, it’s not the recommended way for new projects as the library is currently considered deprecated and replaced by a new library called Preferences.

???? Also Read
ESP32 EEPROM Library Examples Tutorial Arduino

This article will give more in-depth information about ESP32 Flash memory and using the EEPROM library to read and write any data type to the ESP32 Flash memory.

Before proceeding with this tutorial, you should have installed the ESP32 Arduino Core in your Arduino IDE to be able to compile and build projects for ESP32 in Arduino IDE. Follow the tutorial below to get started if you haven’t done that already.

If you’re just starting with ESP32, it’s highly recommended to begin with the following tutorial to kickstart your journey with ESP32 microcontrollers. Then, go to the second link which directs you to the main page for ESP32 Tutorials Series, where you’ll find all ESP32 tutorials ordered and categorized in a logical way that guarantees you systematic progress in learning ESP32 programming and IoT.

❕ Note

Please, be advised that the method included in this tutorial gives you full access to the whole SPI Flash memory of the ESP32. Things can go wrong easily if you attempted overwriting a memory location out of the NVS data partition. We’ll stick to some guidelines that you’ll learn hereafter in this tutorial, but just be acknowledged that it can be risky if not done carefully.

Table of Contents

  1. ESP32 Flash Memory
  2. ESP32 Flash Memory Custom Partition Table (in Arduino)
  3. ESP32 Flash Memory Read Write Functions
  4. ESP32 Flash Memory Example (Arduino IDE) – Strings
  5. ESP32 Flash Read Write Example (Arduino IDE) – Float
  6. ESP32 Flash Memory Example (Arduino IDE)
  7. Download Attachments
  8. Concluding Remarks

ESP32 Flash Memory

The ESP32 has an external SPI Flash memory that’s by default 4MB in size. You can order ESP32 modules with even 8MB or 16MB as well. But generally speaking, we’ll say it’s 4MB. And those 4MB of Flash memory space are divided into some partitions for various uses. You can however add-remove-modify those partitions as per your application’s need, and I’ll show you how to do it in a very easy way in this tutorial as well. The ESP32 default Flash partition table has:

  • NVS: for user data storage
  • 2x App Partitions: for user program storage + ability to perform OTA firmware updates
  • OTAdata: used for OTA (Over-The-Air) firmware updates
  • SPIFFS: SPI Flash File System for file storage and management
  • CoreDump: for debugging and diagnostics purposes

We’re specifically interested in the NVS partition, which is meant to be used for user data storage. It has a space of 0x5000 bytes (20kB), and it has an address offset of 0x9000. This means any write operation to the Flash memory at the absolute address 0x9000 will go into the NVS partition and you can continue from that address up to the end of the NVS partition.

Here is the default partition table for ESP32 Arduino Flash Memory (check the reference).

Applications For ESP32 Flash Memory

Non-Volatile Memories (NVS) like “Flash” are typically used when we need to save some data and need the microcontroller to remember it even if it lost power or got restarted. Typical use cases for data that we need to store in NVS include the following application examples:

  • Passwords
  • WiFi Credentials
  • User Configuration
  • App-Level Parameters
  • Sensor Last Reading
  • State Variables (for some state machines)
  • Sensor Calibration Data
  • and much more…

ESP32 Flash Memory Write Cycles

Generally speaking, Flash memories tend to have 10x times fewer write/erase cycles than EEPROM memory. A typical EEPROM can have 100,000 up to 1,000,000 write/erase cycles while FLASH memories have typical write/erase cycles of around 10,000 up to 100,000 at maximum.

Therefore, we’re expecting to have around 10,000 write cycles for each memory location in the ESP32 Flash Memory. In other words, if you keep writing a byte of data to the exact same address location in the Flash memory, it’d take only 10,0000 write operations to permanently damage that memory location forever.

❕ Note

Please, be cautious when using any sort of NVS memory as it can easily get damaged permanently if you’re not wisely using it. Try to avoid unnecessary regular writing cycles to the NVS unless it’s mandatory. Better library implementations do have some wear and tear leveling algorithms to distribute the memory utilization across all of the sectors so you have a longer FLASH memory lifetime.


ESP32 Flash Memory Custom Partition Table (in Arduino)

After doing some tests, I’ve found out that the NVS Partition is probably erased at startup after a hard reset, it doesn’t retain what was last written to it. However, I could successfully read and write a lot of data and use the full 20kB memory partition space during runtime. But, after a hard reset, everything gets whipped out for no apparent reason.

Therefore, we’ll create our own custom new partition (let’s call it NVM non-volatile-memory) and will make it also 20kB in size. You can obviously change it however you want to make it larger or smaller based on your application’s memory demand.

First, let’s recall the ESP32 Arduino default Flash Partition Table.

I’ll take out 0x5000 bytes (which is 20kB) from the spiffs partition to create my new NVM memory partition. Therefore the new Flash memory partition table will look like this.

ESP32 Flash Memory Custom Partition Table Arduino IDE

As you can see, I’ve created a new partition called NVM with a size of 0x5000 bytes (20kB) which starts at the address 0x290000. The table above is simply a .csv file with a specific name. It has to have the name (partitions.csv) and it has also to exist in the same folder with the Arduino sketch for your project to be picked up automatically during the build process.

This is how you can simply override the default ESP32 Flash memory partition table in Arduino IDE and create your custom partitions or even adjust the memory size of any particular partition you want.

❕ Note

If you’re going to create your own new partitions or modify the default partitions’ sizes, please pay attention to the offset addresses and the total memory space which must not exceed the 4MB space if your ESP32 board has a 4MB flash or whatever size it is. Also, note that (each partition’s offset address = the previous partition’s offset + the previous partition’s size).

❕ Note

The app0 partition is where your code will finally exist in the Flash memory and it should start exactly at the 64kB location. Writing to this partition will distort the actual code that’s currently running on the target microcontroller and it’ll cause runtime errors that end with crashing the software and the microcontroller will keep restarting. No need to test this, I’ve done the test for you!


ESP32 Flash Memory Read Write Functions

There is a couple of functions in the built-in ESP.h that provide us direct access to the full SPI Flash Memory to perform read and write operations to literally any address in the entire memory space. This means it’s our responsibility to check the validity of the address which we’re writing to.

To use those 2 APIs (Functions), you have to first include the <Arduino.h> built-in header file. No libraries are required for this method as stated earlier.

 

ESP32 Flash Write

This is the ESP32 Flash Write API (Function)

 

It takes the offset from the beginning of the Flash memory space which is basically the address you want to write to, a pointer to the data to be written, and the size of the data (number of bytes). It’s worth noting that we need to handle the addressing and offset checking on our own, and also the data type conversion from and to (uint32_t) which is what this function expects as an input.

Moreover, we need also to keep track of how many bytes have been written to the memory to determine what should be the address value for the next piece of data to be written.

For example, let’s say we want to write a uint32_t myVar to the Flash memory at address zero, here is how to do it in code.

 

Note that we have to add the offset value to the beginning of the NVS partition in the Flash memory. And that’s how we write a variable to the ESP32 Flash memory without any additional libraries.

ESP32 Flash Read

Similarly, we’ll use the following API (Function) to read a memory location from the Flash memory. And note that we have to know the exact size of the data element that we want to retrieve from the Flash.

 

And that’s simply how to read and write to the ESP32 Flash memory without any additional libraries and have full access to the entire Flash memory space.

Generic Flash Read Write Wrappers

Those are two wrapper functions that I’ve come up with to be able to write and read any data type in the ESP32 Flash memory without worrying about the data type, size, or whatever.

 

To further demonstrate how they work, we’ll have a couple of example projects before we move to the conclusion.

❕ Note

A successful FlashWrite operation with the given API in ESP.h has to be preceded by an erase operation for the whole sector before attempting to write any new data. A better implementation could be to follow the sequence (read-modify-erase-write) of a complete sector each time a write data operation is required.


ESP32 Flash Memory Example (Arduino IDE) – Strings

In this example, we’ll test the Flash memory by saving and reading a string to the Flash memory in the setup() function.

Example Code

Here is the full code listing for this example.

 

partitions.csv File

Don’t forget that we need to have our custom partitions.csv file in the same folder with the sketch to access the NVM partition correctly.

ESP32-Flash-Memory-Artduino-Examples-Custom-Partitions

Code Explanation

The code above does simple a write operation to the Flash memory which sends a string called StrIn and then read from the same address into a new string variable StrOut and then we print the latter one to see if it’s read successfully from the memory or it’s going to print some garbage.

Testing Results

Here is what I get on the serial monitor after any hard reset. As expected the string is being read successfully from the Flash memory.

ESP32 Flash Memory Arduino Tutorial


ESP32 Flash Read Write Example (Arduino IDE) – Float

In this example, we’ll test the Flash memory by saving and reading a Float variable to the Flash memory in the setup() function.

Example Code

Here is the full code listing for this example.

 

partitions.csv File

Don’t forget that we need to have our custom partitions.csv file in the same folder with the sketch to access the NVM partition correctly.

ESP32-Flash-Memory-Artduino-Examples-Custom-Partitions

Code Explanation

The code above does simple a write operation to the Flash memory which sends a Float variable called Pi and then read from the same address into a new Float variable Read_Pi and then we print the latter one to see if it’s read successfully from the memory or it’s going to print some garbage.

Testing Results

Here is what I get on the serial monitor after any hard reset. As expected the Float is being read successfully from the Flash memory.

ESP32-Flash-Arduino-Example-Float-Variable


ESP32 Flash Memory Example (Arduino IDE)

In this example, we’ll test the Flash memory by saving the last LED state. The LED is toggled by a push button, and whenever its state changes, the last state will be saved to the Flash. We’ll reset the ESP32 board and it should retrieve the last saved state from the Flash memory at startup.

Wiring

Here is the wiring diagram for this example. It has a push button input and output LED only.

Example Code

Here is the full code listing for this example.

 

partitions.csv File

Don’t forget that we need to have our custom partitions.csv file in the same folder with the sketch to access the NVM partition correctly.

ESP32-Flash-Memory-Artduino-Examples-Custom-Partitions

Code Explanation

The code example does simply read the button input pin and debounces it to make sure it’s not picking up any noise. And toggle the LED if the button is actually pressed. The LED toggle event does also a write operation to the FLASH_Address location and saves the current ledState in the FLASH memory.

We start by including the ESP.h or Arduino.h

 

Then, we define the offset address for the new flash partition we’ve created (NVM). And also define the GPIO pins we’ll be using.

 

We also define some global variables to save the LED state, and button state, and perform the button debouncing logic.

 

setup()

in the setup() function, we initialize serial communication for debugging and the pin modes.

 

We also read the last saved LED state from the FLASH memory and apply it to the LED output. This happens only at startup, hence it’s done in the setup() function.

 

loop()

in the loop() function, it’s mostly about reading the button and debouncing it. Once, it’s clear that the button is held HIGH and it’s not a noise, we take the LED toggle action + saving the current LED state to the EEPROM (Flash Memory).

 

Testing Results

Here is a short demo video for the testing result of this example. Note that the ESP32 is remembering the last LED state after every reset operation. And that’s the most simple application for using non-volatile memories.


Parts List

Here is the full components list for all parts that you’d need in order to perform the practical LABs mentioned here in this article and for the whole ESP32 series of tutorials found here on DeepBlueMbedded. Please, note that those are affiliate links and we’ll receive a small commission on your purchase at no additional cost to you, and it’d definitely support our work.

Download Attachments

You can download all attachment files for this Article/Tutorial (project files, schematics, code, etc..) using the link below. Please consider supporting my work through the various support options listed in the link down below. Every small donation helps to keep this website up and running and ultimately supports our community.


Concluding Remarks

To conclude this tutorial, we’ll highlight the fact that ESP32 Flash memory can be accessed without additional libraries but it’s going to take some work to implement what’s needed to handle data alignment, large arrays, and keeping track of the used addressed and sectors write/erase operations. There is a lot to take care of and the example functions provided in this tutorial are just basic blocks to build upon to achieve what you need in your application.

There is however a new library for ESP32 Flash memory handling called Prefrences.h which has replaced the older ESP32 EEPROM Library that we’ve discussed in a previous tutorial. It’s worth checking out if you want to use something robust and not have to deal with a lot of internal details of ESP32 NVS driver implementations.

Share This Page With Your Network!
Join Our +25,000 Newsletter Subscribers!

Stay Updated With All New Content Releases. You Also Get Occasional FREE Coupon Codes For Courses & Other Stuff!

Photo of author
Author
Khaled Magdy
Embedded systems engineer with several years of experience in embedded software and hardware design. I work as an embedded SW engineer in the Automotive & e-Mobility industry. However, I still do Hardware design and SW development for DSP, Control Systems, Robotics, AI/ML, and other fields I'm passionate about.
I love reading, writing, creating projects, and teaching. A reader by day and a writer by night, it's my lifestyle. I believe that the combination of brilliant minds, bold ideas, and a complete disregard for what is possible, can and will change the world! I will be there when it happens, will you?

Leave a Comment