www.mikrocontroller.net

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


Autor: Christian Zapomel (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: mthomas (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Peter Fleury (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Es genügt die Variablen .noinit zu deklarieren:

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

Autor: Christian Zapomel (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Florian (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Christian Zapomel (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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
  }

Autor: Jörg Wunsch (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Christian Zapomel (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.