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 wrden 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: Das ist auch schon alles, was wir für den Zugriff brauchen.

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 bentuzen können.

Hier noch ein kleines Video mit einer Demonstration der Speicherfähigkeiten: