FRAM Speicher bis 512 kBit

Wer in seiner Anwendung die Vorteile eines EEPROMs nutzen, sich aber über die maximale Anzahl von Schreibzyklen keine Sorgen machen möchte, der sollte sich die Verwendung von FRAMs überlegen. Mit bis zu 1 Billionen (10 hoch 12) Schreibzyklen schlägt es das EEPROM (ca. 1 Million Schreibzyklen) um den Faktor 1 Million. Das bedeutet, dass z.B. bei einem Schreibvorgang alle 10 ms ein EEPROM weniger als 3 Stunden lang beschrieben werden kann, ein Flash-Speicher (maximal 100.000 Schreibzyklen) weniger als 0,3 Stunden und ein FRAM 300 Jahre(!!) lang. Neuere FRAMs geben sogar 10 Billionen (10 hoch 13) Schreibzyklen an. Eine vielfach höhere Schreibgeschwindigkeit, einem Bruchteil des Stromverbrauches (bei Schreibvorgängen) und eine höhere Resistenz gegenüber Strahlung (z.B. bei Überprüfung des Gepäcks auf Flughäfen) sind weitere Vorteile gegenüber dem EEPROM. Die Retention der Daten (Datenerhalt) soll bei Raumtemperatur mindestens 200 Jahre und bei 85 °C immerhin noch 10 Jahre betragen (meine Ur-Ur-Ur-Enkel werden dann im Jahr 2217 berichten).

         

          

Bild: FRAM-Breakout Boards von Adafruit mit I2C-Schnittstelle (oben) und SPI-Schnittstelle (unten)

Die von mir verwendeten Breakout Boards von Adafruit sind mit FRAMs der Firma Fujitsu Semiconductor der Serie MB85Rxxxx bestückt, das I2C-Board mit einem 256 kBit Chip MB85RC256V und das SPI-Board mit einem 64 kBit Chip MB85RS64V.

Datenblätter zu den Chips gibt es hier: www.fujitsu.com/uk/products/devices/semiconductor/memory/fram/standalone/

Testaufbau mit I2C-Schnittstelle:

I2C-Adresse:

Die I2C-Adresse des Moduls kann durch Beschalten der Eingängen A2 bis A0 mit GND oder VCC zwischen 0x50 (A2-A0 auf GND) und 0x57 (A2-A0 auf VCC) eingestellt werden. Ohne Beschaltung liegen bereits die Adresseingänge durch interne Pulldown-Widerstände auf logisch Null, daher ist für die Adresse 0x50 keine Beschaltung erforderlich.


Verwendete Bauteile:

  • 1 Arduino Nano
  • 1 FRAM Breakout Board 256 kBit von Adafruit


Anschluss des FRAM (I2C-Adresse 0 0x50) an Arduino Uno/Nano und Mega:

       Arduino                     FRAM-Breakout Board (I2C)

Uno/Nano   Mega

  5V             5V         ->      VCC

  GND          GND      ->      GND

  A5             D21      ->       SCL

  A4             D20      ->       SDA

  GND          GND      ->       A2

  GND          GND      ->       A1

  GND          GND      ->       A0

  Nicht verwendet:               WP  1)


1)  WP = "Write Protect"-Pin, intern auf Pull-Down gesetzt. Durch HIGH-Setzen des Pins wird der Schreibschutz des FRAM-Speichers gesetzt!




Testaufbau mit SPI-Schnittstelle:

Verwendete Bauteile:

  • 1 Arduino Nano
  • 1 FRAM Breakout Board 64 kBit von Adafruit


Anschluss des FRAMs an Arduino Uno/Nano und Mega:

       Arduino                     FRAM-Breakout Board (SPI)

Uno/Nano   Mega

  5V             5V         ->      VCC

  GND          GND      ->      GND

  D13           D52      ->       SCK  (CLK)

  D12           D51      ->       MISO

  D11           D50      ->       MOSI

  Dx             Dx        ->       CS

  Nicht verwendet:               HOLD und WP  1)

Dx: Während die Pins für CLK, MISO und MOSI am Arduino fix vorgegeben sind (Hardware-SPI), kann der CS-Pin (Chipselect) softwaremäßig frei vergeben werden. Im nachfolgenden Beispiel wird für Dx der Pin D10 verwendet.

1)  WP = "Write Protect"- Pin. Durch LOW-Setzen des Pins wird nur der Schreibschutz des Status-Registers des FRAM gesetzt. Der Schreibschutz des FRAM-Speichers selbst, wird softwaremäßig gesetzt!


Library MyFRAM_I2C und MyFRAM_SPI:

Für Arduino habe ich für FRAMs - mit Speichergrößen bis 512 kBit (= 64 kByte) - mit I2C- und (Hardware-)SPI-Schnittstelle zwei Libraries mit folgenden Funktionen geschrieben:


Mit I2C-Schnittstelle:

  • Abfrage, ob der Baustein ansprechbar ist
  • Schreiben eines Byte
  • Schreiben einer Folge von Bytes (max. 30)
  • Vergleichen eines Speicherbereichs mit einem Array
  • Festlegen der FRAM-Startspeicherstelle für Float- und Integer-Zahlen  1)
  • Schreiben einer Integer-Zahl (im long-Format)  1)
  • Schreiben einer Float-Zahl  1)
  • Lesen eines Byte
  • Lesen einer Folge von Bytes (max. 30)
  • Lesen einer Integer-Zahl (im long-Format)  1)
  • Lesen einer Float-Zahl  1)
  • Löschen eines Bytes
  • Löschen eines Bereiches
  • Löschen des gesamten FRAMs

Mit SPI-Schnittstelle:

  • Setzten/Rücksetzen des Schreibschutzes
  • Schreiben eines Byte
  • Schreiben einer Folge von Bytes
  • Vergleichen eines Speicherbereichs mit einem Array
  • Festlegen der FRAM-Startspeicherstelle für Float- und Integer-Zahlen  1)
  • Schreiben einer Integer-Zahl (im long-Format)  1)
  • Schreiben einer Float-Zahl  1)
  • Lesen eines Bytes
  • Lesen einer Folge von Bytes
  • Lesen einer Integer-Zahl (im long-Format)  1)
  • Lesen einer Float-Zahl  1)
  • Löschen eines Bytes
  • Löschen eines Bereiches
  • Löschen des gesamten FRAMs


1)  Es können derzeit maximal 256 Float- und/oder Integer-Zahlen, die mit Variablennamen ansprechbar sind, im FRAM gespeichert werden! Die Zahlen werden, sofern nicht anders angegeben, ab der FRAM-Speicherstelle 0 gespeichert. Mit der Funktion "setStartAddress32Bit" kann diese "Startspeicherstelle" geändert werden (siehe nachfolgendes Programmbeispiel 1).


Die Libraries habe ich bisher nur mit FRAMs auf Adafruit Breakout Boards getestet, die mit Chips der Firma Fujitsu Semiconductor der Serie MB85Rxxxx bestückt sind, das I2C-Board mit einem 256 kBit Chip MB85RC256V und das SPI-Board mit einem 64 kBit Chip MB85RS64V. Inwieweit diese Chips mit FRAM-Chips anderer Hersteller kompatibel sind, habe ich bisher nicht geprüft!

Die maximale Speichergröße der FRAMs darf derzeit maximal 512 kBit (= 64 kByte) betragen. Größere FRAMs, die, soweit mir bekannt, heute mit bis zu 4 MBit (= 512 kByte) erhältlich sind, werden von den Libraries wegen der unterschiedlichen Speicherplatzadressierung (24 Bit anstelle von 16 Bit) derzeit nicht unterstützt. Sollte ich einmal ein FRAM Breakout Board mit mehr als 512 kBit erwerben, werde ich die Libraries entsprechend anpassen.


Erkennen der Speichergröße bei FRAMs mit SPI-Schnittstelle:

Aus vielen FRAM-Speicherchips mit SPI-Schnittstelle der Firma Fujitsu Semiconductor kann die Speichergröße mit dem Kommando (= OP-Code) "RDID" (Read Device ID) ausgelesen werden, z.B. bei den Chips:

  • MB85RDP16LX
  • MB85RS16
  • MB85RS16N
  • MB85RS64V
  • MB85RS128B
  • MB85RS256V
  • MB85RS512T
  • MB85RS1MT (wird derzeit von der Library nicht unterstützt)
  • MB85RS2MT (wird derzeit von der Library nicht unterstützt)

Bei diesen Chips kann eine neue Instanz ohne Angabe der Speichergröße erfolgen, z.B.:

MyFRAM_SPI fram;

Nicht ausgelesen werden kann die Speichergröße z.B. aus dem Chip:

  • MB85RS64

Hier muss die Speichergröße angegeben werden, z.B.:

MyFRAM_SPI fram(64) //FRAM mit 64 kByte


Die Libraries können hier heruntergeladen werden:

Sollte die Library jemand verwenden oder testen, würde ich mich über eine Rückmeldung sehr freuen!

Version 1.2                                              Version 1.3

Für FRAMs mit SPI-Schnittstelle:              Für FRAMs mit I2C-Schnittstelle: 

MyFRAM_SPI.cpp.txt                                 MyFRAM_I2C.cpp.txt

MyFRAM_SPI.h.txt                                     MyFRAM_I2C.h.txt

keywords.txt                                             keywords.txt

Leider kann ich hier keine "cpp"- oder "h"-Files hochladen, daher zum Verwenden der Libraries ".txt" aus den Dateinamen entfernen und in einem neuen Verzeichnis mit dem Namen "MyFRAM_SPI" bzw. "MyFRAM_I2C" dort speichern, wo eure anderen Libraries gespeichert sind.


Zur Auflistung der Funktionen der Libraries geht es hier: Funktionen

Ein FRAM-Mini-Monitor für FRAMs mit I2C- oder SPI-Schnittstelle zum Anzeigen und Löschen des Speicherinhaltes ist im nachfolgenden Programmbeispiel 2 ersichtlich!

Programmbeispiel 1 MyFRAM_SPI:

Im Beispiel 1 werden Float-Zahlen, die nicht im SRAM des Arduino, sondern im FRAM gespeichert sind, für eine Flächenberechnung verwendet. Dabei können bis zu 256 Float- oder Integer-Zahlen (im long-Format) ab einer definierbaren FRAM-Speicherstelle gespeichert werden, ohne sich dabei um die Speicheradresse der einzelnen Variablen kümmern zu müssen. Die Variablen werden über Namen angesprochen, die im Deklarationsteil des Programms mit #define-Anweisungen definiert werden, z.B.:

#define breite 2

In diesem Beispiel ist der Name der Variable "breite" und die "2" ist die Identifikationsnummer ID (diese kann 1 bis 256 betragen). Die ID sollte, um den vorgesehenen FRAM-Speicher optimal auszunutzen, beginnend mit "1" aufsteigend sein und darf nicht doppelt oder mehrfach vergeben werden.

Der Sinn, Float- und/oder Integer-Variable im long-Format in den FRAM-Speicher zu legen, liegt darin, dass z.B. beim Arduino Uno oder Nano (bzw. Mikrocontroller mit Atmega328P-Pozessor) der SRAM-Speicher nur 2 kByte beträgt und oft sehr schnell knapp wird, während im Programmspeicher (Flash-Speicher) noch Platz ist, um die Library zu verwenden.

//Programmbeispiel für FRAM mit SPI-Schnittstelle
//Code fuer Arduino
//Author Retian
//Version 1.0


#include <MyFRAM_SPI.h>


//Wenn aus dem FRAM die Speichergröße ausgelesen werden kann:
MyFRAM_SPI Fram;


//Wenn aus dem FRAM die Speichergröße nicht ausgelesen werden kann:
//MyFRAM_SPI Fram(64) //FRAM mit 64 kBit


//Startadresse für die 4-Byte Variablem im FRAM
//Hier werden die letzten 256 Bytes im FRAM für 4-Byte Variablen vorgesehen.
//Ohne Angabe würde die Startadresse die FRAM-Adresse 0 sein!
#define startAdresse 7936


//Definiere FRAM-Variable mit Identifier (1-256) für Float- und/oder Long-Zahlen
#define laenge 1
#define breite 2
#define flaeche 3


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


  Fram.begin(10); //Digital-Pin 10 ist Chip Select Pin
  Fram.setWriteEnableBit(1); //Schreibschutz Aus


  //Frage des Schreibschutzstatus ab
  if (Fram.getWriteEnableBit()) Serial.println("Schreibschutz Aus");
  else Serial.println("Schreibschutz Ein");


  //Setze startadresse fuer 4-Byte Variable im FRAM
  Fram.setStartAddress32Bit(startAdresse);


  Serial.print("Speichergröße des FRAM: ");
  Serial.print(Fram.framSize);
  Serial.println(" Byte");


  //Speichere Zahlen im FRAM
  Fram.writeFloat(laenge, 45.2);
  Fram.writeFloat(breite, 26.1);


  //Berechnen der Flaeche und speichern im FRAM
  Fram.writeFloat(flaeche, Fram.readFloat(laenge) * Fram.readFloat(breite));


  //Ausgabe
  Serial.println("\nFlaechenberechnung:");
  Serial.print("Laenge: ");
  Serial.println(Fram.readFloat(laenge));
  Serial.print("Breite: ");
  Serial.println(Fram.readFloat(breite));
  Serial.print("Flaeche: ");
  Serial.println(Fram.readFloat(flaeche));

}


void loop() {
}


Programmbeispiel 2:

Mini-Monitor für FRAMs mit I2C- und SPI-Schnittstelle

Der Mini-Monitor dient zur einfachen Überprüfung und Löschung des FRAM-Inhaltes. Nach Programmstart muss die Speichergröße (in kByte), sowie die Art der Schnittstelle I2C oder SPI angegeben werden. (Für die I2C-Schnittstelle ist die Adresse 0x50 und für die SPI-Schnittstelle der CS-Pin mit 10 im Programm vorgegeben.) Danach stehen derzeit die folgende Funktionen zur Verfügung, die über Zifferneingabe aufgerufen werden können:

  • Anzeigen des gesamten FRAM-Inhalts
  • Anzeigen eines FRAM-Bereiches
  • Löschen des gesamten FRAMs
  • Löschen eines FRAM-Bereiches

Je nach Bedarf werde ich den Funktionsumfang noch erweitern.


Der Monitor kann hier in der Version 1.2 heruntergeladen werden:

FRAM_Mini-Monitor.ino.txt

Leider kann ich hier keine "ino"-Files hochladen, daher zum Verwenden des Programms ".txt" aus dem Dateinamen entfernen und in einem neuen Verzeichnis mit dem Namen "FRAM_Mini-Monitor" dort speichern, wo eure anderen Programme gespeichert sind.

Der Mini-Monitor benötigt neben meinen Libraries MyFRAM_I2C V1.2 und MyFRAM_SPI V1.2 auch meine Library MySerialRead, die hier zu finden ist:  Serieller Monitor



Bild: FRAM-Mini-Monitor Programmstart und Anzeige des FRAM-Inhalts partiell mit Angabe des Adressbereiches