Forum: Compiler & IDEs RAM-Initialisierung beim Hochlauf unterdrücken


von Christian Zapomel (Gast)


Lesenswert?

Hallo allerseits!

Zunächst das allgemeine:      Prozessor: AVR Mega168
                              Compiler:  GNU C-Compiler

Ich habe folgendes Problem:
Ich möchte beim Hochlauf die Initialisierung des RAM-Bereiches
UNTERDRÜCKEN.

Grund:
Die Schaltung läuft im Batteriebetrieb. Darum möchte ich
den Controller nach Ausführung eines Programmes "Schlafen legen"
(mittels SLEEP-Befehl) um wenig Strom zu verbrauchen,und diesen
dann durch einen Watchdog-interrupt wieder aufwecken.
Die RAM-Variablen sollten somit nach neuerlichem Anlauf erhalten
bleiben.

Ich nehme an, dass es dafür sicherlich einen Compilerswitch für das
MAKE-File gibt. Vielleicht hat das schon jemand einmal probiert?

Anbei der Code, der das RAM beim Anlauf mit 0x00 initialisiert
(habe ich mit dem AVR-Studio im Singlestep herausgefunden):
+0000006D:   921D        ST      X+,R1            Store indirect and
postincrement
+0000006E:   3AA9        CPI     R26,0xA9         Compare with
immediate
+0000006F:   07B1        CPC     R27,R17          Compare with carry
+00000070:   F7E1        BRNE    PC-0x03          Branch if not equal


Vielen Dank im Voraus für eventuelle Tipps und Lösungsvorschläge!

Viele Grüße,
Christian

von mthomas (Gast)


Lesenswert?

Lt. Linker-Script werden data und BSS in der section .init4
inititialisiert. Mglw. funktioniert es, eine Funktion in .init3
(attribute section...) anzulegen, und von dort aus direkt main()
aufzugerufen. Ist nicht "elegant" und hat sicher einige
Seiteneffekte, aber vielleicht ein Ansatz.
Ausserdem waere es einen Versuch wert, die nicht-zu-initialisierenden
Daten in der Section .noinit anzulegen. Wenn es funktioniert, ist dies
im Vergleich zum Vorschlag oben die bessere Loesung. Falls Resetquelle
"echter Reset/Power-On-Reset": nicht vergessen "von Hand" zu
initialisieren.

Martin

von Peter Fleury (Gast)


Lesenswert?

Es genügt die Variablen .noinit zu deklarieren:

z.B.
 static uint16_t count __attribute__((section(".noinit")));

von Christian Zapomel (Gast)


Lesenswert?

Hallo Peter, Hallo Martin!

Vielen Dank für die schnellen Antworten. Die Lösung mit

"static uint8_t ucTest __attribute__((section(".noinit")));"

funktioniert. Der RAM-Inhalt bleibt nach dem Watchdog-RESET erhalten!

Für die Erst-Initialisierung habe ich mir ein Flag angelegt, das
beim Programmstart auf einen bestimmten Wert abgefragt wird. Damit
ist die Erst-Initialisierung auch gesichert.

viele Grüße, Christian

von Florian (Gast)


Lesenswert?

Hallo Christian,

aus einer Variable einen Reset zu erkennen halte ich für gefährlich.
Denn beim einschalten könnte diese Speicherstelle ja zufällig den Wert
haben, denn du abfrägst und es passiert dann keinen Initialisierung
mehr. Sicherer währe es wenn du die Prozessorinternen Register
abfrägst. Da gibt es eins MC??? aus dem man die Quelle vom letzten
Reset auslesen kann.

Gruß, Florian

von Christian Zapomel (Gast)


Lesenswert?

Hallo Florian!

Danke für den Tipp! Diese Neustartquelle kann man aus dem register
"MCUSR" auslesen! So werd ich es eh machen!
Am besten ists, wenn man den Hochstartgrund und dann
noch ein 16-bit-value abfragt. Dann könnte (fast) nichts
mehr schief gehen!

(Anbei der Code, wie man den Neustart-Grund abfragen kann)

viele Grüße, Christian


//hochstartgrund am programmbegin per MCUSR-register abfragen:
if (MCUSR & BV(WDRF))
  {
    //grund: watchdog-reset
  }
if (MCUSR & BV(PORF))
  {
    //grund: power-on-reset
  }
if (MCUSR & BV(EXTRF)
  {
    //grund: external reset
  }
if (MCUSR & BV(BORF)
  {
    //grund: brown-out reset
  }

von Jörg Wunsch (Gast)


Lesenswert?

> (Anbei der Code, wie man den Neustart-Grund abfragen kann)

Nicht völlig OK.  Du solltest als allererstes (vielleicht sogar in
einer .initX-section) den Inhalt von MCUSR in eine Variable übernehmen
und dieses Register danach ausnullen.  Andernfalls akkumulieren die
einzelnen Bits und du hättest plötzlich ,,mehrere Reset-Gründe''. :)
Als allererstes deshalb, weil der Zeitraum bis zum Löschen des
MCU[C]SR natürlich eine race condition darstellt.  Tritt innerhalb
dieser Zeit ein neuer Rest auf, hast du wirklich zwei Gründe für
Reset.

von Christian Zapomel (Gast)


Lesenswert?

Hallo Jörg!

Du hast recht. Wenn man das Register beim Hochlauf in eine
Variable speichert ist es auf jeden Fall sicherer! Werde das
Programm diesbezüglich umbauen.

Vielen Dank!
Gruß,Christian

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
Noch kein Account? Hier anmelden.