|
| 1 | +--- |
| 2 | +title: SPIFFS Partition on Nano ESP32 |
| 3 | +description: Get started with the SPIFFS partition scheme on the Nano ESP32. |
| 4 | +author: Hannes Siebeneicher |
| 5 | +hardware: |
| 6 | + - hardware/03.nano/boards/nano-esp32 |
| 7 | +tags: [ESP32, SPIFFS, IDE] |
| 8 | +--- |
| 9 | + |
| 10 | +The SPIFFS (Serial Peripheral Interface Flash File System) is a file system designed to be used with NOR flash memory devices and microcontrollers that support the Serial Peripheral Interface (SPI) protocol such as the ESP32 found on the [Nano ESP32](https://store.arduino.cc/products/nano-esp32?queryID=undefined). |
| 11 | + |
| 12 | +***Before proceeding with the SPIFFS file system setup on Nano ESP, please be aware that the mounting instructions mentioned in a comment on the code from the packaged built-in example are tailored for specific older IDE versions such as IDE 1.8. These instructions might not be relevant to IDE 2.0, as it does not support the utilization of custom tools, which are unnecessary in this case.*** |
| 13 | + |
| 14 | +## Hardware & Software Needed |
| 15 | + |
| 16 | +- [Arduino Nano ESP32](https://store.arduino.cc/nano-esp32) |
| 17 | +- [Arduino IDE](https://www.arduino.cc/en/software) |
| 18 | +- [Arduino ESP32 Core](https://github.com/arduino/arduino-esp32) installed (done in the Arduino IDE). |
| 19 | + |
| 20 | +## Set Up SPIFFS File System |
| 21 | + |
| 22 | +Start by opening the **SPIFFS_Test example** by navigating to: |
| 23 | + |
| 24 | +- File > Examples > SPIFFS > SPIFFS_Test |
| 25 | + |
| 26 | +***The example is also included at the bottom (see [Example](#example)), together with an explanation of how the code work.*** |
| 27 | + |
| 28 | + |
| 29 | + |
| 30 | +Select the correct **Partition Scheme** by clicking: |
| 31 | + |
| 32 | +- Tools > Partition Scheme > With SPIFFS partition (advanced) |
| 33 | + |
| 34 | + |
| 35 | + |
| 36 | +Prepare your following these steps: |
| 37 | + |
| 38 | +- Take your **unplugged** board and connect a jumper cable between the **GND** and **B1** pins. |
| 39 | + |
| 40 | +- **Plug it in** and the RGB LED will turn on with a green or blue color. |
| 41 | + |
| 42 | +- While the **GND** and **B1** pins are shorted, press the white **RST** button on the top of the board to reset the board. |
| 43 | + |
| 44 | +- **Remove** the jumper cable. The RGB LED should stay on, in a purple or yellow color. |
| 45 | + |
| 46 | +Select the correct port: |
| 47 | + |
| 48 | + |
| 49 | + |
| 50 | +***If your board shows up as a generic ESP32 device go to Tools > Board and select "Arduino Nano ESP32" as well as the correct port under Tools > Port.*** |
| 51 | + |
| 52 | +Select the **Esptool as Programmer** by going to: |
| 53 | + |
| 54 | +- Tools > Programmer > Esptool |
| 55 | + |
| 56 | + |
| 57 | + |
| 58 | +**Burn the bootloader** by clicking: |
| 59 | + |
| 60 | +- Tools > Burn Bootloader |
| 61 | + |
| 62 | + |
| 63 | + |
| 64 | +We have now successfully changed the partition scheme and the final step is to upload a sketch using programmer and reset the board. |
| 65 | + |
| 66 | +Upload the sketch via **Using Programmer** by going to: |
| 67 | + |
| 68 | +- Sketch > Upload Using Programmer |
| 69 | + |
| 70 | + |
| 71 | + |
| 72 | +After the successful upload press the white **RST** button on the top of the board. You should see two ports in the drop-down menu, one showing a USB symbol and another one showing a cube. |
| 73 | + |
| 74 | +Select the port next to the USB symbol. |
| 75 | + |
| 76 | + |
| 77 | + |
| 78 | +Open the serial monitor and you should see the following output: |
| 79 | + |
| 80 | + |
| 81 | + |
| 82 | +***Note: It might take a short while for the messages to be printed. If you don't see any messages after one minute repeat the process.*** |
| 83 | + |
| 84 | +## Example |
| 85 | + |
| 86 | +As mentioned above the code is taken from **File > Examples > SPIFFS > SPIFFS_Test** and can also be found inside the IDE's example section. It showcases different features available when using the SPIFSF file system. |
| 87 | + |
| 88 | +```arduino |
| 89 | +#include "FS.h" |
| 90 | +#include "SPIFFS.h" |
| 91 | +
|
| 92 | +/* You only need to format SPIFFS the first time you run a |
| 93 | + test or else use the SPIFFS plugin to create a partition |
| 94 | + https://github.com/me-no-dev/arduino-esp32fs-plugin */ |
| 95 | +#define FORMAT_SPIFFS_IF_FAILED true |
| 96 | +
|
| 97 | +void listDir(fs::FS &fs, const char * dirname, uint8_t levels){ |
| 98 | + Serial.printf("Listing directory: %s\r\n", dirname); |
| 99 | +
|
| 100 | + File root = fs.open(dirname); |
| 101 | + if(!root){ |
| 102 | + Serial.println("- failed to open directory"); |
| 103 | + return; |
| 104 | + } |
| 105 | + if(!root.isDirectory()){ |
| 106 | + Serial.println(" - not a directory"); |
| 107 | + return; |
| 108 | + } |
| 109 | +
|
| 110 | + File file = root.openNextFile(); |
| 111 | + while(file){ |
| 112 | + if(file.isDirectory()){ |
| 113 | + Serial.print(" DIR : "); |
| 114 | + Serial.println(file.name()); |
| 115 | + if(levels){ |
| 116 | + listDir(fs, file.path(), levels -1); |
| 117 | + } |
| 118 | + } else { |
| 119 | + Serial.print(" FILE: "); |
| 120 | + Serial.print(file.name()); |
| 121 | + Serial.print("\tSIZE: "); |
| 122 | + Serial.println(file.size()); |
| 123 | + } |
| 124 | + file = root.openNextFile(); |
| 125 | + } |
| 126 | +} |
| 127 | +
|
| 128 | +void readFile(fs::FS &fs, const char * path){ |
| 129 | + Serial.printf("Reading file: %s\r\n", path); |
| 130 | +
|
| 131 | + File file = fs.open(path); |
| 132 | + if(!file || file.isDirectory()){ |
| 133 | + Serial.println("- failed to open file for reading"); |
| 134 | + return; |
| 135 | + } |
| 136 | +
|
| 137 | + Serial.println("- read from file:"); |
| 138 | + while(file.available()){ |
| 139 | + Serial.write(file.read()); |
| 140 | + } |
| 141 | + file.close(); |
| 142 | +} |
| 143 | +
|
| 144 | +void writeFile(fs::FS &fs, const char * path, const char * message){ |
| 145 | + Serial.printf("Writing file: %s\r\n", path); |
| 146 | +
|
| 147 | + File file = fs.open(path, FILE_WRITE); |
| 148 | + if(!file){ |
| 149 | + Serial.println("- failed to open file for writing"); |
| 150 | + return; |
| 151 | + } |
| 152 | + if(file.print(message)){ |
| 153 | + Serial.println("- file written"); |
| 154 | + } else { |
| 155 | + Serial.println("- write failed"); |
| 156 | + } |
| 157 | + file.close(); |
| 158 | +} |
| 159 | +
|
| 160 | +void appendFile(fs::FS &fs, const char * path, const char * message){ |
| 161 | + Serial.printf("Appending to file: %s\r\n", path); |
| 162 | +
|
| 163 | + File file = fs.open(path, FILE_APPEND); |
| 164 | + if(!file){ |
| 165 | + Serial.println("- failed to open file for appending"); |
| 166 | + return; |
| 167 | + } |
| 168 | + if(file.print(message)){ |
| 169 | + Serial.println("- message appended"); |
| 170 | + } else { |
| 171 | + Serial.println("- append failed"); |
| 172 | + } |
| 173 | + file.close(); |
| 174 | +} |
| 175 | +
|
| 176 | +void renameFile(fs::FS &fs, const char * path1, const char * path2){ |
| 177 | + Serial.printf("Renaming file %s to %s\r\n", path1, path2); |
| 178 | + if (fs.rename(path1, path2)) { |
| 179 | + Serial.println("- file renamed"); |
| 180 | + } else { |
| 181 | + Serial.println("- rename failed"); |
| 182 | + } |
| 183 | +} |
| 184 | +
|
| 185 | +void deleteFile(fs::FS &fs, const char * path){ |
| 186 | + Serial.printf("Deleting file: %s\r\n", path); |
| 187 | + if(fs.remove(path)){ |
| 188 | + Serial.println("- file deleted"); |
| 189 | + } else { |
| 190 | + Serial.println("- delete failed"); |
| 191 | + } |
| 192 | +} |
| 193 | +
|
| 194 | +void testFileIO(fs::FS &fs, const char * path){ |
| 195 | + Serial.printf("Testing file I/O with %s\r\n", path); |
| 196 | +
|
| 197 | + static uint8_t buf[512]; |
| 198 | + size_t len = 0; |
| 199 | + File file = fs.open(path, FILE_WRITE); |
| 200 | + if(!file){ |
| 201 | + Serial.println("- failed to open file for writing"); |
| 202 | + return; |
| 203 | + } |
| 204 | +
|
| 205 | + size_t i; |
| 206 | + Serial.print("- writing" ); |
| 207 | + uint32_t start = millis(); |
| 208 | + for(i=0; i<2048; i++){ |
| 209 | + if ((i & 0x001F) == 0x001F){ |
| 210 | + Serial.print("."); |
| 211 | + } |
| 212 | + file.write(buf, 512); |
| 213 | + } |
| 214 | + Serial.println(""); |
| 215 | + uint32_t end = millis() - start; |
| 216 | + Serial.printf(" - %u bytes written in %u ms\r\n", 2048 * 512, end); |
| 217 | + file.close(); |
| 218 | +
|
| 219 | + file = fs.open(path); |
| 220 | + start = millis(); |
| 221 | + end = start; |
| 222 | + i = 0; |
| 223 | + if(file && !file.isDirectory()){ |
| 224 | + len = file.size(); |
| 225 | + size_t flen = len; |
| 226 | + start = millis(); |
| 227 | + Serial.print("- reading" ); |
| 228 | + while(len){ |
| 229 | + size_t toRead = len; |
| 230 | + if(toRead > 512){ |
| 231 | + toRead = 512; |
| 232 | + } |
| 233 | + file.read(buf, toRead); |
| 234 | + if ((i++ & 0x001F) == 0x001F){ |
| 235 | + Serial.print("."); |
| 236 | + } |
| 237 | + len -= toRead; |
| 238 | + } |
| 239 | + Serial.println(""); |
| 240 | + end = millis() - start; |
| 241 | + Serial.printf("- %u bytes read in %u ms\r\n", flen, end); |
| 242 | + file.close(); |
| 243 | + } else { |
| 244 | + Serial.println("- failed to open file for reading"); |
| 245 | + } |
| 246 | +} |
| 247 | +
|
| 248 | +void setup(){ |
| 249 | + Serial.begin(115200); |
| 250 | + if(!SPIFFS.begin(FORMAT_SPIFFS_IF_FAILED)){ |
| 251 | + Serial.println("SPIFFS Mount Failed"); |
| 252 | + return; |
| 253 | + } |
| 254 | + |
| 255 | + listDir(SPIFFS, "/", 0); |
| 256 | + writeFile(SPIFFS, "/hello.txt", "Hello "); |
| 257 | + appendFile(SPIFFS, "/hello.txt", "World!\r\n"); |
| 258 | + readFile(SPIFFS, "/hello.txt"); |
| 259 | + renameFile(SPIFFS, "/hello.txt", "/foo.txt"); |
| 260 | + readFile(SPIFFS, "/foo.txt"); |
| 261 | + deleteFile(SPIFFS, "/foo.txt"); |
| 262 | + testFileIO(SPIFFS, "/test.txt"); |
| 263 | + deleteFile(SPIFFS, "/test.txt"); |
| 264 | + Serial.println( "Test complete" ); |
| 265 | +} |
| 266 | +
|
| 267 | +void loop(){ |
| 268 | +
|
| 269 | +} |
| 270 | +``` |
| 271 | + |
| 272 | +### How It Works? |
| 273 | + |
| 274 | +- First, the **necessary libraries** are included: |
| 275 | + |
| 276 | +```arduino |
| 277 | +#include "FS.h" |
| 278 | +#include "SPIFFS.h" |
| 279 | +``` |
| 280 | + |
| 281 | +- The constant `FORMAT_SPIFFS_IF_FAILED` is used to specify whether the SPIFFS file system should be formatted if it fails to mount. If it's `true`, the file system will be formatted: |
| 282 | + |
| 283 | +```arduino |
| 284 | +#define FORMAT_SPIFFS_IF_FAILED true |
| 285 | +``` |
| 286 | + |
| 287 | +- The code consists of several **functions** defined in the code showcasing **different features** such as: |
| 288 | + |
| 289 | + `void listDir()` = List Files |
| 290 | + |
| 291 | + `void readFile()` = Read Files |
| 292 | + |
| 293 | + `void writeFile()` = Write Files |
| 294 | + |
| 295 | + `void appendFile()` = Append a message to an existing file |
| 296 | + |
| 297 | + `void renameFile()` = Rename Files |
| 298 | + |
| 299 | + `void deleteFile()` = Delete Files |
| 300 | + |
| 301 | + `void testFileIO()` = Testing a file's input and output by writing a large amount of data and then reading it. |
| 302 | + |
| 303 | +- Before calling all the functions mentioned above **two things** are done inside `setup()`: |
| 304 | +1. The serial communication is initialized with a baud rate of 115200. |
| 305 | +2. The SPIFFS file system is mounted and if `FORMAT_SPIFFS_IF_FAILED` is `true` it's formatted. |
| 306 | + |
| 307 | +```arduino |
| 308 | +void setup(){ |
| 309 | + Serial.begin(115200); |
| 310 | + if(!SPIFFS.begin(FORMAT_SPIFFS_IF_FAILED)){ |
| 311 | + Serial.println("SPIFFS Mount Failed"); |
| 312 | + return; |
| 313 | + } |
| 314 | + ... |
| 315 | +} |
| 316 | +``` |
| 317 | + |
| 318 | +Lastly, all functions are called with parameters: |
| 319 | + |
| 320 | +```arduino |
| 321 | +void setup(){ |
| 322 | + Serial.begin(115200); |
| 323 | + if(!SPIFFS.begin(FORMAT_SPIFFS_IF_FAILED)){ |
| 324 | + Serial.println("SPIFFS Mount Failed"); |
| 325 | + return; |
| 326 | + } |
| 327 | + |
| 328 | + listDir(SPIFFS, "/", 0); |
| 329 | + writeFile(SPIFFS, "/hello.txt", "Hello "); |
| 330 | + appendFile(SPIFFS, "/hello.txt", "World!\r\n"); |
| 331 | + readFile(SPIFFS, "/hello.txt"); |
| 332 | + renameFile(SPIFFS, "/hello.txt", "/foo.txt"); |
| 333 | + readFile(SPIFFS, "/foo.txt"); |
| 334 | + deleteFile(SPIFFS, "/foo.txt"); |
| 335 | + testFileIO(SPIFFS, "/test.txt"); |
| 336 | + deleteFile(SPIFFS, "/test.txt"); |
| 337 | + Serial.println( "Test complete" ); |
| 338 | +} |
| 339 | +``` |
| 340 | + |
| 341 | +- All messages printed on the serial monitor are defined in the respective function, except "Test Complete" which printed by `setup()` once everything is done. |
0 commit comments