eigenen EEPROM Bereich im LPC11xx anlegen

Fragen und Diskussionen zur Entwicklung von neuen Geräten. Sowohl Hardware als auch Software. English is welcome.
Olli
Beiträge: 70
Registriert: 12. Aug 2014, 20:52
Wohnort: Moormerland / Ostfriesland

eigenen EEPROM Bereich im LPC11xx anlegen

Beitrag von Olli »

Hallo,

ich benötige für mein aktuelles Projekt einen kleinen EEPROM Bereich, so wie es auch in der sblib gemacht wurde.
Ich habe aktuell eine struct mit 9 Integern (int bzw. unsigned int).
Die struct heißt "temp_values" und davon möchte ich eine Instanz mit dem Namen "temp" haben.

Ich habe versucht mir die Vorgehensweise aus der sblib abzuschauen, aber leider funktioniert das so nicht.
Versucht habe ich folgendes zur Initialisierung:

In der Header-Datei:
extern int tempEepromData[9];

In der CPP:
int __attribute__ ((aligned (4))) tempEepromData[9];
temp_values& temp = *(temp_values*) tempEepromData;


Das lässt sich auch kompilieren und alle Funktionen sind gegeben.
Nur leider werden nach einem Neustart wieder alle Variablen mit 0 initialisiert.
Dieses wird allerdings nicht von mir explizit beschrieben, sonder wird irgendwie automatisch gemacht.
Was muss beachtet werden, dass man "normale" Speicherbereiche als EEPROM nutzen kann?

Vielen Dank und frohe Weihnachten an alle!

Olli
Florian
Beiträge: 161
Registriert: 8. Aug 2015, 23:25
Wohnort: Paderborn

Re: eigenen EEPROM Bereich im LPC11xx anlegen

Beitrag von Florian »

Für eine ähnliche Funktionalität habe ich den MemMapper benutzt. Die Doku von dem ist jetzt leider nicht sehr ausführlich, daher in Kurzfassung ein paar Schnipsel aus meinem Programm:

/*
* Der MemMapper bekommt einen 1kB Bereich ab 0xEA00, knapp unterhalb des UserMemory-Speicherbereichs ab 0xF000.
* Damit lassen sich 3 Pages (je 256Byte) (und die allocTable die MemMappers) unterbringen.
*/
MemMapperMod memMapper(0xea00, 0x400);

void setup (void)
{
_bcu.setMemMapper((MemMapper *)&memMapper);
memMapper.addRange(0x0, 0x100); // Zum Abspeichern/Laden des Systemzustands
}

Danach kann mit den Methoden des MemMappers aus dem Speicherbereich gelesen werden. Werden Daten geschrieben, landen sie erst mal nur im Ram des MemMappers. In das Eeprom geschrieben werden sie, wenn man dem MemMapper dies mitteilt, oder der die Speicherseite anderweitig benötigt.

Das Problem was bleibt ist, dass nun theoretisch dieser Speicherbereich genauso über den EIB/KNX-Bus gelesen und geschrieben werden kann, denn er wird ähnlich wie ein User-Eeprom behandelt. Bei mir habe ich das gelöst, indem ich eine abgeleitete Klasse des MemMappers erstellt habe, der die Zugriffe vom Bus auf Adressen kleiner 256 verbietet (da verstecken sich meine Daten).

Ich muss mein Machwerk bald mal in's github hochladen...
Olli
Beiträge: 70
Registriert: 12. Aug 2014, 20:52
Wohnort: Moormerland / Ostfriesland

Re: eigenen EEPROM Bereich im LPC11xx anlegen

Beitrag von Olli »

Hallo Florian,

vielen Dank für den Tipp mit dem MemMapper.
Ich habe das Ganze mal so umgesetztund musste feststellen, dass die Funktionen "getUIntX" und "setUIntX" nicht von der Byte Reihenfolge her zusammenpassen. Darin ist eine Abfrage der "endianess", die nirgendwo gesetzt wird und somit nutzlos ist (zur Zeit jedenfalls)
Naja, als ich dass entsprechend korrigiert hatte, lief mein Programm.

Bis auf das ich komische Aussetzer und Veränderungen festgestellt habe, nachdem ich die Funktion "doFlash" ausgeführt habe.
Da es bei den LPC µCs ja keinen EEPROM Bereich gibt, sondern diese Daten mit im Programmspeicher (Flash) abgelegt werden, denke ich, dass ich mit deisem Befehl einige Programmdaten überschreibe.

