Herakles
Profifragensteller
Moin!
Ich entwickle gerade eine Steuerung, die beim Abschalten in einen Flash-Speicher schreiben soll, damit "alte" genutzte Daten weiterverwandt werden können, wenn die Steuerung wieder eingeschaltet wird. Um das zu machen, muss erkannt werden, dass ein Spannungsausfall auftrat (per Schalter oder weil eben Stromausfall ist) und über einen Kondensator kurz eine Spannung aufrecht erhalten werden, damit der Speicher weggeschrieben werden kann.
Das funktioniert prächtig, über eine ISR fange ich diesen Fall ab und reagiere dann entsprechend: Ich setze eine Semaphore, die im Hauptprogramm (eine endlose Schleife) abgefragt wird und sollte sie gesetzt sein, schreibe ich den Speicher weg und beim Einschalten ist dieser Speicher dann wieder auslesbar. Wichtige Informationen werden so über einen Spannungsausfall hinaus behalten.
Realisiert habe ich das, indem ich nach einem bemerkten "raisen" der Semaphore eine eigene Funktion aufrufe, die den Speicher wegschreibt. Drumherum werden aber auch noch Tasks gekillt, insgesamt sind das 5 Aufrufe:
Der Fachmann erkennt: FreeRTOS.
Wichtig zu erwähnen: Der genutzte Kondensator hält die Spannung nur für den Bruchteil einer Sekunde (~10ms), das "Speicherwegschreiben" ist also extrem zeitkritisch.
Naja, wie auch immer. So funktioniert das alles sehr schön. Nun will ich das aber nicht nur im Fall des Spannungsausfalls machen, sondern auch, wenn zum Beispiel die Steuerung in einen "Stop" geht oder wenn sie einen Fehler bemerkt. Um also Codedopplungen zu vermeiden, habe ich den oben genannten Code-Teil in eine Funktion gegossen und muss nun nur noch die Funktion aufrufen.
Effekt: Funktioniert nicht. NUR, wenn ich die obigen Aufrufe an die jeweiligen Stellen schreibe, habe ich eine gesicherte Funktion. Wenn ich das über einen Funktionsaufruf mache (wie gesagt: ich will keine Codedopplungen), klappt das nicht beim Spannungsausfall.
Mein aktueller Workaround ist ein #define:
Wenn ich das an den entsprechenden Stelle aufrufe, klappt's!
Sooo, lange erklärt und nun meine eigentliche Frage: Was ist der Grund dafür, dass das, was ich hier beschrieben habe, mit einem Funktionsaufruf nicht klappt, mit einem "#define" oder direkt an Ort und Stelle geschriebenem Code (was meinem Verständnis zufolge ja dasselbe ist wie mit einem #define) aber sehr wohl funktioniert?
Viele Grüße vom berufsbedingten Kopfqualmer
Herakles
Ich entwickle gerade eine Steuerung, die beim Abschalten in einen Flash-Speicher schreiben soll, damit "alte" genutzte Daten weiterverwandt werden können, wenn die Steuerung wieder eingeschaltet wird. Um das zu machen, muss erkannt werden, dass ein Spannungsausfall auftrat (per Schalter oder weil eben Stromausfall ist) und über einen Kondensator kurz eine Spannung aufrecht erhalten werden, damit der Speicher weggeschrieben werden kann.
Das funktioniert prächtig, über eine ISR fange ich diesen Fall ab und reagiere dann entsprechend: Ich setze eine Semaphore, die im Hauptprogramm (eine endlose Schleife) abgefragt wird und sollte sie gesetzt sein, schreibe ich den Speicher weg und beim Einschalten ist dieser Speicher dann wieder auslesbar. Wichtige Informationen werden so über einen Spannungsausfall hinaus behalten.
Realisiert habe ich das, indem ich nach einem bemerkten "raisen" der Semaphore eine eigene Funktion aufrufe, die den Speicher wegschreibt. Drumherum werden aber auch noch Tasks gekillt, insgesamt sind das 5 Aufrufe:
Code:
vTaskDelete( globals.pcb_com_task_handle ); \
vTaskDelete( globals.lwip_task_handle ); \
vTaskDelete( globals.i2c_task_handle ); \
write_remanent_RAM_to_FLASH_on_shutdown( remanent_memory_RAM ); \
vTaskDelete( NULL );
Der Fachmann erkennt: FreeRTOS.

Wichtig zu erwähnen: Der genutzte Kondensator hält die Spannung nur für den Bruchteil einer Sekunde (~10ms), das "Speicherwegschreiben" ist also extrem zeitkritisch.
Naja, wie auch immer. So funktioniert das alles sehr schön. Nun will ich das aber nicht nur im Fall des Spannungsausfalls machen, sondern auch, wenn zum Beispiel die Steuerung in einen "Stop" geht oder wenn sie einen Fehler bemerkt. Um also Codedopplungen zu vermeiden, habe ich den oben genannten Code-Teil in eine Funktion gegossen und muss nun nur noch die Funktion aufrufen.
Effekt: Funktioniert nicht. NUR, wenn ich die obigen Aufrufe an die jeweiligen Stellen schreibe, habe ich eine gesicherte Funktion. Wenn ich das über einen Funktionsaufruf mache (wie gesagt: ich will keine Codedopplungen), klappt das nicht beim Spannungsausfall.
Mein aktueller Workaround ist ein #define:
Code:
#define TURN_OFF_ALL_TASKS_AND_WRITE_TO_REMANENT \
vTaskDelete( globals.pcb_com_task_handle ); \
vTaskDelete( globals.lwip_task_handle ); \
vTaskDelete( globals.i2c_task_handle ); \
write_remanent_RAM_to_FLASH_on_shutdown( remanent_memory_RAM ); \
vTaskDelete( NULL );
Wenn ich das an den entsprechenden Stelle aufrufe, klappt's!
Sooo, lange erklärt und nun meine eigentliche Frage: Was ist der Grund dafür, dass das, was ich hier beschrieben habe, mit einem Funktionsaufruf nicht klappt, mit einem "#define" oder direkt an Ort und Stelle geschriebenem Code (was meinem Verständnis zufolge ja dasselbe ist wie mit einem #define) aber sehr wohl funktioniert?
Viele Grüße vom berufsbedingten Kopfqualmer
Herakles