m-mcgowan / spark-flashee-eeprom

Eeprom emulation using external flash on Particle devices. Includes unit tests cross compiled to regular gcc, and on-device integration tests.
GNU Affero General Public License v3.0
34 stars 8 forks source link

Flash write eventually throws SOS #13

Closed nolanhergert closed 9 years ago

nolanhergert commented 9 years ago

Hey Matt,

I am having problems when I'm using the AddressErase scheme. I've tried structs of both size 28 and 32 bytes, and a "flash size" of 980 and 1200 bytes, and the same thing happens for both. What happens is MultiWriteFlashStore::writeErasePage() gets caught somehow and does an infinite recursion and blows the stack.

When I wipe the flash and rerun my code, it works for 8 repetitions and then does the infinite recursion. When I don't erase the flash, it's random-ish when it shows up, but probably less than 8.

I added some printf's before line 224 to help debugging inside of the writeErasePageBuf function:

    sprintf(foo2,"A: %08x, D: %08x, O: %d, L: %d, S: %d",(uint)address, (uint) dest, (int)offset,(int)length, (int)bufSize);
    Serial.println(foo2);

It seems to always be blowing up on the page boundary, but I don't have a good handle on the inner workings to debug it more. Can you help?

Normal Behavior

Writing to: 448 A: 000001cc, D: 00000e60, O: 0, L: 28, S: 128 A: 000001cc, D: 00000ee0, O: 16, L: 28, S: 128 Writing to: 476 A: 000001e8, D: 00000f40, O: 0, L: 23, S: 128 A: 000001e8, D: 00000fc0, O: 16, L: 23, S: 128 A: 000001ff, D: 00000ffe, O: 0, L: 5, S: 128 Writing to: 504 A: 00000204, D: 00001026, O: 0, L: 28, S: 128 A: 00000204, D: 000010a6, O: 16, L: 28, S: 128

Notes: The 2nd write encounters the end of the page boundary and handles it with an extra recursion. The code continues on normally.

After 8 Writes

Writing to: 448 A: 000001cc, D: 00000e60, O: 0, L: 28, S: 128 A: 000001cc, D: 00000ee0, O: 16, L: 28, S: 128 Writing to: 476 A: 000001e8, D: 00000f40, O: 0, L: 23, S: 128 A: 000001e8, D: 00000fc0, O: 16, L: 23, S: 128 A: 000001ff, D: 00000ffe, O: 0, L: 5, S: 128 A: 00000200, D: 00001006, O: 0, L: 4, S: 128 A: 00000200, D: 00001006, O: 0, L: 4, S: 128 A: 00000200, D: 00001006, O: 0, L: 4, S: 128 A: 00000200, D: 00001006, O: 0, L: 4, S: 128 A: 00000200, D: 00001006, O: 0, L: 4, S: 128

Notes: Normally, the write would finish, but it keeps recursing with the same values.

I have code! This is for a local build. Don't forget the printf above if you need it


#include "application.h"

#include <math.h>

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

FlashDevice* _flash;

SYSTEM_MODE(MANUAL);

//Because the percent sign (%) is remainder in C/C++
#define mod(a,b) ((a % b) + b ) % b

// We could definitely compress this
struct Sample {
    int timestamp;
    float TH0_T;
    float TH0_H;
    float TH1_T;
    float TH1_H;
    float MC;
    float foo;
    int checksum;
};

#define HEAD_PTR_START_ADDR     (flash_addr_t)(3*sizeof(int))

//Round to a multiple of the size of the struct we are storing
const int FLASH_SIZE = floor(1200 / sizeof(Sample)) * sizeof(Sample);

void setup() {

    Serial.begin(57600);
    delay(3000);
    _flash = Devices::createAddressErase();

    // Erase all pages just to be sure
    page_count_t count = _flash->pageCount();
    for (page_count_t i=0; i<count; i++) {
        if (!_flash->erasePage(i*_flash->pageSize())) {
            Serial.print("Wasn't able to erase page: ");
            Serial.println(i);
        }
    }
}

void loop() {
    Sample s;
    char temp[100];
    int addr = 0;

    //Stress test the flash chip
    while (1) {
        s.timestamp = millis();
        s.TH0_T = 03.4567*s.timestamp;
        s.TH0_H = 14.5678*s.timestamp;
        s.TH1_T = 25.6789*s.timestamp;
        s.TH1_H = 36.7890*s.timestamp;
        s.MC    = 47.8901*s.timestamp;
        s.foo   = 23.987*s.timestamp;
        s.checksum = 0x31421519*s.timestamp;
        sprintf(temp,"Writing to: %d",addr);
        Serial.println(temp);
        _flash->write(&s, (flash_addr_t)(addr + HEAD_PTR_START_ADDR), (page_size_t)sizeof(s));
        addr = mod(addr + sizeof(s),FLASH_SIZE);
        delay(10);
    }
}
m-mcgowan commented 9 years ago

Hi @nolanhergert - I recently added a fix to the address erase scheme - could you pull the latest code and try again. Specifically it affect addresses in the region you are writing to.

nolanhergert commented 9 years ago

Seems to work well now! Thanks!

m-mcgowan commented 9 years ago

w00t! Thanks for coming back with that! :+1: