SPI FRAM

Hi guys,

I'm trying to log data on a SPI FRAM breakout (4 Mbit / 512 KBytes - MB85RS4MT) from adafruit. So far I've been able to log data using fram.write8(uint32_t addr, uint8_t value) and the associated read function.

Since speed if a concern, I tried out: fram.write8(uint32_t addr, uint8_t *value, size_t count) and I'm getting something but not quite what I want. Here's the code:

/*
  https://www.adafruit.com/product/4719
  https://github.com/adafruit/Adafruit_FRAM_SPI/blob/master/Adafruit_FRAM_SPI.cpp#L200
*/

#include <SPI.h>
#include "Adafruit_FRAM_SPI.h"

uint8_t FRAM_CS = 10;

Adafruit_FRAM_SPI fram = Adafruit_FRAM_SPI(FRAM_CS);  // use hardware SPI

struct DATA {
  uint16_t data00;
  uint16_t data01;
  uint16_t data02;
  uint16_t data03;
  uint16_t data04;
  uint16_t data05;
  uint16_t data06;
  uint16_t data07;
  uint16_t data08;
  uint16_t data09;
};

struct DATA src;
struct DATA *ptrSrc = &src;
struct DATA dst;
struct DATA *ptrDst = &dst;

uint32_t  framAddr = 0;


void setup() {
  Serial.begin(9600);

  // setup fram module
  if (fram.begin(3)) {
    Serial.println("Found SPI FRAM");
  } else {
    Serial.println("No SPI FRAM found ... check your connections\r\n");
    while (1);
  }

  // populate data
  ptrSrc->data00 = 100;
  ptrSrc->data01 = 100;
  ptrSrc->data02 = 100;
  ptrSrc->data03 = 100;
  ptrSrc->data04 = 100;
  ptrSrc->data05 = 100;
  ptrSrc->data06 = 100;
  ptrSrc->data07 = 100;
  ptrSrc->data08 = 100;
  ptrSrc->data09 = 100;

  // write function
  fram.write(framAddr, (uint8_t *) ptrSrc, sizeof(src));

  // read function
  fram.read(framAddr, (uint8_t *) ptrDst, sizeof(dst));

  // print data
  Serial.print(dst.data00); Serial.print(",");
  Serial.print(dst.data01); Serial.print(",");
  Serial.print(dst.data02); Serial.print(",");
  Serial.print(dst.data03); Serial.print(",");
  Serial.print(dst.data04); Serial.print(",");
  Serial.print(dst.data05); Serial.print(",");
  Serial.print(dst.data06); Serial.print(",");
  Serial.print(dst.data07); Serial.print(",");
  Serial.print(dst.data08); Serial.print(",");
  Serial.println(dst.data09);
}

void loop() {
}

/* NOT USED BY THE CODE
  WRITE
  void Adafruit_FRAM_SPI::write(uint32_t addr, uint8_t *values, size_t count) {
  uint8_t prebuf[10];
  uint8_t i = 0;

  prebuf[i++] = OPCODE_WRITE;
  if (_nAddressSizeBytes > 3)
    prebuf[i++] = (uint8_t)(addr >> 24);
  if (_nAddressSizeBytes > 2)
    prebuf[i++] = (uint8_t)(addr >> 16);
  prebuf[i++] = (uint8_t)(addr >> 8);
  prebuf[i++] = (uint8_t)(addr & 0xFF);

  spi_dev->write(values, count, prebuf, i);
  }

  READ
  void Adafruit_FRAM_SPI::read(uint32_t addr, uint8_t *values, size_t count) {
  uint8_t buffer[10];
  uint8_t i = 0;

  buffer[i++] = OPCODE_READ;
  if (_nAddressSizeBytes > 3)
    buffer[i++] = (uint8_t)(addr >> 24);
  if (_nAddressSizeBytes > 2)
    buffer[i++] = (uint8_t)(addr >> 16);
  buffer[i++] = (uint8_t)(addr >> 8);
  buffer[i++] = (uint8_t)(addr & 0xFF);

  spi_dev->write_then_read(buffer, i, values, count);
  }
*/

and here's what I'm getting:

Found SPI FRAM
513,1027,1541,2055,2569,3083,3597,4111,4625,5139

I'm getting 10 values not they all should be 100.

What am I doing wrong ?

Any help is appreciated. Thanks

Hi everyone,

I've been trying different things but none of them worked, now I'm getting :

Found SPI FRAM
0⸮,0,0,0,0,0,0,0,0,0

This is the code I'm using:

/*
  https://www.adafruit.com/product/4719
  https://github.com/adafruit/Adafruit_FRAM_SPI/blob/master/Adafruit_FRAM_SPI.cpp#L200
*/

#include <SPI.h>
#include "Adafruit_FRAM_SPI.h"

uint8_t FRAM_CS = 10;

Adafruit_FRAM_SPI fram = Adafruit_FRAM_SPI(FRAM_CS);  // use hardware SPI

struct DATA {
  uint16_t data00;
  uint16_t data01;
  uint16_t data02;
  uint16_t data03;
  uint16_t data04;
  uint16_t data05;
  uint16_t data06;
  uint16_t data07;
  uint16_t data08;
  uint16_t data09;
};

struct DATA src;
//struct DATA *ptrSrc = &src;
struct DATA dst;
//struct DATA *ptrDst = &dst;

uint32_t  framAddr = 0;


void setup() {
  Serial.begin(9600);

  // setup fram module
  if (fram.begin(3)) {
    Serial.println("Found SPI FRAM");
  } else {
    Serial.println("No SPI FRAM found ... check your connections\r\n");
    while (1);
  }

  uint8_t *ptrSrc = (uint8_t*) &src;
  uint8_t *ptrDst = (uint8_t*) &dst;

  src.data00 = 100;
  src.data01 = 100;
  src.data02 = 100;
  src.data03 = 100;
  src.data04 = 100;
  src.data05 = 100;
  src.data06 = 100;
  src.data07 = 100;
  src.data08 = 100;
  src.data09 = 100;


  // write function
  fram.write(framAddr, (uint8_t ) *ptrSrc, sizeof(src));

  // read function
  fram.read(framAddr, (uint8_t ) *ptrDst, sizeof(dst));

  // print data
  Serial.print(dst.data00); Serial.print(",");
  Serial.print(dst.data01); Serial.print(",");
  Serial.print(dst.data02); Serial.print(",");
  Serial.print(dst.data03); Serial.print(",");
  Serial.print(dst.data04); Serial.print(",");
  Serial.print(dst.data05); Serial.print(",");
  Serial.print(dst.data06); Serial.print(",");
  Serial.print(dst.data07); Serial.print(",");
  Serial.print(dst.data08); Serial.print(",");
  Serial.println(dst.data09);
}

void loop() {
}

/*
  WRITE
  void Adafruit_FRAM_SPI::write(uint32_t addr, uint8_t *values, size_t count) {
  uint8_t prebuf[10];
  uint8_t i = 0;

  prebuf[i++] = OPCODE_WRITE;
  if (_nAddressSizeBytes > 3)
    prebuf[i++] = (uint8_t)(addr >> 24);
  if (_nAddressSizeBytes > 2)
    prebuf[i++] = (uint8_t)(addr >> 16);
  prebuf[i++] = (uint8_t)(addr >> 8);
  prebuf[i++] = (uint8_t)(addr & 0xFF);

  spi_dev->write(values, count, prebuf, i);
  }

  READ
  void Adafruit_FRAM_SPI::read(uint32_t addr, uint8_t *values, size_t count) {
  uint8_t buffer[10];
  uint8_t i = 0;

  buffer[i++] = OPCODE_READ;
  if (_nAddressSizeBytes > 3)
    buffer[i++] = (uint8_t)(addr >> 24);
  if (_nAddressSizeBytes > 2)
    buffer[i++] = (uint8_t)(addr >> 16);
  buffer[i++] = (uint8_t)(addr >> 8);
  buffer[i++] = (uint8_t)(addr & 0xFF);

  spi_dev->write_then_read(buffer, i, values, count);
  }
*/

Any ideas what is wrong ?

No matter what I try I either get only 0's or that 512 addition.

I really don't get where the mistake is/are. I've based the code on a existing one that does the same and works great.
Is there something special in the write function that I'm doing wrong?

https://github.com/adafruit/Adafruit_FRAM_SPI/tblob/master/Adafruit_FRAM_SPI.cpp#L192  
void Adafruit_FRAM_SPI::write(uint32_t addr, uint8_t *values, size_t count) {
  uint8_t prebuf[10];
  uint8_t i = 0;

  prebuf[i++] = OPCODE_WRITE;
  if (_nAddressSizeBytes > 3)
    prebuf[i++] = (uint8_t)(addr >> 24);
  if (_nAddressSizeBytes > 2)
    prebuf[i++] = (uint8_t)(addr >> 16);
  prebuf[i++] = (uint8_t)(addr >> 8);
  prebuf[i++] = (uint8_t)(addr & 0xFF);

  spi_dev->write(values, count, prebuf, i);
  }

I'm confused ^^

I have a bunch of SPI SRAM (not FRAM) and looking at the datasheet of the FRAM, the OPCODES are identical. I can probably modify my SPI SRAM drivers a bit to make it work with the FRAM version. Let me see what I can do here...

Hi,

That would be nice indeed. Is your code arduino specific or can it be used by an Teensy too ?

Regarding the code above, do you have any idea why it is not working ?

I have SPI drivers for AVRs (Atmega, attiny, xmega), and LPC microcontrollers. I haven't written one for the "Crossover MCUs" used on the Teensy, and I don't have a dev board with that MCU. I thought you are using an Arduino for it.

Regarding the code above, do you have any idea why it is not working ?

Not really as I haven't studied the Adafruit driver. But in general, most SPI SRAM/FRAM behaves the same and easy to port code if you already have the low-level drivers for the SPI peripheral.

fram.write8(uint32_t addr, uint8_t value)

This one looks like it operates one byte at a time (same as the I2C code), thus very slow.

I've tried the following write function and as you said it is pretty slow.

fram.write8(uint32_t addr, uint8_t value)

I've manage to find the solution to the problem. The code was fine but I didn't put "fram.writeEnable(true);" before the write function. Adding this resolved the issue:

  fram.writeEnable(true);
  fram.write(framAddr, (uint8_t *) ptrSrc, sizeof(src));
  fram.writeEnable(false);

The above write function is much faster than the standard write8() one.

Using an Arduino Uno, it took 8'332 us to store 100 bytes using write8() and 1'404 us using write().
Using a Teensy 3.5, it took 4'860 us to store 100 bytes using write8() and 633 us using write().

I'm very happy about the result since my goal was to store 100 bytes in less than 1 milliseconds.
Here is the code:

/*
  https://www.adafruit.com/product/4719
  https://github.com/adafruit/Adafruit_FRAM_SPI/blob/master/Adafruit_FRAM_SPI.cpp#L200
*/

#include <SPI.h>
#include "Adafruit_FRAM_SPI.h"

uint8_t FRAM_CS = 10;

// Adafruit_FRAM_SPI fram = Adafruit_FRAM_SPI(FRAM_CS);  // use hardware SPI

uint8_t FRAM_SCK = 13;
uint8_t FRAM_MISO = 12;
uint8_t FRAM_MOSI = 11;
//Or use software SPI, any pins!
Adafruit_FRAM_SPI fram = Adafruit_FRAM_SPI(FRAM_SCK, FRAM_MISO, FRAM_MOSI, FRAM_CS);

struct DATA {
  uint16_t data00;
  uint16_t data01;
  uint16_t data02;
  uint16_t data03;
  uint16_t data04;
  uint16_t data05;
  uint16_t data06;
  uint16_t data07;
  uint16_t data08;
  uint16_t data09;
};

struct DATA src;
struct DATA *ptrSrc = &src;
struct DATA dst;
struct DATA *ptrDst = &dst;

uint32_t framAddr = 0;
uint16_t dataSizeInBytes = 100;
uint32_t totalTime = 0;


void setup() {
  delay(3000);
  Serial.begin(9600);

  // setup fram module
  if (fram.begin(3)) {
    Serial.println("Found SPI FRAM");
  } else {
    Serial.println("No SPI FRAM found ... check your connections\r\n");
    while (1);
  }

  // populate data
  ptrSrc->data00 = 100;
  ptrSrc->data01 = 100;
  ptrSrc->data02 = 100;
  ptrSrc->data03 = 100;
  ptrSrc->data04 = 100;
  ptrSrc->data05 = 100;
  ptrSrc->data06 = 100;
  ptrSrc->data07 = 100;
  ptrSrc->data08 = 100;
  ptrSrc->data09 = 100;

  // Start clock
  uint32_t microsAtStart = micros();

  // write function
  fram.writeEnable(true);
  fram.write(framAddr, (uint8_t *) ptrSrc, dataSizeInBytes);
  fram.writeEnable(false);

  // Stop clock and calculate total logging time
  totalTime = micros() - microsAtStart;

  // read function
  fram.read(framAddr, (uint8_t *) ptrDst, sizeof(dst));

  // print data
  Serial.print(dst.data00); Serial.print(",");
  Serial.print(dst.data01); Serial.print(",");
  Serial.print(dst.data02); Serial.print(",");
  Serial.print(dst.data03); Serial.print(",");
  Serial.print(dst.data04); Serial.print(",");
  Serial.print(dst.data05); Serial.print(",");
  Serial.print(dst.data06); Serial.print(",");
  Serial.print(dst.data07); Serial.print(",");
  Serial.print(dst.data08); Serial.print(",");
  Serial.println(dst.data09);

  // Print total logging time
  Serial.print("Time to save ");
  Serial.print(dataSizeInBytes);
  Serial.print(" Bytes : ");
  Serial.print(totalTime);
  Serial.println(" us");
}

void loop() {
}

/* NOT USED BY THE CODE
  WRITE
  void Adafruit_FRAM_SPI::write(uint32_t addr, uint8_t *values, size_t count) {
  uint8_t prebuf[10];
  uint8_t i = 0;

  prebuf[i++] = OPCODE_WRITE;
  if (_nAddressSizeBytes > 3)
    prebuf[i++] = (uint8_t)(addr >> 24);
  if (_nAddressSizeBytes > 2)
    prebuf[i++] = (uint8_t)(addr >> 16);
  prebuf[i++] = (uint8_t)(addr >> 8);
  prebuf[i++] = (uint8_t)(addr & 0xFF);

  spi_dev->write(values, count, prebuf, i);
  }

  READ
  void Adafruit_FRAM_SPI::read(uint32_t addr, uint8_t *values, size_t count) {
  uint8_t buffer[10];
  uint8_t i = 0;

  buffer[i++] = OPCODE_READ;
  if (_nAddressSizeBytes > 3)
    buffer[i++] = (uint8_t)(addr >> 24);
  if (_nAddressSizeBytes > 2)
    buffer[i++] = (uint8_t)(addr >> 16);
  buffer[i++] = (uint8_t)(addr >> 8);
  buffer[i++] = (uint8_t)(addr & 0xFF);

  spi_dev->write_then_read(buffer, i, values, count);
  }
*/

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.