Du hast den Bereich an die Adresse 0xEA00 gelegt. Hast du dem Compiler in irgendeiner Form noch mitgeteilt, dass in diesem Bereich keine Programmdaten abzulegen sind?

Ich finde dazu sonst nichts. Mein Programm ist leider bereits sehr groß. Daher sind auch bereits in diesem Bereich evtl Programmdaten vom Compiler untergebracht worden?!

Grüße,
Olli
Florian
Beiträge: 161
Registriert: 8. Aug 2015, 23:25
Wohnort: Paderborn

Re: eigenen EEPROM Bereich im LPC11xx anlegen

Beitrag von Florian »

Da hast Du ja bereits fleißig gecoded :D

Auf das Problem bin ich auch schon gestoßen. Eine Methode um sicherzustellen, dass der Linker nichts in dem Speicherbereich ablegt, den der MemMapper benutzt, kenne ich auch noch nicht. Bis jetzt lasse ich mir immer das Mapping-File erzeugen und sehe dort manuell nach, ob mein Programm bereits zu groß ist.

Als Abhilfe lasse ich Teile des Programms mit Optimierung übersetzen. Leider kommt der Debugger dann immer etwas durcheinander, wenn man durch eine optimierte Routine durchsteppt. Und zwar je deutlicher, je mehr optimiert wird.

Ich optimiere die sblib mit -O3. Wenn ich tatsächlich in der sblib debuggen will, lasse ich Teile meines Programms weg.

Ich habe gerade gesehen, dass Du mir in meinen Fork der sblib einen Pull Request geschickt hast. Irgendeinen Grund, warum Du den nicht an sblib/software-arm-lib geschickt hast? Ich bin da eigentlich der falsche Ansprechpartner, ich verwalte die Lib nicht. Bitte schicke deine Änderungen an sblib/software-arm-lib, dann werden die eingearbeitet.
Olli
Beiträge: 70
Registriert: 12. Aug 2014, 20:52
Wohnort: Moormerland / Ostfriesland

Re: eigenen EEPROM Bereich im LPC11xx anlegen

Beitrag von Olli »

Hallo Florian,

vielen Dank für die schnelle Info.

Für den pull-request an dich muss ich mich entschuldigen.
Ich bin noch nicht so wirklich fit mit Github. Da ist wohl etwas schief gelaufen...
Ich wollte das Ganze eigentlich direkt an sblib/software-arm-lib senden.

Mal sehen, ob's beim nächsten Mal klappt ;-)

Grüße,
Olli
StefanSverige
Beiträge: 163
Registriert: 15. Feb 2014, 13:32

Re: eigenen EEPROM Bereich im LPC11xx anlegen

Beitrag von StefanSverige »

Hallo,

den Pullrequest muss sich StefanT mal ansehen, er hat auch die passenden Rechte für das ARM Lib Repo.

/Stefan
Olli
Beiträge: 70
Registriert: 12. Aug 2014, 20:52
Wohnort: Moormerland / Ostfriesland

Re: eigenen EEPROM Bereich im LPC11xx anlegen

Beitrag von Olli »

Hallo,

ich habe das Problem mit den überschriebenen Speicherstellen bis heute gehabt.
Nun möchte ich meine Problemlösung hier bereitstellen, sodass vielleicht andere mit dem gleichen Problem in der Zukunft es einfacher haben :-)

Ich habe glücklicherweise ein GLCD an dem Controller, der mittels u8glib angesteuert wird. Somit konnte ich diese Veränderung der Speicherstellen bemerken. Ohne dieses hätte ich mir in Zukunft sicherlich einen Wolf nach unerklärlichen Aussetzern gesucht...

Nun zu meinem Problem:
Es wurde immer eine bestimmte Speicherzelle mit dem Aufruf von memMapper.doFlash(); überschrieben. Diese war glücklicherweise eine, die einen Schriftdatensatz für das GLCD beinhaltet.
Somit hatte ich nach dem Speichern immer eine nicht mehr lesbare Schrift auf dem GLCD.
Das Problem war, dass ich diesen Controller bereits zur Entwicklung einiger Softwaren verwendet hatte und somit auch bereits sehr viel im Speicher herumgeschrieben wurde.

