Skip to content

Commit 074b952

Browse files
Add FatFS and FatFSUSB - Wear-Leveled FTL based FAT filesystem for onboard flash (#2028)
* Add FatFS for onboard flash use/sharing of FAT * Move all to "fatfs" namespace The FatFS library defines commonly used names like WORD which could conflict with user code otherwise. * Restyle * FTL-based, wear-leveling FatFS with USB export Allow using FAT filesystem with onboard flash in a safer, wear-leveled way and to export the onboard flash to the host as a USB drive for easy data transfer. * Update documentation * Fix submodule reference * Don't spellehcek ChaN FatFS files * Disable FTL debugging * More codespell skips * Move to latest SPIFTL library * Allow using raw flash instead of FTL * Remove unneeded static FIL 4k allocation * Expose FAT FS format configuration options * Update documentation * Remove USB partial flash rewrites * Remove unneeded dups of FatFS sources Leave the LICENSE.md and README.md to point to upstream. * Clean up comments
1 parent 11dfb2c commit 074b952

25 files changed

+26129
-8
lines changed

.github/workflows/pull-request.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ jobs:
2424
- name: Run codespell
2525
uses: codespell-project/actions-codespell@master
2626
with:
27-
skip: ./ArduinoCore-API,./libraries/ESP8266SdFat,./libraries/Adafruit_TinyUSB_Arduino,./libraries/LittleFS/lib,./tools/pyserial,./pico-sdk,./.github,./docs/i2s.rst,./cores/rp2040/api,./libraries/FreeRTOS,./tools/libbearssl/bearssl,./include,./libraries/WiFi/examples/BearSSL_Server,./ota/uzlib,./libraries/http-parser/lib,./libraries/WebServer/examples/HelloServerBearSSL/HelloServerBearSSL.ino,./libraries/HTTPUpdateServer/examples/SecureBearSSLUpdater/SecureBearSSLUpdater.ino,./.git
27+
skip: ./ArduinoCore-API,./libraries/ESP8266SdFat,./libraries/Adafruit_TinyUSB_Arduino,./libraries/LittleFS/lib,./tools/pyserial,./pico-sdk,./.github,./docs/i2s.rst,./cores/rp2040/api,./libraries/FreeRTOS,./tools/libbearssl/bearssl,./include,./libraries/WiFi/examples/BearSSL_Server,./ota/uzlib,./libraries/http-parser/lib,./libraries/WebServer/examples/HelloServerBearSSL/HelloServerBearSSL.ino,./libraries/HTTPUpdateServer/examples/SecureBearSSLUpdater/SecureBearSSLUpdater.ino,./.git,./libraries/FatFS/lib/fatfs,./libraries/FatFS/src/diskio.h,./libraries/FatFS/src/ff.cpp,./libraries/FatFS/src/ffconf.h,./libraries/FatFS/src/ffsystem.cpp,./libraries/FatFS/src/ff.h
2828
ignore_words_list: ser,dout
2929

3030
# Consistent style

.gitmodules

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,3 +37,6 @@
3737
[submodule "libraries/http_parser/lib/http-parser"]
3838
path = libraries/http-parser/lib/http-parser
3939
url = https://github.com/nodejs/http-parser.git
40+
[submodule "libraries/FatFS/lib/SPIFTL"]
41+
path = libraries/FatFS/lib/SPIFTL
42+
url = https://github.com/earlephilhower/SPIFTL.git

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,8 @@ The installed tools include a version of OpenOCD (in the pqt-openocd directory)
253253
* [http-parser](https://github.com/nodejs/http-parser) is copyright Joyent, Inc. and other Node contributors.
254254
* WebServer code modified from the [ESP32 WebServer](https://github.com/espressif/arduino-esp32/tree/master/libraries/WebServer) and is copyright (c) 2015 Ivan Grokhotkov and others.
255255
* [Xoshiro-cpp](https://github.com/Reputeless/Xoshiro-cpp) is copyright (c) 2020 Ryo Suzuki and distributed under the MIT license.
256+
* [FatFS low-level filesystem](http://elm-chan.org/fsw/ff/) code is Copyright (C) 2024, ChaN, all rights reserved.
257+
256258
257259
-Earle F. Philhower, III
258260

docs/fatfsusb.rst

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
FatFSUSB
2+
========
3+
4+
When the onboard flash memory is used as a ``FatFS`` filesystem, the
5+
``FatFSUSB`` can be used to allow exporting it to a PC as a standard
6+
memory stick. The PC can then access, add, and remove files as if the
7+
Pico was a USB memory stick, and upon ejection the Pico can access
8+
any new files just as if it made them itself.
9+
10+
(Note, if you are using LittleFS then you need to use ``SingleFileDrive``
11+
to export a single file, not this class, because the PC does not
12+
understand the LittleFS disk format.)
13+
14+
Callbacks, Interrupt Safety, and File Operations
15+
------------------------------------------------
16+
17+
The ``FatFSUSB`` library allows your application to get a callback
18+
when a PC attempts to mount or unmount the Pico as a FAT drive.
19+
20+
When the drive is being used by the Pico (i.e. any ``File`` is open for
21+
read or write, the ``FatFS`` is not ``end()`` -ed and still mounted,
22+
etc.) the host may not access it. Conversely, while the host PC is
23+
connected to the drive no ``FatFS`` access by the Pico is allowed.
24+
25+
Your ``driveReady`` callback will be called when the PC attempts to mount
26+
the drive. If you have any files open, then this callback can report back
27+
that the drive is not yet ready. When you complete file processing, the PC
28+
can re-attempt to mount the drive and your callback can return ``true`` .
29+
30+
The ``onPlug`` callback will generally ``FatFS.end()`` and set a
31+
global flag letting your application know not to touch the filesystem until
32+
the flag is cleared by the ``onUnplug`` callback (which will also do a
33+
``FatFS.begin()`` call).
34+
35+
Failing to close all files **and** ``FatFS.end()`` before granting the
36+
PC access to flash memory will result in corruption. FAT does not allow multiple
37+
writers to access the same drive. Even mounting and only reading files from
38+
the PC may cause hidden writes (things like access time, etc.) which would
39+
also cause corruption.
40+
41+
See the included ``Listfiles-USB`` sketch for an example of working with
42+
these limitations.

docs/fs.rst

Lines changed: 49 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ following include to the sketch:
3333
#include "LittleFS.h" // LittleFS is declared
3434
// #include <SDFS.h>
3535
// #include <SD.h>
36+
// #include <FatFS.h>
3637
3738
3839
Compatible Filesystem APIs
@@ -48,10 +49,45 @@ SD card reader.
4849
SD is the Arduino-supported, somewhat old and limited SD card filesystem.
4950
It is recommended to use SDFS for new applications instead of SD.
5051

51-
All three of these filesystems can open and manipulate ``File`` and ``Dir``
52+
FatFS implements a wear-leveled, FTL-backed FAT filesystem in the onboard
53+
flash which can be easily accessed over USB as a standard memory stick
54+
via FatFSUSB.
55+
56+
All of these filesystems can open and manipulate ``File`` and ``Dir``
5257
objects with the same code because the implement a common end-user
5358
filesystem API.
5459

60+
FatFS File System Caveats and Warnings
61+
--------------------------------------
62+
63+
The FAT filesystem is ubiquitous, but it is also around 50 years old and ill
64+
suited to SPI flash memory due to having "hot spots" like the FAT copies that
65+
are rewritten many times over. SPI flash allows a high, but limited, number
66+
of writes before losing the ability to write safely. Applications like
67+
data loggers where many writes occur could end up wearing out the SPI flash
68+
sector that holds the FAT **years** before coming close to the write limits of
69+
the data sectors.
70+
71+
To circumvent this issue, the FatFS implementation here uses a flash translation
72+
layer (FTL) developed for SPI flash on embedded systems. This allows for the
73+
same LBA to be written over and over by the FAT filesystem, but use different
74+
flash locations. For more information see
75+
[SPIFTL](https://github.com/earlephilhower/SPIFTL). In this mode the Pico
76+
flash appears as a normal, 512-byte sector drive to the FAT.
77+
78+
What this means, practically, is that about 5KB of RAM per megabyte of flash
79+
is required for housekeeping. Writes can also become very slow if most of the
80+
flash LBA range is used (i.e. if the FAT drive is 99% full) due to the need
81+
for garbage collection processes to move data around and preserve the flash
82+
lifetime.
83+
84+
Alternatively, if an FTL is not desired or memory is tight, FatFS can use the
85+
raw flash directly. In this mode sectors are 4K in size and flash is mapped
86+
1:1 to sectors, so things like the FAT table updates will all use the same
87+
physical flash bits. For low-utilization operations this may be fine, but if
88+
significant writes are done (from the Pico or the PC host) this may wear out
89+
portions of flash very quickly , rendering it unusable.
90+
5591
LittleFS File System Limitations
5692
--------------------------------
5793

@@ -115,8 +151,8 @@ second SPI port, ``SPI1``. Just use the following call in place of
115151
SD.begin(cspin, SPI1);
116152
117153
118-
File system object (LittleFS/SD/SDFS)
119-
-------------------------------------
154+
File system object (LittleFS/SD/SDFS/FatFS)
155+
-------------------------------------------
120156

121157
setConfig
122158
~~~~~~~~~
@@ -131,14 +167,22 @@ setConfig
131167
c2.setCSPin(12);
132168
SDFS.setConfig(c2);
133169
170+
FatFSConfig c3;
171+
c3.setUseFTL(false); // Directly access flash memory
172+
c3.setDirEntries(256); // We need 256 root directory entries on a format()
173+
c3.setFATCopies(1); // Only 1 FAT to save 4K of space and extra writes
174+
FatFS.setConfig(c3);
175+
FatFS.format(); // Format using these settings, erasing everything
176+
134177
This method allows you to configure the parameters of a filesystem
135178
before mounting. All filesystems have their own ``*Config`` (i.e.
136179
``SDFSConfig`` or ``LittleFSConfig`` with their custom set of options.
137180
All filesystems allow explicitly enabling/disabling formatting when
138181
mounts fail. If you do not call this ``setConfig`` method before
139182
perforing ``begin()``, you will get the filesystem's default
140-
behavior and configuration. By default, LittleFS will autoformat the
141-
filesystem if it cannot mount it, while SDFS will not.
183+
behavior and configuration. By default, LittleFS and FatFS will autoformat the
184+
filesystem if it cannot mount it, while SDFS will not. FatFS will also use
185+
the built-in FTL to support 512 byte sectors and higher write lifetime.
142186

143187
begin
144188
~~~~~

keywords.txt

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,19 @@ Arduino KEYWORD3 RESERVED_WORD
88
# Datatypes (KEYWORD1)
99
#######################################
1010

11+
Dir KEYWORD1
12+
File KEYWORD1
1113
timeval KEYWORD1
1214
time_t KEYWORD1
1315

1416
#######################################
1517
# Methods and Functions (KEYWORD2)
1618
#######################################
1719

20+
openDir KEYWORD2
21+
setConfig KEYWORD2
22+
fileCreationTime KEYWORD2
23+
1824
setup1 KEYWORD2
1925
loop1 KEYWORD2
2026

@@ -64,7 +70,6 @@ digitalReadFast KEYWORD2
6470

6571
enableDoubleResetBootloader KEYWORD2
6672

67-
Dir KEYWORD2
6873
openDir KEYWORD2
6974
next KEYWORD2
7075
getLastWrite KEYWORD2

libraries/FatFS/keywords.txt

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#######################################
2+
# Syntax Coloring Map
3+
#######################################
4+
5+
#######################################
6+
# Datatypes (KEYWORD1)
7+
#######################################
8+
9+
FatFS KEYWORD1
10+
11+
#######################################
12+
# Methods and Functions (KEYWORD2)
13+
#######################################
14+
15+
format KEYWORD2
16+
FatFSConfig KEYWORD2
17+
setUseFTL KEYWORD2
18+
setDirEntries KEYWORD2
19+
setFATCopies KEYWORD2
20+
21+
#######################################
22+
# Constants (LITERAL1)
23+
#######################################
24+

libraries/FatFS/lib/SPIFTL

Submodule SPIFTL added at 3016627

libraries/FatFS/lib/fatfs/LICENSE.txt

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
FatFs License
2+
3+
FatFs has being developped as a personal project of the author, ChaN. It is free from the code anyone else wrote at current release. Following code block shows a copy of the FatFs license document that heading the source files.
4+
5+
/*----------------------------------------------------------------------------/
6+
/ FatFs - Generic FAT Filesystem Module Rx.xx /
7+
/-----------------------------------------------------------------------------/
8+
/
9+
/ Copyright (C) 20xx, ChaN, all right reserved.
10+
/
11+
/ FatFs module is an open source software. Redistribution and use of FatFs in
12+
/ source and binary forms, with or without modification, are permitted provided
13+
/ that the following condition is met:
14+
/
15+
/ 1. Redistributions of source code must retain the above copyright notice,
16+
/ this condition and the following disclaimer.
17+
/
18+
/ This software is provided by the copyright holder and contributors "AS IS"
19+
/ and any warranties related to this software are DISCLAIMED.
20+
/ The copyright owner or contributors be NOT LIABLE for any damages caused
21+
/ by use of this software.
22+
/----------------------------------------------------------------------------*/
23+
24+
Therefore FatFs license is one of the BSD-style licenses, but there is a significant feature. FatFs is mainly intended for embedded systems. In order to extend the usability for commercial products, the redistributions of FatFs in binary form, such as embedded code, binary library and any forms without source code, do not need to include about FatFs in the documentations. This is equivalent to the 1-clause BSD license. Of course FatFs is compatible with the most of open source software licenses include GNU GPL. When you redistribute the FatFs source code with changes or create a fork, the license can also be changed to GNU GPL, BSD-style license or any open source software license that not conflict with FatFs license.

libraries/FatFS/lib/fatfs/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
FatFS home at http://elm-chan.org/fsw/ff/

0 commit comments

Comments
 (0)