Batteriegepufferte Backup-Register des STM32 nutzen
In meinem Artikel zur internen Echtzeituhr des STM32 hatte ich ja schon erwähnt, dass es Backup-Register gibt, dessen Inhalt durch die Pufferbatterie an VBat erhalten bleibt, auch wenn der STM32 den Strom verliert.Für mein nächstes Projekt, ein Countdown-Wecker möchte ich die einzelnen Einstellungen hier speichern, so dass sie auch nach einem Stromausfall erhalten bleiben und ich nicht alles neu einstellen muss.
Man hätte dazu auch den Flashspeicher wählen können, dann hätte es noch nichtmal eine Backup-Batterie gebraucht, aber Flash-Speicher ist "nur" ein paar tausend mal beschreibbar, bevor er dann kaputt geht. Und da eh eine Batterie am STM32 hängt, ist dies die elegantere Methode.
Doch wieviel Speicher steht uns jetzt genau zur Verfügung?
Ein Blick in das Datenblatt zum STM32 gibt Aufschluss:
Medium-density devices are STM32F101xx, STM32F102xx and STM32F103xx microcontrollers where the Flash memory density ranges between 64 and 128 Kbytes.
20-byte data registers (in medium-density and low-density devices) or 84-byte data registers (in high-density, XL-density and connectivity line devices)Wir haben also mit unserem STM32F103C8T6 auf der Blue Pill 20 Bytes zur Verfügung. Diese sind in 10 Register-Worte à 16 Bit eingeteilt. Diese Register werden nach einem Stromausfall ohne VBat-Pufferung auf 0x00 zurückgesetzt und sind standardmäßig schreibgeschützt.
Zugriff auf die Backup-Register
Beim Zugriff auf die Backup-Register helfen uns wieder die Libraries von Roger Clark, die wir bereits installiert haben sollten.Interessant ist hier besonders https://github.com/rogerclarkmelbourne/Arduino-STM32F1-corelibs/blob/master/cores/maple/libmaple/bkp_f1.c, wo entsprechende Zugriffsfunktionen implementiert sind:
- void bkp_init(void): initialisiert den Zugriff
- uint16 bkp_read(uint8 reg): liest ein Register
- void bkp_enable_writes(void): schaltet Schreibzugriff ein
- void bkp_disable_writes(void): schaltet Schreibzugriff aus
- void bkp_write(uint8 reg, uint16 val): schreibt einen Wert in ein Register
Zu beachten ist, dass wir den Schreibzugriff mit bkp_enable_writes erlauben müssen, bevor wir etwas schreiben können.
Hier ein kleines Beispielprogramm, dass den Regsiterzugriff testet:
Source-Code
////////////////////////////////////////////////////////
// (C) 2019 by Oliver Kuhlemann //
// Bei Verwendung freue ich mich über Namensnennung, //
// Quellenangabe und Verlinkung //
// Quelle: http://cool-web.de/arduino/ //
////////////////////////////////////////////////////////
#include <libmaple/libmaple.h>
#include <libmaple/bkp.h>
void setup() {
bkp_init();
bkp_enable_writes(); // Schreibschutz aufheben
for (byte i = 0; i < 42; i++) { // optimistischerweise versuchen, alle 42 Register zu beschreiben
bkp_write (i, i+1); // nach erstem Lauf auskommentieren
}
bkp_disable_writes(); // Schreibschutz wieder aktivieren
}
void loop() {
uint16_t w;
for (byte i = 0; i < 42; i++) {
w = bkp_read (i); // Register auslesen
Serial.print (i);
Serial.print (":");
Serial.print (w);
Serial.print (" ");
}
Serial.println();
delay (5000);
}
Die Ausgabe des Programmes (nachdem wir den bkp_write-Befehl auskommiert haben) sieht so aus:
0:0 1:2 2:3 3:4 4:5 5:6 6:7 7:8 8:9 9:10 10:0 11:0 12:0 13:0 14:0 15:0 16:0 17:0 18:0 19:0 20:0 21:0 22:0 23:0 24:0 25:0 26:0 27:0 28:0 29:0 30:0 31:0 32:0 33:0 34:0 35:0 36:0 37:0 38:0 39:0 40:0 41:0
Was auffällt ist, das sich Register 0 nicht beschreiben lässt und Register 10 den Wert nur bis zum Reset hält und dann auf 0x00 zurückspringt. Aber das ist ja auch schon das 11. Register (gezählt ab Null). Die weiteren Register bis 41 behalten ihren Null-Wert. Diese sind im medium F103 nicht vorhanden.Uns bleiben also Register 1 bis 9 (Übergabewerte uint8 reg), also 18 Byte, die wir zuverlässig benutzen können.
Hier noch ein kleines Video mit einer Demonstration der Speicherfähigkeiten:
