We had already explained internal flash with various filesystems and SD management. The first integrated with low energy consumption, the second from small to huge capacity but quite thirsty for energy.
But why now I’d like to explain external SPI flash if these devices already have integrated one? The answer is pretty simple: internal flash has a short life for the write cycle, but flash memories like Winbond (or other) exist that, instead of having one hundred thousand cycles, have millions of write cycles and can be used like data logging.
esp32 esp8266 external SPI Flash memory
So today, we are going to see the SPI Flash memory (NOR Flash). They are a single chip that can be managed via SPI and have high-speed access and low power consumption.
Flash memory is an electronic non-volatile computer memory storage medium that can be electrically erased and reprogrammed. The two main types of flash memory, NOR flash and NAND flash, are named for the NOR and NAND logic gates. NAND flash and NOR flash use the same cell design, consisting of floating gate MOSFETs. They differ at the circuit level: in NAND flash, the relationship between the bit line and the word lines resembles a NAND gate; in NOR flash, it resembles a NOR gate; this depends on whether the state of the bit line or word lines is pulled high or low. Flash memory, a type of floating-gate memory, was invented at Toshiba in 1980 and is based on EEPROM technology. Toshiba began marketing flash memory in 1987. EPROMs had to be erased completely before they could be rewritten. NAND flash memory, however, may be erased, written, and read in blocks (or pages), which generally are much smaller than the entire device. NOR flash memory allows a single machine word to be written – to an erased location – or read independently. A flash memory device typically consists of one or more flash memory chips (each holding many flash memory cells), along with a separate flash memory controller chip.
Wikipedia
SPI Flash memories pinout
There are SMD, and Discrete IC managed by SPI protocol.
SPI Flash Discrete PDIP pinout
SPI Flash SMD SOIC DIP8 pinout
Here a set of SPI flash with different size w25q16 SMD 2Mb - w25q16 Discrete 2Mb -
w25q32 SMD 4Mb - w25q32 Discrete 4Mb -
w25q64 SMD 8Mb - w25q64 Discrete 8Mb -
w25q128 SMD 16Mb - w25q128 Discrete 16Mb
W25Q32 W25Q64 w25q128 module 4Mb 8Mb 16Mb
esp8266 wiring diagram
As usual, for the esp8266 device, I use WeMos D1 mini.
WeMos D1 mini esp8266 pinout mischianti low resolution
Arduino SPI Flash D8 /CS Pulled UP if not standard CS D6 DI (IO1 ) D7 DI (IO0 ) D5 CLK 3.3v /WP 3.3v /Hold GND GND 3.3v VCC
Here is the result on the breadboard.
esp8266 WeMos D1 mini connection DIP8 SPI Flash breadboard
And here is the schema.
esp8266 WeMos D1 mini connection DIP8 SPIFlash schema
esp32 connection schema
ESP32 DOIT DEV KIT v1 pinout
Here the connection schema
esp32 DOIT DEV KIT v1 connection DIP8 SPIFlash breadboard w25q128
Arduino SPI Flash GPIO5 /CS Pulled UP if not standard CS GPIO19 DI (IO1 ) GPIO23 DI (IO0 ) GPIO18 CLK 3.3v /WP 3.3v /Hold GND GND 3.3v VCC
Here is the schema.
esp32 DOIT DEV KIT v1 connection DIP8 SPI Flash schema w25q64
SPI Flash basic usage
If you don’t need a particular data structure, you can do basic and raw usage of the SPI Flash.
For primary usage, I advise using a library named SPIMemory, quite simple but with good support without complexity. You can download It via library manager from Arduino IDE.
For additional information on this library, you can see the article “Arduino: external fast SPI Flash memory “.
SPIMemory library from Arduino IDE library manager
Pay attention to esp32. You must set SPI frequencies limits to 24Mhz; esp8266 had no limitations.
To set frequencies limits, use a command like this (read the Arduino article to get more information):
flash.setClock(
24000000
);
Here is a simple example that stores a JSON string in the initial address 0, and I re-read It, then I ask the method getAddress the first available contiguous position where I can store another JSON string, and I save It re-read.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
#include
<SPIMemory.h>
#include
<ArduinoJson.h>
SPIFlash flash(SS,
&
SPI);
void
setup
() {
Serial.begin
(
115200
);
while
(
!
Serial) ;
delay
(
100
);
flash.begin();
Serial.print
(F(
"Flash size: "
));
Serial.print
((
long
)(flash.getCapacity()
/
1000
));
Serial.println
(F(
"Kb"
));
unsigned
long
strAddr
=
0
;
unsigned
long
strAddrSecondString
=
0
;
Serial.println
();
Serial.println
(F(
"Generate JSON file!"
));
DynamicJsonDocument doc(
512
);
doc[
"energyLifetime"
]
=
21698620
;
doc[
"energyYearly"
]
=
1363005
;
Serial.print
(F(
"Put data in a buffer.. "
));
String buf;
if
(serializeJson(doc, buf)
=
=
0
) {
Serial.println
(F(
"failed to write buffer"
));
}
if
(flash.writeStr(strAddr, buf)){
Serial.print
(F(
"OK, writed on address "
));
Serial.println
(strAddr);
}
else
{
Serial.println
(F(
"KO"
));
}
String outputString
=
""
;
if
(flash.readStr(strAddr, outputString)) {
Serial.print
(F(
"Read json: "
));
Serial.println
(outputString);
Serial.print
(F(
"From address: "
));
Serial.println
(strAddr);
}
Serial.println
(F(
"Generate JSON file!"
));
DynamicJsonDocument doc2(
512
);
doc2[
"energyLifetime"
]
=
222
;
doc2[
"energyYearly"
]
=
333
;
Serial.println
();
Serial.print
(F(
"Check first free sector: "
));
strAddrSecondString
=
flash.getAddress(doc2.size());
Serial.println
(strAddrSecondString);
Serial.println
();
Serial.print
(F(
"Stream data in flash memory!"
));
Serial.print
(F(
"Put data in a buffer.."
));
String buf2;
if
(serializeJson(doc2, buf2)
=
=
0
) {
Serial.println
(F(
"failed to write buffer"
));
}
if
(flash.writeStr(strAddrSecondString, buf2)){
Serial.print
(F(
"OK, writed on address "
));
Serial.println
(strAddrSecondString);
}
else
{
Serial.println
(F(
"KO"
));
}
String outputString2
=
""
;
if
(flash.readStr(strAddrSecondString, outputString2)) {
Serial.print
(F(
"Read data: "
));
Serial.println
(outputString2);
Serial.print
(F(
"From address: "
));
Serial.println
(strAddrSecondString);
}
while
(
!
flash.eraseSector(strAddr));
while
(
!
flash.eraseSector(strAddrSecondString));
}
void
loop
() {
}
Here is the console result.
1
2
3
4
5
6
7
8
9
10
11
12
13
Flash size: 8388Kb
Generate JSON file!
Put data in a buffer.. OK, writed on address 0
Read json: {"energyLifetime":21698620,"energyYearly":1363005}
From address: 0
Generate JSON file!
Check first free sector: 56
Stream data in flash memory!Put data in a buffer..OK, writed on address 56
Read data: {"energyLifetime":222,"energyYearly":333}
From address: 56
SPI Flash advanced use with SdFat filesystem
A more complex library (and more hungry for resources) The Adafruit one, the Adafruit SPIFlash , needs to be used with the SdFat Adafruit fork .
This library Is discouraged on Arduino’s boards like UNO or Mega because only for buffer, It needs 512 bytes, and every file has some byte of a preamble, and you risk wasting a lot of RAM. For a low-power microcontroller, It’s better to use a library like SPIMemory.
You can also find these libraries on the library manager “Adafruit SPIFlash” and SdFat – Adafruit Fork”.
Arduino IDE library manager Adafruit SPIFlash and SdFat fork
Add new SPI Flash type
The set of chips is supported. It’s limited to a specified list but create a new device. It’s pretty simple. For example, I have a W25X80AVAIZ (I think Winbond clone), a discrete component buy for a very low price. It has these characteristics:
1Mb capacity;
104Mhz of speed;
Winbond clone;
Single dual and quad SPI.
Then, I write a simple sketch to check the compatibility:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
#include
"SdFat.h"
#include
"Adafruit_SPIFlash.h"
Adafruit_FlashTransport_SPI flashTransport(SS, SPI);
Adafruit_SPIFlash flash(
&
flashTransport);
void
setup
()
{
Serial.begin
(
115200
);
while
(
!
Serial )
delay
(
100
);
if
(flash.begin()) {
Serial.println
(F(
"Device finded and supported!"
));
}
else
{
Serial.println
(F(
"Problem to discover and configure device, check wiring also!"
));
}
flashTransport.setClockSpeed(
4000000
,
4000000
);
Serial.println
();
Serial.println
(
"Adafruit Serial Flash get basic info: "
);
Serial.print
(
"JEDEC ID (FFFFFF for unknown): "
);
Serial.println
(flash.getJEDECID(), HEX);
Serial.print
(
"Flash size: "
);
Serial.println
(flash.size());
Serial.println
();
Serial.println
();
uint8_t jedec_ids[
4
];
flashTransport.readCommand(SFLASH_CMD_READ_JEDEC_ID, jedec_ids,
4
);
if
(jedec_ids[
1
]
=
=
0x7F
) {
jedec_ids[
1
]
=
jedec_ids[
2
];
jedec_ids[
2
]
=
jedec_ids[
3
];
}
Serial.println
(
"Retrieve JDEC_ID"
);
Serial.print
(
"Manufacturer ID: 0x"
);
Serial.println
(jedec_ids[
0
], HEX);
Serial.print
(
"Memory Type: 0x"
);
Serial.println
(jedec_ids[
1
], HEX);
Serial.print
(
"Capacity: 0x"
);
Serial.println
(jedec_ids[
2
], HEX);
Serial.print
(
"Capacity DEC: "
);
Serial.println
(jedec_ids[
2
], DEC);
}
void
loop
()
{
}
The serial output for my unsupported device is:
1
2
3
4
5
6
7
8
9
10
11
12
13
Unknown flash device 0xEF4014
Problem to discover and configure device, check wiring also!
Adafruit Serial Flash get basic info:
JEDEC ID (FFFFFF for unknown): FFFFFF
Flash size: 0
Retrieve JDEC_ID
Manufacturer ID: 0xEF
Memory Type: 0x40
Capacity: 0x14
Capacity DEC: 20
So I get from the Adafruit_SPIFlash library the file flash_devices.h, and I get the most similar device is in the list.
Then I use:
Capacity DEC to get the size: .total_size = (1UL << 20), /* 1 MiB */
Manufacturer ID for the manufacturer: .manufacturer_id = 0xef
Memory type for the memory_type: .memory_type = 0x40
The capacity for capacity: .capacity = 0x14
I try to find some information on the compatible device datasheet.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#define
W25X80BV \
{ \
.total_size
=
(
1UL
<<
20
),
\
.start_up_time_us
=
5000
, .manufacturer_id
=
0xef
, \
.memory_type
=
0x40
, .capacity
=
0x14
, .max_clock_speed_mhz
=
104
, \
.quad_enable_bit_mask
=
0x02
, .has_sector_protection
=
false
, \
.supports_fast_read
=
true
, .supports_qspi
=
true
, \
.supports_qspi_writes
=
true
, .write_status_register_split
=
false
, \
.single_status_byte
=
false
, .is_fram
=
false
, \
}
static
const
SPIFlash_Device_t possible_devices[]
=
{
W25X80BV,
};
if
(
!
flash.begin(possible_devices)) {
Serial.println
(
"Error, failed to initialize flash chip!"
);
while
(
1
) yield();
}
Now the complete test sketch become:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
#include
"SdFat.h"
#include
"Adafruit_SPIFlash.h"
Adafruit_FlashTransport_SPI flashTransport(SS, SPI);
Adafruit_SPIFlash flash(
&
flashTransport);
void
setup
()
{
Serial.begin
(
115200
);
while
(
!
Serial )
delay
(
100
);
#define
W25X80BV \
{ \
.total_size
=
(
1UL
<<
20
),
\
.start_up_time_us
=
5000
, .manufacturer_id
=
0xef
, \
.memory_type
=
0x40
, .capacity
=
0x14
, .max_clock_speed_mhz
=
104
, \
.quad_enable_bit_mask
=
0x02
, .has_sector_protection
=
false
, \
.supports_fast_read
=
true
, .supports_qspi
=
true
, \
.supports_qspi_writes
=
true
, .write_status_register_split
=
false
, \
.single_status_byte
=
false
, .is_fram
=
false
, \
}
static
const
SPIFlash_Device_t possible_devices[]
=
{
W25X80BV,
};
if
(flash.begin(possible_devices)) {
Serial.println
(F(
"Device finded and supported!"
));
}
else
{
Serial.println
(F(
"Problem to discover and configure device, check wiring also!"
));
}
flashTransport.setClockSpeed(
4000000
,
4000000
);
Serial.println
();
Serial.println
(
"Adafruit Serial Flash get basic info: "
);
Serial.print
(
"JEDEC ID (FFFFFF for unknown): "
);
Serial.println
(flash.getJEDECID(), HEX);
Serial.print
(
"Flash size: "
);
Serial.println
(flash.size());
Serial.println
();
Serial.println
();
uint8_t jedec_ids[
4
];
flashTransport.readCommand(SFLASH_CMD_READ_JEDEC_ID, jedec_ids,
4
);
if
(jedec_ids[
1
]
=
=
0x7F
) {
jedec_ids[
1
]
=
jedec_ids[
2
];
jedec_ids[
2
]
=
jedec_ids[
3
];
}
Serial.println
(
"Retrieve JDEC_ID"
);
Serial.print
(
"Manufacturer ID: 0x"
);
Serial.println
(jedec_ids[
0
], HEX);
Serial.print
(
"Memory Type: 0x"
);
Serial.println
(jedec_ids[
1
], HEX);
Serial.print
(
"Capacity: 0x"
);
Serial.println
(jedec_ids[
2
], HEX);
Serial.print
(
"Capacity DEC: "
);
Serial.println
(jedec_ids[
2
], DEC);
}
void
loop
()
{
}
And now the result is:
1
2
3
4
5
6
7
8
9
10
11
12
Device finded and supported!
Adafruit Serial Flash get basic info:
JEDEC ID (FFFFFF for unknown): EF4014
Flash size: 1048576
Retrieve JDEC_ID
Manufacturer ID: 0xEF
Memory Type: 0x40
Capacity: 0x14
Capacity DEC: 20
Test and Troubleshooting
To check if all It’s ok, you can use the test given in the library. First, you must launch the example SdFat_speedtest
, for Arduino UNO like board with little RAM, you must reduce the buffer from
to
here is the complete sketch with custom IC:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
#include
"SdFat.h"
#include
"Adafruit_SPIFlash.h"
#define
CUSTOM_CS SS
#define
CUSTOM_SPI SPI
#define
EXTERNAL_FLASH_USE_QSPI
Adafruit_FlashTransport_SPI flashTransport(CUSTOM_CS, CUSTOM_SPI);
Adafruit_SPIFlash flash(
&
flashTransport);
#define
BUFSIZE
4096
uint8_t bufwrite[BUFSIZE] __attribute__ ((aligned(
4
)));
uint8_t bufread[BUFSIZE] __attribute__ ((aligned(
4
)));
void
setup
()
{
Serial.begin
(
115200
);
while
(
!
Serial )
delay
(
100
);
SPI.setFrequency(
12000000
);
#define
W25X80BV \
{ \
.total_size
=
(
1UL
<<
20
),
\
.start_up_time_us
=
5000
, .manufacturer_id
=
0xef
, \
.memory_type
=
0x40
, .capacity
=
0x14
, .max_clock_speed_mhz
=
104
, \
.quad_enable_bit_mask
=
0x02
, .has_sector_protection
=
false
, \
.supports_fast_read
=
true
, .supports_qspi
=
true
, \
.supports_qspi_writes
=
true
, .write_status_register_split
=
false
, \
.single_status_byte
=
false
, .is_fram
=
false
, \
}
static
const
SPIFlash_Device_t possible_devices[]
=
{
W25X80BV,
};
flash.begin();
pinMode
(LED_BUILTIN,
OUTPUT
);
flash.setIndicator(LED_BUILTIN,
true
);
Serial.println
(
"Adafruit Serial Flash Speed Test example"
);
Serial.print
(
"JEDEC ID: "
);
Serial.println
(flash.getJEDECID(), HEX);
Serial.print
(
"Flash size: "
);
Serial.println
(flash.size());
Serial.flush
();
write_and_compare(
0xAA
);
write_and_compare(
0x55
);
Serial.println
(
"Speed test is completed."
);
Serial.flush
();
}
void
print_speed(
const
char
*
text, uint32_t count, uint32_t ms)
{
Serial.print
(text);
Serial.print
(count);
Serial.print
(
" bytes in "
);
Serial.print
(ms
/
1000.0
F,
2
);
Serial.println
(
" seconds."
);
Serial.print
(
"Speed : "
);
Serial.print
( (count
/
1000.0
F)
/
(ms
/
1000.0
F),
2
);
Serial.println
(
" KB/s.\r\n"
);
}
bool write_and_compare(uint8_t pattern)
{
uint32_t ms;
Serial.println
(
"Erase chip"
);
Serial.flush
();
#define
TEST_WHOLE_CHIP
#ifdef
TEST_WHOLE_CHIP
uint32_t
const
flash_sz
=
flash.size();
flash.eraseChip();
#else
uint32_t
const
flash_sz
=
4096
;
flash.eraseSector(
0
);
#endif
flash.waitUntilReady();
memset(bufwrite, (
int
) pattern,
sizeof
(bufwrite));
Serial.printf(
"Write flash with 0x%02X\n"
, pattern);
Serial.flush
();
ms
=
millis
();
for
(uint32_t addr
=
0
; addr < flash_sz; addr
+
=
sizeof
(bufwrite))
{
flash.writeBuffer(addr, bufwrite,
sizeof
(bufwrite));
}
uint32_t ms_write
=
millis
()
-
ms;
print_speed(
"Write "
, flash_sz, ms_write);
Serial.flush
();
Serial.println
(
"Read flash and compare"
);
Serial.flush
();
uint32_t ms_read
=
0
;
for
(uint32_t addr
=
0
; addr < flash_sz; addr
+
=
sizeof
(bufread))
{
memset(bufread,
0
,
sizeof
(bufread));
ms
=
millis
();
flash.readBuffer(addr, bufread,
sizeof
(bufread));
ms_read
+
=
millis
()
-
ms;
if
( memcmp(bufwrite, bufread, BUFSIZE) )
{
Serial.printf(
"Error: flash contents mismatched at address 0x%08X!!!"
, addr);
for
(uint32_t i
=
0
; i<
sizeof
(bufread); i
+
+
)
{
if
( i
!
=
0
)
Serial.print
(
' '
);
if
( (i
%
16
=
=
0
) )
{
Serial.println
();
Serial.printf(
"%03X: "
, i);
}
Serial.printf(
"%02X"
, bufread[i]);
}
Serial.println
();
return
false
;
}
}
print_speed(
"Read "
, flash_sz, ms_read);
Serial.flush
();
return
true
;
}
void
loop
()
{
}
If you have a Serial output like this (I use […] to indicate the line replication):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
Adafruit Serial Flash Speed Test example
JEDEC ID: EF4014
Flash size: 1048576
Erase chip
Write flash with 0xAA
Write 1048576 bytes in 1.03 seconds.
Speed : 1016.06 KB/s.
Read flash and compare
Error: flash contents mismatched at address 0x00000000!!!
000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[...]
FF0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Erase chip
Write flash with 0x55
Write 1048576 bytes in 1.03 seconds.
Speed : 1017.05 KB/s.
Read flash and compare
Error: flash contents mismatched at address 0x00000000!!!
000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[...]
FF0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Speed test is completed.
The lines (or other HEX characters) with
1
000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
indicate that the data compared don’t match, so (If the previous test sketch work) probably you had some problem.
In most cases, the SPI speed is too high; this does not mean that the speed is too high for the microcontroller or IC, but it can be a problem with a poor connection cable.
But the solution to this was to reduce the speed, so you must go to add a line like this after the flash.begin()
:
flashTransport.setClockSpeed(
24000000
,
24000000
);
esp32 WeMos LOLIN32 external SPI Flash memory on the breadboard
the command set the SPI speed to 24Mhz, and now the result become like so:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
Adafruit Serial Flash Speed Test example
JEDEC ID: EF4014
Flash size: 1048576
Erase chip
Write flash with 0xAA
Write 1048576 bytes in 4.07 seconds.
Speed : 257.38 KB/s.
Read flash and compare
Read 1048576 bytes in 0.47 seconds.
Speed : 2226.28 KB/s.
Erase chip
Write flash with 0x55
Write 1048576 bytes in 4.07 seconds.
Speed : 257.38 KB/s.
Read flash and compare
Read 1048576 bytes in 0.47 seconds.
Speed : 2231.01 KB/s.
Speed test is completed.
If no compare errors are shown, the SPI Flash was correctly configured.
esp32 limitations
For esp32, the maximum stable speed I have reached is 24Mhz, so I must add
1
flashTransport.setClockSpeed(
24000000
,
24000000
);
esp8266 limitations
esp8266 has a lower CPU frequency but no limitations on SPI frequencies.
WeMos D1 mini external SPI Flash memory on the breadboard
Practical sketch
First of all, you must Format the SPI Flash; in the examples of Adafruit_SPIFlash, you can find the SdFat_format
example , that format the SPI flash for you.
When you launch the sketch, It asks you to insert, in the Serial monitor, “OK” in camel case, here the Serial output result.
1
2
3
4
5
6
7
8
9
10
11
12
13
Adafruit SPI Flash FatFs Format Example
Flash size: 1024 KB
Flash chip JEDEC ID: 0xEF4014
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
This sketch will ERASE ALL DATA on the flash chip and format it with a new filesystem!
Type OK (all caps) and press enter to continue.
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
>>Send to COM17: "OK"<<
Creating and formatting FAT filesystem (this takes ~60 seconds)...
Setting disk label to: EXT FLASH
Formatted flash!
Flash chip successfully formatted with new empty filesystem!
Now you are ready to use the SPI Flash with FAT FS.
If you want to use the filesystem FAT, I advise you to use a SPIFlash with more than 1Mb of space.
Here is a simple sketch that creates a test.txt file with the string <num> -> testing 1, 2, 3.
100 times.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
#include
"SdFat.h"
#include
"Adafruit_SPIFlash.h"
Adafruit_FlashTransport_SPI flashTransport(SS, SPI);
Adafruit_SPIFlash flash(
&
flashTransport);
FatFileSystem fatfs;
File myFile;
void
setup
()
{
Serial.begin
(
115200
);
while
(
!
Serial )
delay
(
100
);
if
(flash.begin()) {
Serial.println
(F(
"Device finded and supported!"
));
}
else
{
Serial.println
(F(
"Problem to discover and configure device, check wiring also!"
));
}
flashTransport.setClockSpeed(
24000000
,
24000000
);
pinMode
(LED_BUILTIN,
OUTPUT
);
flash.setIndicator(LED_BUILTIN,
true
);
Serial.println
(
"Adafruit Serial Flash read write example"
);
Serial.print
(
"JEDEC ID: "
);
Serial.println
(flash.getJEDECID(), HEX);
Serial.print
(
"Flash size: "
);
Serial.println
(flash.size());
Serial.flush
();
Serial.println
();
if
(
!
fatfs.begin(
&
flash)) {
Serial.println
(
"Error, failed to mount newly formatted filesystem!"
);
Serial.println
(
"Was the flash chip formatted with the SdFat_format example?"
);
while
(
1
) yield();
}
Serial.println
(
"Mounted filesystem!"
);
Serial.println
();
myFile
=
fatfs.open(
"test.txt"
, FILE_WRITE);
if
(myFile) {
Serial.print
(
"Writing to test.txt..."
);
for
(
int
i
=
0
;i<
100
;i
+
+
){
myFile.print(i);
myFile.println(
" -> testing 1, 2, 3."
);
}
myFile.close();
Serial.println
(
"done."
);
}
else
{
Serial.println
(
"error opening test.txt"
);
}
myFile
=
fatfs.open(
"test.txt"
);
if
(myFile) {
Serial.println
(
"test.txt:"
);
while
(myFile.available()) {
Serial.write
(myFile.read());
}
myFile.close();
}
else
{
Serial.println
(
"error opening test.txt"
);
}
}
void
loop
() {
}
The result becomes like so:
1
2
3
4
5
6
7
8
9
10
11
12
13
Device finded and supported!
Adafruit Serial Flash Speed Test example
JEDEC ID: EF4017
Flash size: 8388608
Mounted filesystem!
Writing to test.txt...done.
test.txt:
0 -> testing 1, 2, 3.
[...]
99 -> testing 1, 2, 3.
ets Jun 8 2016 00:22:57
Now we can call some command to retrieve the filesystem info and then get the list of files with the ls command.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
#include
"SdFat.h"
#include
"Adafruit_SPIFlash.h"
Adafruit_FlashTransport_SPI flashTransport(SS, SPI);
Adafruit_SPIFlash flash(
&
flashTransport);
FatFileSystem fatfs;
void
setup
()
{
Serial.begin
(
115200
);
while
(
!
Serial )
delay
(
100
);
if
(flash.begin()) {
Serial.println
(F(
"Device finded and supported!"
));
}
else
{
Serial.println
(F(
"Problem to discover and configure device, check wiring also!"
));
}
flashTransport.setClockSpeed(
24000000
,
24000000
);
pinMode
(LED_BUILTIN,
OUTPUT
);
flash.setIndicator(LED_BUILTIN,
true
);
Serial.println
(
"Adafruit Serial Flash Speed Test example"
);
Serial.print
(
"JEDEC ID: "
);
Serial.println
(flash.getJEDECID(), HEX);
Serial.print
(
"Flash size: "
);
Serial.println
(flash.size());
Serial.flush
();
Serial.println
();
if
(
!
fatfs.begin(
&
flash)) {
Serial.println
(
"Error, failed to mount newly formatted filesystem!"
);
Serial.println
(
"Was the flash chip formatted with the SdFat_format example?"
);
while
(
1
) yield();
}
Serial.println
(
"Mounted filesystem!"
);
Serial.println
();
Serial.print
(
"Clusters: "
);
Serial.println
(fatfs.clusterCount());
Serial.print
(
"Blocks x Cluster: "
);
Serial.println
(fatfs.blocksPerCluster());
Serial.print
(
"Total Blocks: "
);
Serial.println
(fatfs.blocksPerCluster()
*
fatfs.clusterCount());
Serial.println
();
uint32_t volumesize;
Serial.print
(
"Volume type is: FAT"
);
Serial.println
(fatfs.fatType(), DEC);
volumesize
=
fatfs.blocksPerCluster();
volumesize
*
=
fatfs.clusterCount();
volumesize
/
=
2
;
Serial.print
(
"Volume size (Kb): "
);
Serial.println
(volumesize);
Serial.print
(
"Volume size (Mb): "
);
volumesize
/
=
1024
;
Serial.println
(volumesize);
Serial.println
();
volumesize
=
0
;
volumesize
=
fatfs.blocksPerCluster();
volumesize
*
=
fatfs.freeClusterCount();
volumesize
/
=
2
;
Serial.print
(
"Free space size (Kb): "
);
Serial.println
(volumesize);
Serial.print
(
"Free space size (Mb): "
);
volumesize
/
=
1024
;
Serial.println
(volumesize);
Serial.println
(
"\nFiles found on the card (name, date and size in bytes): "
);
fatfs.rootDirStart();
fatfs.ls(LS_R
|
LS_DATE
|
LS_SIZE);
}
void
loop
(
void
) {
}
The result becomes
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Device finded and supported!
Adafruit Serial Flash Speed Test example
JEDEC ID: EF4017
Flash size: 8388608
Mounted filesystem!
Clusters: 2043
Blocks x Cluster: 8
Total Blocks: 16344
Volume type is: FAT12
Volume size (Kb): 8172
Volume size (Mb): 7
Free space size (Kb): 8164
Free space size (Mb): 7
Files found on the card (name, date and size in bytes):
2000-01-01 01:00:00 7170 test.txt
Thanks
Arduino: fast external SPI Flash memory
Arduino MKR SAMD: FAT filesystem on external SPI flash memory
esp32 and esp8266: FAT filesystem on external SPI flash memory
STM32: SPI flash memory FAT FS
ESP32: pinout, specs and Arduino IDE configuration
ESP32: integrated SPIFFS Filesystem
ESP32: manage multiple Serial and logging
ESP32 practical power saving
ESP32 practical power saving: manage WiFi and CPU
ESP32 practical power saving: modem and light sleep
ESP32 practical power saving: deep sleep and hibernation
ESP32 practical power saving: preserve data, timer and touch wake up
ESP32 practical power saving: external and ULP wake up
ESP32 practical power saving: UART and GPIO wake up
ESP32: integrated LittleFS FileSystem
ESP32: integrated FFat (Fat/exFAT) FileSystem
ESP32-wroom-32
ESP32-wroom-32: flash, pinout, specs and IDE configuration
ESP32-CAM
ESP32-CAM: pinout, specs and Arduino IDE configuration
ESP32-CAM: upgrade CamerWebServer with flash features
ESP32: use ethernet w5500 with plain (HTTP) and SSL (HTTPS)
ESP32: use ethernet enc28j60 with plain (HTTP) and SSL (HTTPS)
How to use SD card with esp32
esp32 and esp8266: FAT filesystem on external SPI flash memory
Firmware and OTA update management
Firmware management
ESP32: flash compiled firmware (.bin)
ESP32: flash compiled firmware and filesystem (.bin) with GUI tools
OTA update with Arduino IDE
ESP32 OTA update with Arduino IDE: filesystem, firmware, and password
OTA update with Web Browser
ESP32 OTA update with Web Browser: firmware, filesystem, and authentication
ESP32 OTA update with Web Browser: upload in HTTPS (SSL/TLS) with self-signed certificate
ESP32 OTA update with Web Browser: custom web interface
Self OTA uptate from HTTP server
ESP32 self OTA update firmware from the server
ESP32 self OTA update firmware from the server with version check
ESP32 self-OTA update in HTTPS (SSL/TLS) with trusted self-signed certificate
Non-standard Firmware update
ESP32 firmware and filesystem update from SD card
ESP32 firmware and filesystem update with FTP client
Integrating LAN8720 with ESP32 for Ethernet Connectivity with plain (HTTP) and SSL (HTTPS)
Connecting the EByte E70 to ESP32 c3/s3 devices and a simple sketch example
ESP32-C3: pinout, specs and Arduino IDE configuration
Integrating W5500 with ESP32 Using Core 3: Native Ethernet Protocol Support with SSL and Other Features
Integrating LAN8720 with ESP32 Using Core 3: Native Ethernet Protocol Support with SSL and Other Features
Dallas ds18b20:
Guide to I2C on ESP32: Communication with Heterogeneous 5V and 3.3V Devices, Additional Interface Management and Scanner
WeMos D1 mini (esp8266), specs and IDE configuration
WeMos D1 mini (esp8266), integrated SPIFFS Filesystem
WeMos D1 mini (esp8266), debug on secondary UART
WeMos D1 mini (esp8266), the three type of sleep mode to manage energy savings
WeMos D1 mini (esp8266), integrated LittleFS Filesystem
esp12 esp07 (esp8266): flash, pinout, specs and IDE configuration
Firmware and OTA update management
Firmware management
esp8266: flash firmware binary (.bin) compiled and signed
esp8266: flash firmware and filesystem binary (.bin) compiled with GUI tools
OTA update with Arduino IDE
esp8266 OTA update with Arduino IDE: filesystem, signed and password
OTA update with Web Browser
esp8266 OTA update with Web Browser: firmware, filesystem and authentication
esp8266 OTA update with Web Browser: sign the firmware and HTTPS (SSL/TLS)
esp8266 OTA update with Web Browser: custom web interface
Self OTA uptate from HTTP server
esp8266 self OTA update firmware from server
esp8266 self OTA update firmware from server with version check
esp8266 self OTA update in HTTPS (SSL/TLS) with trusted self signed certificate
Non standard Firmware update
esp8266 firmware and filesystem update from SD card
esp8266 firmware and filesystem update with FTP client
esp32 and esp8266: FAT filesystem on external SPI flash memory
i2c esp8266: how to, network 5v, 3.3v, speed, and custom pins
[…]