Let's get (non)volatile

One option is to use the external flash; the Core has 2MB of external flash, of which we’re only using 0.5MB, and the remaining space is reserved for the user.

Here’s a quick interface written up by @zachary, but not yet integrated into our code:


The following two functions can be used similarly to EEPROM.read() and EEPROM.write() to access the 1.5MB available on the external flash chip.

Addresses passed to these two functions can range from 0 to 1,572,863 = 0x17FFFF. The corresponding address on the external flash is from 0x80000 to 0x1FFFFF. In case you haven’t seen it, the memory map for the external flash chip is here:

http://docs.spark.io/#/hardware/memory-mapping-external-flash-memory-map

One significant quirk—this chip can only be accessed 16 bits at a time, so you can NOT pass odd addresses. All addresses must be even.

Another “just in case you didn’t know”—you can use dfu-util to read and write directly between your computer and the external flash chip on the Core. That’s how we program keys and factory reset firmware onto external flash during manufacturing.


int SparkFlash_read(int address)
{
  if (address & 1)
    return -1; // error, can only access half words

  uint8_t values[2];
  sFLASH_ReadBuffer(values, 0x80000 + address, 2);
  return (values[0] << 8) | values[1];
}

int SparkFlash_write(int address, uint16_t value)
{
  if (address & 1)
    return -1; // error, can only access half words

  uint8_t values[2] = {
    (uint8_t)((value >> 8) & 0xff),
    (uint8_t)(value & 0xff)
  };
  sFLASH_WriteBuffer(values, 0x80000 + address, 2);
  return 2; // or anything else signifying it worked
}

Additionally, as you can see and probably guess, it’s much more efficient to write large buffers than to write a half word at a time. If your surrounding code:

  • guarantees even addresses and numbers of bytes
  • adds 0x80000 to addresses, and
  • converts data to/from a byte array

then you would do better to just call sFLASH_ReadBuffer or sFLASH_WriteBuffer directly with a larger number of bytes as the final argument.

3 Likes