I dispositivi Arduino SAMD non hanno una memoria flash SPI interna, ma è chiaro che una memoria veloce e piccola come quella può essere molto utile, quindi dobbiamo parlare ancora (e ancora e ancora e ancora e ancora…) di sistemi di archiviazione.
Arduino SAMD MKR external SPI Flash storage
Avevamo già visto la gestione della SD (puoi vedere la gestione della SD su “Come usare la scheda SD con esp8266 e Arduino “), ora vorremmo guardare uno storage alternativo come la flash SPI esterna, simile alla EEPROM ma con la taglia più grande. La flash SPI ha una capacità inferiore ma è piccolo, veloce e ha un consumo energetico molto basso. L’SD È sicuramente la scelta migliore per dimensioni e compatibilità, ma queste caratteristiche le paghiamo con una buona quantità di energia.
Oggi vedremo la memoria flash SPI (NOR Flash); su un unico chip che può essere gestito tramite SPI e hanno accesso ad alta velocità e basso consumo energetico.
La memoria flash è un supporto di memoria elettronico non volatile per computer che può essere cancellato e riprogrammato elettricamente. I due tipi principali di memoria flash, NOR flash e NAND flash, prendono il nome dalle porte logiche NOR e NAND. La flash NAND e la flash NOR utilizzano lo stesso design delle celle, costituito da MOSFET a gate flottante. Differiscono a livello di circuito: nelle flash NAND, la relazione tra la linea di bit e le linee di parola assomiglia a una porta NAND; nelle flash NOR, assomiglia a un gate NOR; questo dipende dal fatto che lo stato della linea di bit o delle linee di parola sia HIGH o LOW. La memoria flash, un tipo di memoria a gate flottante, è stata inventata da Toshiba nel 1980 e si basa sulla tecnologia EEPROM. Toshiba ha iniziato a commercializzare memorie flash nel 1987. Le EPROM dovevano essere cancellate completamente prima di poter essere riscritte. La memoria flash NAND, tuttavia, può essere cancellata, scritta e letta in blocchi (o pagine), che generalmente sono molto più piccoli dell’intero dispositivo. La memoria flash NOR consente di scrivere una singola parola macchina – in una posizione cancellata – o di leggerla in modo indipendente. Un dispositivo di memoria flash è in genere costituito da uno o più chip di memoria flash (ciascuno contenente molte celle di memoria flash), insieme a un chip controller di memoria flash separato.
Wikipedia
Memorie flash
Ci sono IC SMD e discreti gestiti dal protocollo SPI.
SPI Flash Discrete PDIP pinout
SPI Flash SMD SOIC DIP8 pinout
Qui un set di memorie flash di varie dimensioni 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
Schema elettrico Arduino MKR WiFi 1010
Puoi selezionare una SERCOM SPI su tutti i pin che desideri, ma ora utilizzeremo lo SPI standard.
Arduino MKR WiFi 1010 pinouts low resolution
Quindi puoi fare riferimento alla piedinatura e collegare i pin 8, 9, 10 e 4 per CS.
Arduino Flash SPI 4 /CS Pulled UP se non è un CS standard 10 DI (IO1 ) 8 DI (IO0 ) 9 CLK 3.3v /WP 3.3v /Hold GND GND 3.3v VCC
Arduino MKR WiFi 1010 connection DIP8 SPI Flash breadboard w25q64
Per il condensatore, io uso un 0.1μF e funziona correttamente, ma il valore standard era 0.01μF.
Arduino MKR WiFi 1010 connection DIP8 SPI Flash schema w25q64
Schema elettrico Arduino NANO 33 IoT
Anche qui puoi selezionare una SERCOM SPI in tutti i pin che desideri, ma andremo ad utilizzare uno SPI standard.
Arduino NANO 33 IoT pinouts low resolution
Quindi puoi fare riferimento alla piedinatura e collegare i pin 11, 12, 13 e 10 per CS.
Arduino Flash SPI 10 /CS Pulled UP se non è uno standard CS 12 DI (IO1 ) 11 DI (IO0 ) 13 CLK 3.3v /WP 3.3v /Hold GND GND 3.3v VCC
Arduino NANO 33 IoT connection DIP8 SPI Flash w25q64
Per il condensatore, ho usato uno 0,1μF e funziona correttamente, ma il valore standard era 0,01μF.
Utilizzo di base di una flash SPI
Se non hai bisogno di una struttura di dati particolare, puoi fare un utilizzo di base e grezzo della flash SPI.
Per ulteriori informazioni su questa libreria, è possibile consultare l’articolo “Arduino: memoria SPI flash esterna veloce ”.
Per un utilizzo di base, consiglio di utilizzare una libreria denominata SPIMemory, abbastanza semplice ma con un buon supporto senza difficoltà. Puoi scaricarla tramite il gestore della libreria da Arduino IDE.
È necessario bloccare le frequenze a 12Mhz per questo dispositivo perché l’interfaccia sercom non ne consente di più. Ma in teoria puoi aprire cinque diversi dispositivi SPI.
SPIMemory library from Arduino IDE library manager
Ecco un semplice esempio che memorizza una stringa JSON nell’indirizzo iniziale 0 e la rileggo, quindi chiedo al metodo getAddress
la prima posizione contigua disponibile in cui posso memorizzare un’altra stringa JSON, la salvo e la rileggo .
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.setClock(
12000000
);
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
() {
}
Ecco il risultato della console.
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
Uso avanzato di una Flash SPI con il filesystem SdFat
Una libreria più complessa (e più affamata di risorse) è quella di Adafruit, l’Adafruit SPIFlash , che deve essere usata con il fork di SdFat Adafruit .
Questa libreria è sconsigliata su schede Arduino come UNO o Mega perché, solo per il buffer, ha bisogno di 512 byte e ogni file ha qualche byte di preambolo e rischi di sprecare molta RAM. Per un microcontrollore a bassa potenza, è meglio usare una libreria come SPIMemory.
Puoi trovare queste librerie anche sul gestore delle librerie “Adafruit SPIFlash” e “SdFat – Adafruit Fork”.
Arduino IDE library manager Adafruit SPIFlash and SdFat fork
Aggiungere un nuovo tipo di flash SPI
Il set di chip supportato è limitato a un elenco specificato ma si può creare un nuovo dispositivo. Ad esempio, ho un W25X80AVAIZ (penso Winbond clone), un componente discreto che è possibile acquistare a un prezzo molto basso. Ha queste caratteristiche:
capacità 1Mb;
104 Mhz di velocità;
clone di Winbond;
SPI singolo doppio e quadruplo.
Ora, scrivo un semplice sketch per verificare la compatibilità:
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
()
{
}
L’uscita seriale per il mio dispositivo non supportato è:
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
Quindi prendo dalla libreria Adafruit_SPIFlash il file flash_devices.h e seleziono il dispositivo più simile nell’elenco.
Allora uso:
Capacity DEC per ottenere la dimensione: .total_size = (1UL << 20), /* 1 MiB */
Manufacturer ID per il produttore: .manufacturer_id = 0xef
Memory type per memory_type: .memory_type = 0x40
The Capacity per la capacità: .capacity = 0x14
Cerco di trovare alcune informazioni sulla scheda tecnica del dispositivo compatibile.
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();
}
Ora lo sketch di prova completo diventa:
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
()
{
}
E ora il risultato è:
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 e risoluzione dei problemi
Per verificare se tutto è a posto, puoi utilizzare il test fornito in libreria. Innanzitutto, devi avviare l’esempio SdFat_speedtest; per Arduino UNO, come la scheda con poca RAM, è necessario ridurre il buffer da
a
ecco lo sketch completo con l’IC personalizzato:
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
);
#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
()
{
}
Se hai un output Serial come questo (io uso […] per indicare la replica della linea):
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.
Le righe (o altri caratteri esadecimali) con
1
000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
indica che i dati confrontati non corrispondono , quindi (se lo schizzo di prova precedente funziona) probabilmente hai avuto qualche problema.
Nella maggior parte dei casi, la velocità dello SPI è troppo alta; questo non significa che la velocità sia troppo alta per il microcontrollore o IC, ma può essere un problema con un cavo di connessione scadente.
Arduino MKR SAMD è supportato molto bene da questa libreria, quindi non devi fare nulla. Vedremo meglio nel prossimo paragrafo.
Ma se la soluzione fosse stata ridurre la velocità devi aggiungere una riga come questa dopo flash.begin()
:
flashTransport.setClockSpeed(
24000000
,
24000000
);
il comando imposta la velocità SPI a 24 Mhz, e ora il risultato diventa così:
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.
Se non vengono visualizzati errori di confronto, la flash SPI è stata configurata correttamente.
Limitazioni degli Arduino SAMD
Per i dispositivi Arduino SAMD, la libreria blocca internamente la velocità massima a 12MHz, che è il limite dell’interfaccia sercom, ma puoi creare tutte le connessioni SPI che desideri.
1
2
3
4
5
#if
defined(ARDUINO_ARCH_SAMD)
&
&
!
defined(__SAMD51__)
rd_speed
=
min
(
12000000
, rd_speed);
#endif
Sketch pratico
Arduino SAMD 1010 wifi external SMD SPI Flash w25q64
Prima di tutto, devi formattare la flash SPI; negli esempi di Adafruit_SPIFlash, puoi trovare l’ esempio SdFat_format
, che formatta la flash SPI per te.
Quando avvii lo sketch, ti chiede di inserire, nel monitor Serial, “OK” in maiuscolo, ecco il risultato dell’output seriale.
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!
Ora sei pronto per utilizzare la flash SPI con FAT FS.
Se vuoi usare il file system FAT, ti consiglio di usare una flash SPI con più di 1Mb di spazio.
Ecco un semplice sketch che crea un file test.txt con la stringa <num> -> testing 1, 2, 3.
100 volte.
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!"
));
}
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
() {
}
Il risultato sarà così:
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
Ora possiamo chiamare alcuni comandi per recuperare le informazioni sul filesystem e quindi ottenere l’elenco dei file con il comando ls.
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!"
));
}
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
) {
}
Il risultato sarà
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
Grazie
Arduino SAMD NINA: piedinatura, specifiche e configurazione Arduino IDE
Arduino SAMD NINA: WiFiNINA, aggiornamento firmware e led RGB
Arduino SAMD (NANO 33 e MKR): file system FAT su memoria flash SPI esterna
Shield Arduino NANO 33 IoT per supporto memorie Flash SPI
Shield Arduino MKR WiFi 1010 per supporto memorie Flash SPI
i2c Arduino SAMD MKR: interfaccia aggiuntiva SERCOM, rete e scanner di indirizzi
Arduino MKR SAMD: file system FAT su memoria flash SPI esterna
Collegamento dell’EByte E70 ai dispositivi Arduino SAMD (Nano 33, MKR…) e un semplice sketch di esempio