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
1 | #include <stdint.h> |
2 | |
3 | uintptr_t get_bss_start (void) |
4 | {
|
5 | extern char __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.
:
Bearbeitet durch User
Warum sollte man ein Problem mit Hackertricks lösen, wenn man es auch problemlos lehrbuchartig machen kann? KISS!
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
:
Bearbeitet durch User
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
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.