Der memMapper funktioniert so, dass er aus dem zugewiesenen Speicherbereich (hier von Florian 0xEA00) die allocationtable sich herausholt und verwendet, solange die Inhalte nicht 0xFF sind. Da in diesen Speicherzellen bei meinem Controller von vorher bereits etwas drin stand (ungleich 0xFF), wurde diese dort angegebene Adresse verwendet. Und diese Adresse war nun zufällig die, wo der Schriftsatz der u8glib abgelegt wurde.

Lösung:
Es gibt im LPCXpresso die Funktion "Program Flash" (IC als Symbol), mit der man den gesamten Speicher wieder löschen kann. Nach der Ausführung dieser Funktion funktioniert auch der memMapper wie gewünscht.

Auch für das Problem der vom Linker beschriebenen Speicherstellen gibt es eine einfache
Lösung:
In den Projekteinstellungen stellt man für den Controller den Flash Speicherbereich nur bis zum Beginn des memMapper Speicherbereichs ein. Dahinter sollte dann ja sowieso nur noch der Speicherbereich des userEeproms der sblib liegen.
Somit kommt der Linker nicht auf die Idee etwas in den memMapper oder userEeprom Bereich zu legen.
Man kommt wie folgt zu den Einstellungen: Projekt anwählen->Project->Properties->C/C++ Build->MCU Settings->Edit unter Memory details
In der Spalte Flash die Size auf den Anfang des memMappers legen (hier 0xEA00)
Somit ist nur der Bereich vor dieser Adresse für den Linker verfügbar.

Grüße,
Olli
Florian
Beiträge: 161
Registriert: 8. Aug 2015, 23:25
Wohnort: Paderborn

Re: eigenen EEPROM Bereich im LPC11xx anlegen

Beitrag von Florian »

Ahhh, da kann man die Speichergröße einstellen. Dann muss ich demnächst nicht mehr immer im Mapping-File suchen, vielen Dank!
Klamm
Beiträge: 82
Registriert: 19. Jul 2013, 11:30

Re: eigenen EEPROM Bereich im LPC11xx anlegen

Beitrag von Klamm »

Morgen!
Ich möchte für das Info Display Projekt auch den memMapper nutzen und habe da noch ein Problem.

So versuche ich es aktuell zu nutzen:

MemMapper memMapper(0x8000,0x8000);

void setup() {
memMapper.addRange(0x0,0x8000);

test1=memMapper.getUInt8(0x10);

memMapper.setUInt8(0x0,0x38);
memMapper.setUInt8(0x10,0x38);

test2=memMapper.getUInt8(0x10);
memMapper.doFlash();
}

Die Werte werden in den Speicher des Controllers geschrieben und sind auch nach einem Neustart immer noch an der richtigen Stelle vorhanden, jedoch ist alles wieder leer sobald die Funktion addRange ausgeführt wird.
Wie kann ich das denn verhindern? addRange wird ja immer wieder ausgeführt, wenn der Controller neu startet.

Ich brauche den Speicherbereich vom Controller, da dieser von ETS über den Bus beschrieben werden soll. Da wäre es natürlich nicht gut wenn das Programm nach jedem Neustart des Controllers wieder weg ist.

Hat jemand dafür eine Lösung oder eine Idee?
Florian
Beiträge: 161
Registriert: 8. Aug 2015, 23:25
Wohnort: Paderborn

Re: eigenen EEPROM Bereich im LPC11xx anlegen

Beitrag von Florian »

Also... wenn ich den MemMapper richtig verstehe, dann ist der Speicherbereich, den du anzulegen versuchst, zu groß. Du legst den MemMapper mit 0x8000 Bytes Größe im Flash an. Von dem Speicherbereich benötigt der MemMapper 256 Bytes, also ein Seite, für das Abspeichern der allocTable. Also wäre der größte Range, den zu anlegen kannst, 0x7f00.
Bitte überprüfe doch mal die Fehlercodes, die die MemMapper-Funktionen zurückliefern. Wenn meine Vermutung richtig ist, dann müsste addRAnge() MEM_MAPPER_OUT_OF_MEMORY zurückgeben.
Als Resultat wird die geänderte allocTable nie im Flash gespeichert, bleibt also volatil. Beim nächsten Start findet der MemMapper deinen angelegten Range nicht im Flash und betrachtet ihn als vollkommen neu.
Antworten