How to use QSPI Flash on Boron

Hi,
So I have a particle Boron and I am programming it locally in Workbench. And I have a project where I get data from an accelerometer and I want to save it to the on board flash (only 2 MB are available to users), even after it's powered off.

Can someone please point me to the correct library I am supposed to install, and how I am supposed to use this?

I have already seen this page: File system | Reference | Particle

For a place to start, there is a library called: StorageHelperRK with a number of examples. I have utilized code in the form of examples: 04-persistent.cpp & 07-validate.cpp on the Argon. I have not used it with the Boron yet, but it should work.

Check this link out too (great stuff!). This is where I first learned about this library being available:
https://community.particle.io/t/new-library-storagehelperrk/62895

Thank you so much for the reply. I am somewhat inexperienced with C++, so could I just copy the persistent.cpp code into my .ino file?

Yes, you can do that.

However, you might find it easier to eliminate the .ino file from your Workbench project and only use the .cpp file. To do that, try adding the following #include line at the top of your .cpp file, - above your other library #include(s):

#include "Particle.h"
// add the above line to the top of your example code 
// - above ALL your library #includes - and run it in the .cpp file ONLY
#include "StorageHelperRK.h"

SerialLogHandler logHandler(LOG_LEVEL_TRACE);

SYSTEM_THREAD(ENABLED);
SYSTEM_MODE(SEMI_AUTOMATIC);
... // the rest of your code here

Here is a link about using the special #include at the top - above - other #include(s) in your code:
https://community.particle.io/t/preprocessors-puzzling-behavior/63196/3

Thank you so much; you were of great help. Do you know of a library other than the one you said where reading and writing files are much simpler; like you write data with one simple function, etc.

Here is a link to Particle reference material about EEPROM emulation. These functions, I think, you are interested in:
EEPROM.put()
EEPROM.get()
and more described:
https://docs.particle.io/reference/device-os/firmware/#eeprom

It would help to create a "struct" for persistent data you want to store/retrieve and assign an address to it. This thread nicely covers this as well as assigning a data version number which comes in very handy:
https://community.particle.io/t/eeprom-technique/29263

1 Like

What is the difference between EEPROM and Flash? Will it limit the total amount of data I can store (since it uses 2 transistors instead of 1)?

On the Boron (also Argon, B Series SoM, P2, and Photon 2), the EEPROM is actually just a 4096 byte file on the file system. It's part of the baseline usage of the 2 MB flash file system along with a couple K of configuration data. The total system usage is under 10K, except on the Tracker.

So is there a way for me to write data that's as large as 2MB to the file system (non-volatile) in a easy to use way?

Exactly 2 MB? No.

You need to leave some empty space, and there's overhead in the file system so you'll never be able to actually store 2 MB of data.

Okay, so let's say I want to store up to 1.6 MB. Do you know an easy to use library with easy functions to write data (non-volatile) to the flash?

You just use the file system API to read and write files.

I tried that but the library "#include <fcntl.h>" can't be installed and gives me an error.

What development environment are you using? Workbench or Web IDE?

If Workbench, make sure you've use Particle: Configure Project for Device and selected your Boron and a recent version of Device OS.

If Web IDE, make sure you've selected a Boron and a recent version of Device OS from the Devices tab. Make sure there is a gold star before the name. The default is a device that does not support the file system if you do not select a device.

I am using Workbench on Windows 10 and I already tried that. Once I get access to my computer (in a few hours) I will post the error I get.

So this time it actually didn't get an error, but it's not running my code correctly. Here is my code:

#include <fcntl.h>

SYSTEM_THREAD(ENABLED)


void setup() {
  pinMode(7, OUTPUT);
  int fd = open("/FileSystemTest/test1.txt", O_RDWR | O_CREAT | O_TRUNC);
  if (fd != -1) {
    for(int ii = 0; ii < 100; ii++) {
        String msg = String::format("testing %d\n", ii);
        digitalWrite(7,1);
        write(fd, msg.c_str(), msg.length());
    }
    close(fd);
}

}

// loop() runs over and over again, as quickly as it can execute.
void loop() {
  // The core of your code will likely live here.

}

The LED on D7 is not on, thus I concluded that it didn't write to the flash. Am I doing something wrong?

open with O_CREAT only creates the file, not its parent directory. Try this:

int fd = open("/usr/test1.txt", O_RDWR | O_CREAT | O_TRUNC);

So, I am trying to write code to read data from the file that was created in setup; here is my code:

#include <fcntl.h>

SYSTEM_THREAD(ENABLED)

int fd;

String* buf = new String[100];

void setup() {
  pinMode(7, OUTPUT);
  Serial.begin(9600);
  fd = open("/usr/test1.txt", O_RDWR | O_CREAT | O_TRUNC);
  if (fd != -1) {
    for(int ii = 0; ii < 100; ii++) {
        String msg = String::format("testing %d\n", ii);
        digitalWrite(7,1);
        Serial.println(msg);
        write(fd, msg.c_str(), msg.length());
    }
    close(fd);
}

}

int gd;

// loop() runs over and over again, as quickly as it can execute.
void loop() {
  // The core of your code will likely live here.
gd = open("/test1.txt", O_RDWR);
if (gd != -1) {
  digitalWrite(7,0);
  int a = read(gd, buf, 100);
  Serial.println(a);
  if (a != 0) {
  Serial.println(*buf);
  close(gd);
}
}

It's not working and I don't know how to fix it since I am very new to this environment. I also tried:

gd = open("/usr/test1.txt", O_RDWR);

but that resulted in a blinking red LED. Please Help.

This is correct in loop:

gd = open("/usr/test1.txt", O_RDWR);

The reason you are getting as SOS, I presume a SOS+1 hard fault is that you allocated buf incorrectly. It should be declared:

char buf[100];

and read:

int a = read(gd, buf, sizeof(buf));

In the documentation for the File System: File system write - File system | Reference | Particle

it says to use a pointer to an array:

int read(int fd, void* buf, size_t count)

but the one you said isn't a pointer; am I doing something wrong?