Hallo,
gibt es da Zauberworte, welche dem Compiler zur Laufzeit oder
Übersetzungszeit die Start und Enadresse des .bss Section mitteilt?
Ich brauche die, da ich zur Laufzeit eine Kopie im EEProm speichere, die
nach Reset wieder eine identische Umgebung erzeugt. Da meine
Kopierroutine variablenmässig aus dem Stack heraus arbeitet dürfte kein
Absturz erfolgen.
Gruss,
Christian
externchar__bss_start[];// Defined in linker script.
6
return(uintptr_t)__bss_start;
7
}
Dito für __bss_end.
Allerdings ist der Ansatz nicht wirklich empfehlenswert: Falls der
Inhalt von (statischen) Konstruktoren gesetzt wird, funktioniert das
nicht mehr.
Stattdessen kann man die Daten als Struktur bzw. POD modellieren und von
diesem 2 Instanzen halten, eine im RAM und eine im EEPROM. Bei Bedarf
werden die dann mit eeprom_read_block bzw. eeprom_update_block kopiert.
Auch hier müssen die Daten POD sein.
Das hab ich in Projekten, wo Konfiguration nach (Powerdown) Reset
erhalten bleiben soll, aber nie war dazu nötig den ganzen RAM zu
speichern.
AUßerdem ist zu bedenken was mit .data und .rodata passieren soll.
Danke erstmal. Ist ein reines C Programm ohne Cpp Anteile, ausser in den
verwendeten Libs. Moeglich waere noch eine Zusammengassung aller
Variablen in einem Struct, da ich nur globale Zaehler etc sichern will
und das moeglichst nicht alle einzeln.
Die einzelnen frei flottierenden Variablen werden zu einem Strukt
zusammengefasst, in welchem sie als Komponenten auftreten. Der Struct
kann als ganzes gelesen, gespeichert, kopiert etc. werden. Die
Möglichkeit Komponenten einzeln zuzugreifen besteht natürlich, ist aber
nicht zwingend.
Ardiuno kenne ich nicht, ist meines wissens aber C++. Und selbst in C
kann man Konstruktoren haben — zumindest in GNU-C. Wenn solche in den
Libs Verwendung finden dann hast du prinzipiell dieses Problem.
Der saubere Weg wäre aber schon, die Variablen einzeln ins EEPROM zu
kopieren, und auch wieder zu holen. Wenn’s unbedingt zusammengefasst
passieren soll, dann pack die halt alle zusammen in einen struct.
Oliver
Falk B. schrieb:> Warum sollte man ein Problem mit Hackertricks lösen, wenn man es auch> problemlos lehrbuchartig machen kann?
Und was sagt das Lehrbuch? Auch ein Windows PC macht beim Ruhezustand
ein Image und zieht sich das stur wieder rein beim Aufwecken.
Alle Vars in struct sind einfach, zerreissen mir aber das Programm, da
ich diverse structs habe wo alles zusammen gefasst ist, was da rein
gehört. Lieber wäre mir den ganzen Bereich einfach rein zu holen und da
die laufvars etc auf dem Stack liegen passiert da auch nix.
Johann L. schrieb:> Stattdessen kann man die Daten als Struktur bzw. POD modellieren und von> diesem 2 Instanzen halten, eine im RAM und eine im EEPROM.
Ich verstehe von C++ leider nichts, will das aber noch ändern.
Wie erzeugt man denn so tolle Sachen wie EEPROM[Adresse] = .... ? Das
geht nämlich beim Arduino und dahinter verbirgt sich dann der
Schreibvorgang. Das EE wird aber wie ein Array angesprochen. Ich bin ja
schon voll begeistert von den Stream Klassen, alles mit << und schon
flutscht es rein in die Ausgabe.
Christian J. schrieb:> Falk B. schrieb:>> Warum sollte man ein Problem mit Hackertricks lösen, wenn man es auch>> problemlos lehrbuchartig machen kann?>> Und was sagt das Lehrbuch? Auch ein Windows PC macht beim Ruhezustand> ein Image und zieht sich das stur wieder rein beim Aufwecken.
Wollen wir wetten, daß es auch da DEUTLICH geordneter zugeht, als du es
dir ausmalst?
> Alle Vars in struct sind einfach, zerreissen mir aber das Programm,
Nö, denn dann ist deine Datenorganistation nicht sinnvoll.
Wenn ich schon spezielle Daten habe, welche eben derartig im EEPROM
gesichert werden sollen, dann faßt man die sinnvollerweise zusammen und
verteilt sie NICHT über sonst wie viele Objekte.
> da> ich diverse structs habe wo alles zusammen gefasst ist, was da rein> gehört. Lieber wäre mir den ganzen Bereich einfach rein zu holen und da> die laufvars etc auf dem Stack liegen passiert da auch nix.
Schuster bleib bei deinen Leisten. Einem Compiler so auszutricksen ist
selten eine gute Idee. Erst recht, wenn man einen Tunnelblick hat und zu
faul ist, sein Problem durch passende Umstrukturierung der Daten zu
lösen.
Falk B. schrieb:> Schuster bleib bei deinen Leisten. Einem Compiler so auszutricksen ist> selten eine gute Idee.
Klappt bei meinem Z80 Bauwerk auch :-) Boot Loader Kopiert sich aus
EPROM ins Higher RAM, schaltet untere Bank von EPROM auf RAM um und
zieht sich dann den Hex Code von der Uart rein und startet ihn
anschließend. Und das alles in C mit dem SDCC. RAM ist allerdings ein
Uhren RAM mit interner Batterie, da bleibt eh alles erhalten.
Gehen tut alles... aber ich denke drüber nach wie ich das mit
Bordmitteln lösen kann.
PS: Mein PC schaltet die Monitore nicht mehr ein beim Aufwecken :-(
Was hast du denn alles an Anwendungs-Status, der so behalten werden
muss? Soll das Display genau im selben Untermenü wie vorher sein, genau
in der Mitte der Animation wie vorher? Extern anzusprechende Komponenten
bleiben auch garantiert in ihrem Zustand und müssen nie neu
initialisiert werden?
Bei den meisten Embedded-Geräten ist der Zustand so flüchtig, dass man
bei einem Neustart sowieso alles neu initialisieren muss. Nur ein paar
Grundeinstellungen/Parameter müssen behalten werden, was man problemlos
mit einem struct machen kann.
Christian J. schrieb:> Wie erzeugt man denn so tolle Sachen wie EEPROM[Adresse] = .... ?
Überladung des []-Operators und des = Operators. Ist im Endeffekt auch
nur ein Funktionsaufruf (ggf. mit ein paar Hilfsfunktionen).
Johann L. schrieb:> #include <stdint.h>>> uintptr_t get_bss_start (void)> {> extern char __bss_start[]; // Defined in linker script.> return (uintptr_t) __bss_start;> }> Dito für __bss_end.>> Allerdings ist der Ansatz nicht wirklich empfehlenswert: Falls der> Inhalt von (statischen) Konstruktoren gesetzt wird, funktioniert das> nicht mehr.
Warum eigentlich nicht?
Wenn man alles zwischen __data_start und __heap_start kopiert, sollte
man doch eigentlich wirklich alles erwischen.
Oliver
Dr. Sommer schrieb:> Überladung des []-Operators und des = Operators. Ist im Endeffekt auch> nur ein Funktionsaufruf (ggf. mit ein paar Hilfsfunktionen).
Nur ein Bastelgerät, was Bewegung, Temperaturen, Uhrzeit, Datum usw.
aufzeichnet. Bisher lese ich alles manuell zurück aber wie schön
einfacher wäre es doch wenn alles was geht auf einmal wieder da wäre,
alle Zeiger auf Arrays usw. Die DS3231 usw. werden ja per Hand
initialisiert. Es ist nur Spielerei, weil ich leidenschaftlich gern
programmiere und Problemchen löse.
Ich werde das mit dem Code oben mal ausprobieren. Sehe es dann ja ob es
klappt.
Oliver S. schrieb:> Wenn man alles zwischen __data_start und __heap_start kopiert, sollte> man doch eigentlich wirklich alles erwischen.
Leider nein!
Es fehlt eben der Heap.
Und ja, teilweise wird Speicher reserviert.
z.B. die SD Klassen tun das
Auch geht dir der Stack durch die Lappen.
Sowie alle Register. Ja, der Optimierer sorgt dafür, dass möglichst
viele Daten in den Registern gehalten werden.
Ebenso sind die akuten Daten in externer Hardware dem Verlust preis
gegeben.
Christian J. schrieb:> weil ich leidenschaftlich gern> programmiere und Problemchen löse.
Ich vermute, so machst du dir eher welche...
;-)
Christian J. schrieb:> Wie erzeugt man denn so tolle Sachen wie EEPROM[Adresse] = .... ? Das> geht nämlich beim Arduino und dahinter verbirgt sich dann der> Schreibvorgang. Das EE wird aber wie ein Array angesprochen. Ich bin ja> schon voll begeistert von den Stream Klassen, alles mit << und schon> flutscht es rein in die Ausgabe.
Ja, das lohnt sich anzusehen!
Ein ganzer Eimer von Operatoren wird da überladen.
Viel interessanter/universeller, als das Array Access Interface, sind
die get() und put() Methoden.
Lesenswert:
https://github.com/arduino/ArduinoCore-avr/blob/master/libraries/EEPROM/src/EEPROM.h
Arduino Fanboy D. schrieb:> Leider nein!>> Es fehlt eben der Heap.
Dann halt bis heap-end, wobei das dann wiederum noch andere Maßnahmen
nach sich ziehen dürfte, um den wieder aus der Kopie wieder
herzustellen. Das ganze Konzept ist eh Murks, und hat natürlich seine
Grenzen.
Aber hier gehts letztendlich um ein paar globale Zähler. Die landen
nicht auf den heap.
Oliver
Arduino Fanboy D. schrieb:
Moin,
da Du dich ja sehr gut mit C++ auskennst und ich langsam Gefallen an
einigen nützlichen Dingen finde nochmal ne Frage. Ich kriege das allein
noch nicht hin.
Ich habe für den TSOP eine prima Übertragung zum PC hin. Bastelei sendet
mit einer IR Diode und es schnurrt aufs Terminal. Wahlweise IR oder eben
auf die UART. Mit Streaming.h und << klappt das gut. 8N1 Protokoll.
Parity ginge aber auch.
Diese Sache möchte ich nun auch für den Empfang einsetzen:
IR-Diode >..... durch die Luft.....> TSOP -> Arduino rein. Und der Ardu
decodiert das möglichst über eine Uart, entweder die RX0/TX0 oder eine
Softserial, die aber auch INT gesteuert einen Buffer füllt, so dass ich
etwas Zeit habe zu reagieren.
Wie sähe ein C++ Konstrukt aus, dass mir genau das macht?
Irgendwie etwas mit IRQuelle >> myVariable und einige Funktionen
drumherum die den Umgang damit einfach machen?
struct IrSend_t: Print {
virtual size_t write(uint8_t value) {
SendIRByte(value);
//Serial.write(value);
return 1;
}
};
Meinen Dank, für die Blumen.
Aber da hast du dir schon was vorgenommen......
Christian J. schrieb:> Wie sähe ein C++ Konstrukt aus, dass mir genau das macht?
Unschön!
Eine ISR in einer Klasse unter zu bringen, ist nicht ganz trivial.
Auch darf man diese dann nur statisch nutzen, also nicht instanziieren,
oder alternativ, sollte man sie zu einem Singleton machen, damit nix
anbrennen kann.
Also alles in allem, gibt es zwar klare und saubere Lösungen, diese sind
allerdings nicht "schön".
Das Singelton Design Pattern findest du z.B. bei Wikipedia beschrieben.
Wie man ISR in Klassen stopft, findest du hier:
https://www.mikrocontroller.net/articles/AVR_Interrupt_Routinen_mit_C%2B%2B