non-volitile variable storage??

11 Oct 2010

Hello ladies and gents.

I have some variables (floating point doubles) that I would like to store in some form of internal memory so that they can be recalled during reset.  I would prefer not to use some in built filesystem.  I would not be totally opposed to maybe some spi external flash memory however less external hardware is probably best for me.  What options do I have with the mbed system?  Eventually this code may be ported to a non mbed board for a more production type system.

Thanks!!!

11 Oct 2010

1. RTC backup registers (around 20 bytes, needs backup battery)
2. internal on-chip flash (not the FS which actually uses an SPI flash chip); you'll have to be careful with erase and wear. See here.
3. External SD card.
4. external USB drive

11 Oct 2010

I wouldnt be writing to them often but would read from them at each power up.  

12 Oct 2010

Hi Matt

Here's a code snippet showing how to use the RTC registers:

// restore energy totalisers from rtc registers if previous update within 600 seconds
void restoreTotalisers() {
    time_t seconds = time(NULL);
    if (LPC_RTC->GPREG4 > seconds - 600 && LPC_RTC->GPREG4 < seconds) {
        elecMonitor.setRawEnergy(LongLong(LPC_RTC->GPREG0, LPC_RTC->GPREG1).Value());
        gasMonitor.setCount(LPC_RTC->GPREG2);
    } else {
        LPC_RTC->GPREG0 = 0;
        LPC_RTC->GPREG1 = 0;
        LPC_RTC->GPREG2 = 0;
        //LPC_RTC->GPREG3 = 0;
        LPC_RTC->GPREG4 = 0;
    }
}

// save totalisers and seconds when updated
void saveTotalisers() {
    time_t seconds = time(NULL);
    LongLong rawEnergy(elecMonitor.RawEnergy());
    LPC_RTC->GPREG0 = rawEnergy.Reg0();
    LPC_RTC->GPREG1 = rawEnergy.Reg1();
    LPC_RTC->GPREG2 = gasMonitor.Count();
    LPC_RTC->GPREG4 = seconds;
}

LongLong is a union that helps convert a 64-bit number into two 32-bit registers. If you are using doubles, you'll need something similar. As Igor points out, you only have 20 bytes to play with though in the RTC (GPREG0 to GPREG4).

 

// union to convert between long long, uint32_t registers and unsigned chars
union LongLong {
private:
    unsigned char _bytes[8];
    uint32_t _reg[2];
    long long _value;

public:
    LongLong(unsigned char *bytes) {
        for (int i = 0; i < 8; i++)
            _bytes[i] = bytes[i];
    }

    LongLong(uint32_t reg0, uint32_t reg1) {
        _reg[0] = reg0;
        _reg[1] = reg1;
    }

    LongLong(long long value) {
        _value = value;
    }

    long long Value() {
        return _value;
    }

    uint32_t Reg0() {
        return _reg[0];
    }

    uint32_t Reg1() {
        return _reg[1];
    }
    
    unsigned char* Bytes() {
        return _bytes;
    }
};

Regards
Daniel