Electronic – Read and Write multi variable (Struct) from/to external FRAM memory over SPI by ATMEGA Using Code Vision

avrcodevisionnon-volatile-memoryspi

I am working on a project to read some data from ADC and store them in external FRAM over SPI.
I have 8 different float values which need to save when the power is off or other specific situation and after power get on read each value and continue from saved variables.
So my question is if I save them in array ot structure how can I write and read them from FRAM.
Thanks in advance.

Best Answer

SPI memories on AVR microcontrollers are not memory mappable: you can't tell the ATMEGA that you have connected a memory, and let it map the device in the memory area, and take care of all the commands required by the read/write operations.

Instead, you have to manually create your functions readByte/writeByte, to read and write a single byte to the FRAM through the SPI.

Then, you create the functions readBuffer/writeBuffer, and pass the pointer of that structure, and the sizeof that structure (and the destination address in the FRAM, of course).

Still, working directly on an external SPI memory will be extremely slow. A better idea is to work on a copy in the internal RAM, and then adopt one of the following strategies:

  • copy the structure just before the AVR is turned off or it goes to sleep mode (you might need some hardware to detect when power is being removed, and have some reservoir capacitor to actually be able of saving data to the FRAM).
  • copy the structure when a write operation occurs (slower, but does not require additional hardware).

In any case, when the device is powered, you must copy the data from the FRAM back to the internal RAM.

EDIT:

As you said, you have already the functions that write and read a byte to/from the FRAM. You just need to create a function that read a larger amount of data, and writes a larger amount of data. Then you can do the following:

void writeBuffer (uint16_t address, uint8_t *data, int16_t size)
{
   for (; size>0; size--)
   {
      writeByte (address++, *data++);
   }
}
void readBuffer (uint16_t address, uint8_t *data, int16_t size)
{
   for (; size>0; size--)
   {
      *data++ = readByte (address++);
   }
}

Then to read the structure:

readBuffer(address, (uint8_t*) &yourStructure, sizeof(yourStructure));

To write:

writeBuffer(address, (uint8_t*) &yourStructure, sizeof(yourStructure));