provides direct flash access and eeprom-like access
can use all the external flash - emulates address erasable eeprom over specified regions (up to 1MB per region.)
performs wear leveling so erases to the same page are distributed across all pages in the flash device, improving endurance.
circular buffer for dumping in data for later retrieval (e.g. buffering data to be sent out over wifi.)
streamed read/write interface for convenient saving and loading of data
small memory overhead - uses 9 bits of data for each page of flash managed. No overhead for direct access to flash.
I’m rather proud of how this library was developed.
The library was developed first as a regular C++ GCC library, with unit and integration tests using Google Test. This was possible because of the key FlashDevice abstraction.
I then coded a SparkFlashDevice and compiled the code for the spark. I also ported over ArduinoUnit - let’s call it SparkUnit - and ported the integration tests from Google Test over to SparkUnit so that the same core set of integration tests that I had running on the desktop were now running on the spark. This gives a high confidence that the library is correct.
Flashee now supports the file storage via the FAT filesystem!!! You can allocate upto 1MB for a FAT12 filesystem. Since it’s based on the wear leveling layer in flashee, the files are completely rewritable, and there’s no danger of the first few sectors containing the filesystem structures being prematurely worn since the wear will be distributed over the free space.
The FAT filesystem is provided by the excellent fatfs library, I simply had to provide a block device based on the FlashDevice provided by flashee, and some logic to detect if the filesystem needs formatting.
The library contains an example application to experiment with creating, deleting and viewing a file, as well as listing the root directory and showing used/free space in the filesystem.
Here’s an example session - each time the user presses a key the system prints "cmd: ".
FAT filesystem successfully mounted.
Commands:
c - create file abc.txt
d - delete file abc.txt
l - list files and show used/free space
p - print file contents
cmd: create file abc.txt
Created file abc.txt
cmd: delete file abc.txt
Deleted file abc.txt
cmd: delete file abc.txt
Unable to delete file :File not found
cmd: create file abc.txt
Created file abc.txt
cmd: dir
06/22/2014 23:14:50 26 ABC.TXT
1007 KiB total drive space.
1006 KiB available.
cmd: print file abc.txt
The world's smallest NAS?
cmd: create file abc.txt
Unable to create file :File exists
cmd: delete file abc.txt
Deleted file abc.txt
Hehe, I think this is pretty cool!
So dfu-util doubles as a filesystem backup and restore program! And since we are using standard FAT partitions, you can use one of the many virtual FAT drivers to create a image file and upload that to the spark with dfu-util to pre-populate your app’s filesystem.
Do I need to put everything from firmware/ directory if i’m compiling locally and don’t want FAT support - just write like 2 values only? Won’t it increase memory usage?
Hi @ryotsuke! Great that you want to use my library!
The FAT support doesn’t increase memory usage unless you actually use it, but to be sure you can just leave out the ff.cpp file.
Pull the headers into a inc/flashee-eeprom, and pull flashee-eeprom.cpp into your src folder. Edit build.mk, and add flashee-eeprom.cpp to the list of source files. And since you don’t want FAT support then you don’t need to pull ff.cpp.
It certainly will simplify page write and erase problems.128K storage option is fine for my data logging application but do you have any example code for writing strings of data to this NV storage area. I tried using the header info but on compilation received an error message “fatal error: flashee-eeprom/flashee-eeprom.h: No such file or directory”.
Are you compiling locally or using the CLI/online IDE? In the online IDE, you’ll need to at least add the library to your app before you can use it. If you’re compiling locally, the instructions above describe how you get the sources into your local build.
Thanks for the advice. I am a relative novice with the ‘Spark’ and am on a steep learning curve. I must profess to being a bit lazy and looking for the easy route. I have been using the online compiler in ‘Build’ but when I am more conversant will try and compile locally. I assume the library can be added with an “include” statement.
Have you tried using Flashee? Have now found that “Flashdevice* flash = Devices::createAddressErase();” needs to be called within each function before writing or reading data rather than being called just once in setup();
Thanks. I have now done that but the “Getting Started” documentation is a little ambiguous on this and I understood it to mean just enter “FlashDevice* flash = Devices::createAddressErase();” in setup();
P.S. I have compiled my app with this code and it is now an 88kB binary file instead of 84kB. When I flash it seems to go through the motions with the usual high speed flashing of the LED for writing and read verification but then I get the red flashing kiss of death. Could it be that the compiled code is too large?
You’re right, the current docs aren’t clear in this regard. I had rewritten the getting started section but didn’t push to the github repo. (D’oh!) But I just pushed the changes now, so hopefully it’s clearer, but let me know if not!