Need advice using FlashDevice (flashee-eeprom.h)

I am trying to write data into a flash ram and then reading it back. I don’t understand why the flashRAM->read() call does not return the same bytes that I have written via flashRAM->write(). Below is a short test program. if you run it make sure to open the serial connection to be able to see the dump of the original data. After 5 secs it dumps the original data and after 10 secs the flashRAM bytes and they don’t match.

Am I using the FlashDevice wrong?

#include "flashee-eeprom/flashee-eeprom.h"
using namespace Flashee;

#define SPARK_ARRAY_LENGTH 622
static FlashDevice* flashRAM;
static char g_data[SPARK_ARRAY_LENGTH];

void  printArray()
{
    for(int i =0; i < SPARK_ARRAY_LENGTH; i++)
    {
        Serial.print((int)g_data[i]); 
        Serial.print("\t"); 
    }
    Serial.println();
}

void setup() {
    Serial.begin(115200);
    g_data[0] = 0;

    flashRAM = Devices::createAddressErase();
    for(int i =0; i < SPARK_ARRAY_LENGTH; i++)
    {
        g_data[i] = (i%127) +1;// avoid null
    }
    flashRAM->write(g_data, 0, SPARK_ARRAY_LENGTH);
}

void loop() {
    delay(5000);
    printArray();
    flashRAM->read(g_data, 0, SPARK_ARRAY_LENGTH);
}

I am having major problems using the flashee library. Here is a code that creates 1 red blink (Hardware error I believe) and I dont know why. Is there any more comprehensive manual or examples than the description found under the git link?

#include "flashee-eeprom/flashee-eeprom.h"
using namespace Flashee;

#define SPARK_ARRAY_LENGTH 622
static FlashDevice* flashRAM;

int led2 = D7; 

void setup() {
    pinMode(led2, OUTPUT);

    flashRAM = Devices::createAddressErase(0,8*SPARK_ARRAY_LENGTH);
    char data = 0x5d;
    flashRAM->write(&data, 0, 1);
    data = 0xaa;
    flashRAM->write(&data, 1, 1);
}

void loop() {
    char data, data2;
    flashRAM->read(&data, 0, 1);
    flashRAM->read(&data2, 1, 1);
    if(data =! 0x5d || data2 != 0xaa)
    {
        digitalWrite(led2, HIGH);
        delay(1000);
        digitalWrite(led2, LOW); 
        delay(1000);
    }
}

@MarkusL,

the variables data and data2 is declared after the setup() that’s why.

You might want to put them before setup() and try again!

1 Like

@kennethlimcp: I am not sure I understand your comment. Why would the location of the destination buffer play a role? You might have suggested what is show below, but it crashes with the same error. See the line with the comment. If you do not specify location and size of the FlashRam then it does not crash:

    #include "flashee-eeprom/flashee-eeprom.h"
    using namespace Flashee;
    
    static FlashDevice* flashRAM;
    char data[256];
    
    void setup() {
        Serial.begin(9600);        
        flashRAM = Devices::createAddressErase(0,1234); //crashing
   //     flashRAM = Devices::createAddressErase(); // NO crash!
        for(int i = 0; i < 256; i++)
            data[i]= i;
        flashRAM->write(data, 0, 256);
    }
    
    void loop() {
        flashRAM->read(data, 0, 256);
        for(int i = 0; i < 256; i++)
            if(data[i] =! i)
        {
            Serial.print(i); 
            Serial.print("="); 
            Serial.println((int)data[i]); 
        }
    }

@MarkusL,

I’m not commenting about the location of the buffer. It’s about using the data in the setup() before you declared them.

You might want to try using the function to declare a space in multiples of 4096 like the in README:

    FlashDevice* eeprom = Devices::createAddressErase(0, 256*4096);

Your 1234 is not a multiple of 4096bytes (size of each page) and that might be causing the issue :wink:

@kennethlimcp, the size is not the cause. I tried below line:

flashRAM = Devices::createAddressErase(0,4096);

but that still crashes.

