This library allows to use the SPI flash that is embedded in every dice device in a filesystem-like way. It provides functions to create, read, write, erase etc. files similar to the SD library. The library distinguishes between two types of files. ‘Normal’ files and ‘RecordSet’ files. Recordset files, in contrast to normal files, are split into ‘records’ of equal size. The differences and advantages of each type make them suitable for the specific use cases as explained further down.

To use this library

#include "SerialFlash.h"

By including the library, the global object SerialFlash will be created. Its begin() functions has to be called before any further operations are taking place:

SerialFlash.begin();

Example

// 'Normal' file example
#include "SerialFlash.h"
SerialFlashFile file;
void setup()
{
  while(!Serial);
  SerialFlash.begin();
  if( SerialFlash.exists("myFile.txt") )
  {
    file = SerialFlash.open("myFile.txt");
    file.erase();
  }
  else
  {
    SerialFlash.recreate("myFile.txt", 8 * 1024);
  }
  file = SerialFlash.open("myFile.txt");
  String s_text = "Hello flash!";
  file.write(s_text.c_str(), s_text.length());  
}
void loop()
{
  char c = 0;
  file.seek(0);
  while((file.read(&c, 1) > 0) && (c != 255))
    Serial.write(c);
  while(1){ yield(); };
}

Use cases

Recordset file examples:
Download a file from a server (HTTP GET & writeFromClient())
Upload a file to a server (HTTP POST & readToClient())
Transfer files between the PC and a device or two devices (FileTransfer – Library)
CAN Datalogging into a file (bin/ascii)
Normal file examples:
Writing text log files
CAN ASCII datalogger
File -> Examples -> Serial_Flash -> ...

Further details:

Normal file
The in-progress file write and erase operations do NOT block read access on other files. SerialFlash automatically allocates files with flash page and sector awareness, and supports suspending in-progress write and erase operations, to minimize read latency even while the flash memory is “busy” writing data. The performance oriented design does impose some usage limitations. Files are created with a fixed size which can never change or grow. Once created, files can not be renamed or deleted (except for erasing the entire chip). Files begin with all bytes erased (255). Each byte may be written only once but may be fully erased, to allow new data to be written. Best performance is achieved by writing in 256 byte chunks, though individual bytes may be written

Record Set file
The lib has been extended by “RecordSet”-Files. A recordset-file is just like a normal file but starts internally with a header containing the file-version and the size of its “records”. A RecSet-file may be written step by step in record-set chunks. This allows to always “know” where the last record of the file is and where to continue writing new data at a later stage, respectively.

In the example the file was created with the record length 8: create( filename, length, nb_of_records, file_version ); Record 0 & 2 were written ok. Record 1 is not valid. The next write (or read) operation would start at byte 4 if the current record (3).


The marker byte of each record informs about the state of the following record
R – successfully written record, it is closed on now read only
P – marks the record as a bad record. It might have been corrupted by switching off without closing the file before.
S – this is the current record that read() / write() operations will act on. The position() of the r/w index refers in the scope of the current record (not the whole file) e.g. also for seek(), position(), available() functions.
For the user the bad-‘record’ management etc. will be transparent so bad records just won’t appear when the file is read. The same applies for the markers generally which don’t appear either. The user can simply write record by record and read the file just like any other file.
Note that record files might not only be helpful for logging (e.g. CAN/GPS logging) applications. The record file type (if ‘nb of records’ =1) would be suitable for applications that need to ensure that the file is consistent (complete and properly closed()) and when the actual size of the data is important. Examples are binary data files like application.bin files.
If small files should be transferred (e.g. to a web server) it also makes sense to only transfer the actual data and not a large file with the minimum page size of 64kB which is mainly empty (0xff).

SerialFlash library notes / compatibility

The SerialFlash library that is delivered as part of the dice board support package is a derived version of the original code by Paul Stoffregen. (thanks for the great work by the way). This documentation comes in large parts from the explanations that can also be found within the library’s source code.

Further information

GitHub – PaulStoffregen/SerialFlash – org. code this library is based on
HTTP_Client Class
FileTransfer – Library