Flash Backpack basics using SerialFlash Library
Hi,
Started using the backpacks. Started with the flash storage one. Following is a basic initialize and test that may be helpful to other first time users. SerialFlash library has examples but tend to be a little complicated and of course are generic and not setup specifically for the bolder backpack. Key concept I missed at first is that this is really two different SPI devices so you need set the CS pin of the chip you are not accessing to INPUT_PULLUP. This code does the following on each chip, does a full erase, creates a file named test, writes data, reads data, checks for file existing, erases file if exists, writes data, reads data.
Code:
#include <SerialFlash.h>
int FlashChipSelect = 16;
bool eraseAllFirst;
int size;
unsigned char id[256];
SerialFlashFile file;
const unsigned long testIncrement = 4096;
float eraseBytesPerSecond(const unsigned char *id) {
if (id[0] == 0x20) return 152000.0; // Micron
if (id[0] == 0x01) return 500000.0; // Spansion
if (id[0] == 0xEF) return 419430.0; // Winbond
if (id[0] == 0xC2) return 279620.0; // Macronix
return 320000.0; // guess?
}
const char * id2chip(const unsigned char *id)
{
if (id[0] == 0xEF) {
// Winbond
if (id[1] == 0x40) {
if (id[2] == 0x14) return "W25Q80BV";
if (id[2] == 0x15) return "W25Q16DV";
if (id[2] == 0x17) return "W25Q64FV";
if (id[2] == 0x18) return "W25Q128FV";
if (id[2] == 0x19) return "W25Q256FV";
}
}
if (id[0] == 0x01) {
// Spansion
if (id[1] == 0x02) {
if (id[2] == 0x16) return "S25FL064A";
if (id[2] == 0x19) return "S25FL256S";
if (id[2] == 0x20) return "S25FL512S";
}
if (id[1] == 0x20) {
if (id[2] == 0x18) return "S25FL127S";
}
}
if (id[0] == 0xC2) {
// Macronix
if (id[1] == 0x20) {
if (id[2] == 0x18) return "MX25L12805D";
}
}
if (id[0] == 0x20) {
// Micron
if (id[1] == 0xBA) {
if (id[2] == 0x20) return "N25Q512A";
if (id[2] == 0x21) return "N25Q00AA";
}
if (id[1] == 0xBB) {
if (id[2] == 0x22) return "MT25QL02GC";
}
}
if (id[0] == 0xBF) {
// SST
if (id[1] == 0x25) {
if (id[2] == 0x02) return "SST25WF010";
if (id[2] == 0x03) return "SST25WF020";
if (id[2] == 0x04) return "SST25WF040";
if (id[2] == 0x41) return "SST25VF016B";
if (id[2] == 0x4A) return "SST25VF032";
}
if (id[1] == 0x25) {
if (id[2] == 0x01) return "SST26VF016";
if (id[2] == 0x02) return "SST26VF032";
if (id[2] == 0x43) return "SST26VF064";
}
}
return "(unknown chip)";
}
void InitializeSerialFlash(int CSPin)
{
if ( FlashChipSelect == 16)
{
pinMode(15, INPUT_PULLUP);
pinMode(16, INPUT);
}
else
{
pinMode(16, INPUT_PULLUP);
pinMode(15, INPUT);
}
Serial.print("Initializing SerialFlash on CS number:");
Serial.println(CSPin);
Serial.println();
if (!SerialFlash.begin(CSPin)) {
while (1) {
Serial.println("Unable to access SPI Flash chip");
delay(1000);
}
}
}
void PrintChipInfo()
{
SerialFlash.readID(id);
Serial.print(" JEDEC ID: ");
Serial.print(id[0], HEX);
Serial.print(" ");
Serial.print(id[1], HEX);
Serial.print(" ");
Serial.println(id[2], HEX);
Serial.print(" Part Nummber: ");
Serial.println(id2chip(id));
size = SerialFlash.capacity(id);
Serial.print("Total Size:");
Serial.println(size);
Serial.println();
}
void FullErase()
{
unsigned long startMillis = millis();
Serial.print("Flash Memory has ");
Serial.print(size);
Serial.println(" bytes.");
Serial.println("Erasing ALL Flash Memory:");
// Estimate the (lengthy) wait time.
Serial.print(" estimated wait: ");
int seconds = (float)size / eraseBytesPerSecond(id) + 0.5;
Serial.print(seconds);
Serial.println(" seconds.");
Serial.println(" Yes, full chip erase is SLOW!");
SerialFlash.eraseAll();
unsigned long dotMillis = millis();
unsigned char dotcount = 0;
while (SerialFlash.ready() == false) {
if (millis() - dotMillis > 1000) {
dotMillis = dotMillis + 1000;
Serial.print(".");
dotcount = dotcount + 1;
if (dotcount >= 60) {
Serial.println();
dotcount = 0;
}
}
}
if (dotcount > 0) Serial.println();
Serial.println("Erase completed");
unsigned long elapsed = millis() - startMillis;
Serial.print(" actual wait: ");
Serial.print(elapsed / 1000ul);
Serial.println(" seconds.");
Serial.println();
}
void OpenEraseWrite( const char *fileName, char buffer[])
{
SerialFlashFile file = SerialFlash.open(fileName);
Serial.print("Open Result:");
Serial.println(file);
Serial.print("Erasing File:");
Serial.println(fileName);
file.erase();
Serial.print("Writing:");
Serial.println(buffer);
file.write(buffer, 12);
Serial.print("Reading:");
file.seek(0);
file.read(buffer, 12);
Serial.println(buffer);
Serial.println();
}
void DoFileTest()
{
Serial.println("_________________________________");
Serial.println();
InitializeSerialFlash(FlashChipSelect);
PrintChipInfo();
if (eraseAllFirst) {
FullErase();
}
String stringOne = "Example Data in Flash With CS Pin ";
stringOne += FlashChipSelect;
char buffer[stringOne.length() + 1];
stringOne.toCharArray(buffer, stringOne.length() + 1);
//SerialFlash.remove("test");
if (SerialFlash.exists("test"))
{
Serial.println("File named test already exists");
OpenEraseWrite("test", buffer);
}
else
{
Serial.println("test does not exist...creating");
bool createResult = SerialFlash.createErasable("test", 60000);
Serial.println("Result of create erasable file named test");
Serial.println(createResult);
OpenEraseWrite("test", buffer);
}
Serial.println("_________________________________");
Serial.println();
Serial.println();
}
void setup() {
Serial.begin(9600);
while (!Serial) ;
delay(100);
eraseAllFirst = true;
FlashChipSelect = 16;
DoFileTest();
FlashChipSelect = 15;
DoFileTest();
eraseAllFirst = false;
FlashChipSelect = 16;
DoFileTest();
FlashChipSelect = 15;
DoFileTest();
}
void loop() {
// do nothing after the test
}
Serial Output should be as follows:
_________________________________
Initializing SerialFlash on CS number:16
JEDEC ID: 1 2 20
Part Nummber: S25FL512S
Total Size:67108864
Flash Memory has 67108864 bytes.
Erasing ALL Flash Memory:
estimated wait: 134 seconds.
Yes, full chip erase is SLOW!
............................................................
...............................................
Erase completed
actual wait: 107 seconds.
test does not exist...creating
Result of create erasable file named test
1
Open Result:1
Erasing File:test
Writing:Example Data in Flash With CS Pin 16
Reading:Example Data in Flash With CS Pin 16
_________________________________
_________________________________
Initializing SerialFlash on CS number:15
JEDEC ID: 1 2 20
Part Nummber: S25FL512S
Total Size:67108864
Flash Memory has 67108864 bytes.
Erasing ALL Flash Memory:
estimated wait: 134 seconds.
Yes, full chip erase is SLOW!
............................................................
............................................................
.
Erase completed
actual wait: 121 seconds.
test does not exist...creating
Result of create erasable file named test
1
Open Result:1
Erasing File:test
Writing:Example Data in Flash With CS Pin 15
Reading:Example Data in Flash With CS Pin 15
_________________________________
_________________________________
Initializing SerialFlash on CS number:16
JEDEC ID: 1 2 20
Part Nummber: S25FL512S
Total Size:67108864
File named test already exists
Open Result:1
Erasing File:test
Writing:Example Data in Flash With CS Pin 16
Reading:Example Data in Flash With CS Pin 16
_________________________________
_________________________________
Initializing SerialFlash on CS number:15
JEDEC ID: 1 2 20
Part Nummber: S25FL512S
Total Size:67108864
File named test already exists
Open Result:1
Erasing File:test
Writing:Example Data in Flash With CS Pin 15
Reading:Example Data in Flash With CS Pin 15
_________________________________