I am not getting anywhere debugging this code :(. Are there any projects out there using Devices::createAddressErase()?

Is anyone able to share working code?

Sorry about that. I used that recently so let me flash your code and see what’s up!

We probably need @mdma to help on this.

The wear leveling schemes require some pages for housekeeping, so the minimum size you can allocate is 4 pages.

It’s best to allocate as much as you can afford, since the effectiveness of wear leveling is related to how many free pages there are. So as a minimum

flashRAM = Devices::createAddressErase(0,10*4096);

But I would recommend you allocate much more if writes are frequent.

@mdma: thanks for the clarification on the usage of the lib. I changed the code to 10*4096 and it works now.
I am only writing 8 bytes per minute, is that within the assumed usage?

If you don’t need to use the rest of the flash then make the area much larger, e.g. 1284096 - the larger the area the more free pages and the greater erase count. With the addressErase scheme you get ca. 100,000free pages erases. You may get a lot more - It depends where you’re writing those 8 bytes to - or more specifically what they are overwriting.

@mdma so it turns out that I still have a problem writing into the flash. Here is the code that crashes between 60-90 seconds of runtime:

#include "flashee-eeprom/flashee-eeprom.h"
using namespace Flashee;

#define SPARK_ARRAY_LENGTH 622
static FlashDevice* flashRAM;
char data[SPARK_ARRAY_LENGTH];

void setup() {
    Serial.begin(9600);
    flashRAM = Devices::createAddressErase(0,128*4096);
    for(int i = 0; i < SPARK_ARRAY_LENGTH; i++)
        data[i]= i%256;
    flashRAM->write(data, 0, SPARK_ARRAY_LENGTH);
    flashRAM->write(data,   SPARK_ARRAY_LENGTH, SPARK_ARRAY_LENGTH);
    flashRAM->write(data, 2*SPARK_ARRAY_LENGTH, SPARK_ARRAY_LENGTH);
    flashRAM->write(data, 3*SPARK_ARRAY_LENGTH, SPARK_ARRAY_LENGTH);
}

void storeTimelineData(unsigned char d, unsigned long dayDataIndex)
{
  Serial.print("storeTimelineData "); Serial.println(dayDataIndex);
    flashRAM->write(&d, 0 + dayDataIndex, 1);
    flashRAM->write(&d,   SPARK_ARRAY_LENGTH + dayDataIndex, 1);
    flashRAM->write(&d, 2*SPARK_ARRAY_LENGTH + dayDataIndex, 1);
    flashRAM->write(&d, 3*SPARK_ARRAY_LENGTH + dayDataIndex, 1);
}

unsigned long idx = 0;
void loop() {
    storeTimelineData(millis() % 256,idx);
    idx++;
    delay(1000);
}

Your dayDataIndex is unbounded and incremented in each loop iteration. Loop is executed pretty quickly so this could easily run off the end of flash.

I imagine you want to increment it, mod SPARK_ARRAY_LENGTH?

idx = idx+1 % SPARK_ARRAY_LENGTH?

true but it does not matter because the core crashes when then index reaches values between 60 and 90 in my test.

@mdma: Still stuck here. Did you try running my code and does it crash on your spark as well?

I have read that sFlash is another way to access the ram - maybe that can help me here.
Is there any ‘official’ usage description?

Hi @MarkusL

Thanks for posting the code - very useful tool in trying to reproduce the problem.

However, the system doesn’t crash for me. It’s been running for 30 minutes with no crash. It could be a result of corrupted data in your external flash. As a precaution, you could clear the flash memory - this is done by adding this call:

Flashee::Devices::userFlash().eraseAll()

However, ideally flashee should never crash regardless of what is in the flash memory from before. Perhaps you could help me diagnose the problem by taking a copy of your external flash first before clearing, so I can investigate? You can do that using dfu-util:

dfu-util -d 1d50:607f -a 1 -s 0x00080000:0x180000 -D sflash.bin

I hope this helps! :slight_smile:

1 Like

@mdma: I tried your command and this is the result, it did not write the file because of ‘No such file or directory’

dfu-util 0.7

Copyright 2005-2008 Weston Schmidt, Harald Welte and OpenMoko Inc.
Copyright 2010-2012 Tormod Volden and Stefan Schmidt
This program is Free Software and has ABSOLUTELY NO WARRANTY
Please report bugs to dfu-util@lists.gnumonks.org

Filter on vendor = 0x1d50 product = 0x607f
Opening DFU capable USB device... ID 1d50:607f
Run-time device DFU version 011a
Found DFU: [1d50:607f] devnum=0, cfg=1, intf=0, alt=1, name="@SPI Flash : SST25x/0x00000000/512*04Kg"
Claiming USB DFU Interface...
Setting Alternate Setting #1 ...
Determining device status: state = dfuERROR, status = 10
dfuERROR, clearing status
Determining device status: state = dfuIDLE, status = 0
dfuIDLE, continuing
DFU mode device DFU version 011a
Device returned transfer size 1024
sflash.bin: No such file or directory

ok, I changed the command to:
dfu-util -d 1d50:607f -a 1 -s 0x00080000:0x180000 -U sflash.binin
and that worked now.

I have uploaded the bin to my dropbox here

Thanks for posting. I have the file - you can delete if you want to!

@mdma: did the memory dump lead you anywhere?
Using Flashee::Devices::userFlash().eraseAll() solved the problem and it does not crash any more.
Is there a way to find out if calling eraseAll() is necessary?