Store variables in flash

Posted on
  • Hi All,

    Is there a way to store vertaling variables in flash while running code? Like for a small DB?

    I know save() stores all ram to flash, I just want to store a few variables.

    Regards,

    Alex

  • Hi Alex, there's the STM32F1Flash module which will let you access the flash.

    You've just got to be aware that it works in pages. You can't just keep writing a single value - once you've written a value, to change it you've got to erase the whole page.

    Someone could make an EEPROM emulation module though - effectively a little journalling database that worked around the limitation.

  • Hi Gordon, that sounds tricky.. I'll have to read up as to how data is stored exactly.
    What does this mean?

    &~2047
    

    Regards,

    Alex

  • &~2047 means 'round down to the nearest 2048' - you need 2048 because that's the page size. What it's doing is setting the bottom 11 bits of the number to 0.

    So, (x+2047)&~2047 rounds up to the nearest 2048.

    The EEPROM emulation really isn't that bad. Think of it this way:

    • have one block of 2048 bytes
    • split it into 4 byte records (we have to write 4 bytes at once)
    • In each record, the first (top) byte can be a number that's the 'address', and the bottom 3 bytes is data
    • To write, you just write a new record on the end of the block (any unwritten value will be all 1s, so the value 0xFFFFFFFF)
    • To read, go through the whole block from the end backwards, looking for the record with the 'address' you want. If the same address was written more than once it doesn't matter, because we're only looking for the last one
    • When you write and the block is full, run through the block working out all the current values, erase it, and write them back in.

    I just had a go at doing this - just use the code below. At some point (if it works ok) I'll have a go at packing it into a module:

    var f = require("STM32F1Flash");
    f.unlock(); // unlock the memory
    
    var baseAddr = (process.memory().flash_binary_end+2047)­&~2047;
    var currentRecord = 0;
    // when we start up, find out how full we are
    while (f.read(baseAddr+currentRecord)!=-1)
      currentRecord+=4;
    
    // read data from the end backwards
    function read(addr) {
      var i = currentRecord-4;
      while (i>=0) {
        var d = f.read(baseAddr+i);
        if ((d>>>24) == addr) return d&0xFFFFFF;
        i-=4;
      }
    }
    
    function readAll() {
      var arr = [];
      for (var i=0;i<currentRecord;i+=4) {
        var d = f.read(baseAddr+i);
        arr[d>>24] = d&0xFFFFFF;
      }
      return arr;
    }
    
    function write(addr, data) {
      if (currentRecord < 2048) {
        f.write(baseAddr+currentRecord, (addr<<24)|(data&0xFFFFFF));
        currentRecord+=4;
      } else { 
       console.log("Compacting...");
       // we're full - we need to 'compact' the block
       // read data in
       var arr = readAll();
       // erase the block
       f.erase(baseAddr);
       currentRecord = 0;
       // write the data back
       for (var i in arr) write(i, arr[i]);
      }
    }
    
  • You use it like this:

    // write(number from 0 to 255, value from 0 to 16777215)
    write(3,42)
    write(73,1234)
    // read back
    read(3) // return 42
    // write again
    write(3,5678)
    // read again
    read(3) // return 5678
    
  • Gordon, where is code/etc saved using save() stored in the flash? Is it included in process.memory().flash_binary_end, or does the save()'ed data go at the end instead?

    How many write/erase cycles is the flash in the Espruino rated at?
    Depending on how frequently you're logging something, it would be possible to rack up a lot of write cycles. You can get I2C EEPROM chips for pretty cheap (see http://www.espruino.com/AT24 for part numbers ) either as bare chips or modules. This also has the advantage of not getting clobbered when you flash a new version of the firmware.

  • Memory layout is documented in the module's page: http://microcosm.app/out/a32

    I can't remember about write cycles offhand. But yes, this should come with a warning. Great for settings modified by the user, but you don't want to be updating it every second!

  • Hi Gordon,
    thank you for the example! I'll give it a try when I have time again!

  • Hi. a have same question, but with esp8266. need to save one variable after manual change and restore it from memory after reboot.

    //actuation temp. this variable need to store and restore from memory
    let maxTemp = 21;
    
    buttonPlus.on('click', function() {
      maxTemp++;
       save();
    });
    
    buttonMinus.on('click', function() {
      maxTemp--;
       save();
    });
    
    

    thanks

  • A lot has happened in the 6 years since this post!

    This should work on any device:

    var value = require("Storage").readJSON("myinfo",1);­
    if (value===undefined) value=21;
    
    buttonPlus.on('click', function() {
      maxTemp++;
       require("Storage").writeJSON("myinfo",ma­xTemp);
    });
    buttonMinus.on('click', function() {
      maxTemp--;
       require("Storage").writeJSON("myinfo",ma­xTemp);
    });
    
  • All working. Thanks a lot!!)

  • Post a reply
    • Bold
    • Italics
    • Link
    • Image
    • List
    • Quote
    • code
    • Preview
About

Store variables in flash

Posted by Avatar for Alex @Alex

Actions