Forum: Compiler & IDEs Variable in .noinit scheint Initialisiert zu werden


von Malte _. (malte) Benutzerseite


Lesenswert?

Hallo,
Ich möchte dass eine Variable während eines Watchdog Resets (ATMega8)
erhalten bleibt und habe daher die Variable in die Sektion .noinit
getan:
1
u08 volatile baudval __attribute__((section(".noinit")));
Die Variable wird also nur initialisiert wenn der Reset nicht durch den
Watchdog erfolgt:
1
if (MCUCSR != (1<<WDRF)) {  //Wenn kein Watchdog reset
2
  baudval = baud9600val;
3
}
Direkt nach dem Code gebe ich die Variable aus. Nach einem Power-On
steht in der Variable der gewünscht Wert, nach einem Watchdog Reset
jedoch immer 0. Testeshalber habe ich direkt vor der Watchdog
Aktivierung die Variable mal auf einen Wert gesetzt und bin dann in
eine Endlosschleife gegangen:
1
baudval = 42;
2
wdt_enable(WDTO_15MS);
3
_delay_ms(200.0);
Die Variable ist jedoch nach dem Reset weiterhin Null.

Kann mir jemand sagen wo die Ursache dafür liegt?

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Dein Test ist flasch.  Die Flags in MCU[C]SR akkumulieren, d. h.
wenn du das PORF nicht löschst, ist es zusammen mit dem WDRF nach
dem nächsten watchdog reset gemeinsam dort vorhanden.  Damit
schlägt dein purer Test auf Ungleichheit aber fehl, und du
initialisierst deine Variable trotzdem.

Bei Prozessoren mit dem neuen AVR-Watchdog musst du sowieso
vorsichtig sein: dort kann man den Watchdog, wenn er einmal
zugeschlagen hat, nicht so einfach wieder loswerden, der triggert
sonst immer wieder neu.  Daher empfiehlt es sich, den Wachhund
möglichst frühzeitig (am besten in .init3) außer Betrieb zu nehmen
und dort den Reset-Status zu retten.  Das habe ich in der avr-libc-
Doku beispielhaft beschrieben (im Kapitel zu <avr/wdt.h>).

von Malte _. (malte) Benutzerseite


Lesenswert?

Ok, ich hätte wohl einen etwas größeren Auschnitt aus meinem Quellcode
posten sollen:
1
if (MCUCSR != (1<<WDRF)) {  //Wenn kein Watchdog reset
2
  baudval = baud9600val;
3
}
4
MCUCSR = 0;
5
[0]
6
und
7
[c]
8
#define F_CPU 11059200
9
#define baud9600val (F_CPU/(9600*16l)-1)
Der Test funktioniert auch, nach dem power-on ist der Wert wie erwartet
71. Nach dem Watchdog-Reset ist der Wert 0, müsste aber 42 sein.

Dass der Watchdog nach einem Reset bei den neueren Modellen nicht
automatisch deativiert wird, ist gut zu wissen. Scheint aber bei dem
ATMEGA8 nicht der Fall zu sein.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Simulierst du, oder hast du richtiges Silizium?

Ich frage nur, weil ich gerade eine ähnliche Anfrage in
avrfreaks.net gelesen habe, und diese sich auf den Simulator
von AVR Studio bezog...  Manche Details bekommt er wohl nicht
so recht hin.

Mein persönliches Testprogramm für die avr-libc, das ich nach
der Portierung auf jeden neuen AVR loslasse, testet jedenfalls
das WDRF, und das hat bislang immer funktioniert.  Auch die
.noinit-Variablen funktionieren sehr wohl (ist auch recht gut
durchschaubar, wenn man das Prinzip verstanden hat).

von Malte _. (malte) Benutzerseite


Lesenswert?

Richtiges Silizium :-) Das AvrStudio4 geht nicht mit WINE.
Aber da ist mir gerade was aufgefallen... ich hab ja nen Bootloader (
http://www.mikrocontroller.net/forum/read-4-53146.html ) mit auf dem
Chip und bei einem Reset geht der ja erstmal los... ich vermute der
setzt die 0 in die Speicherzelle.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Am besten im Bootloader nur .noinit-Variablen benutzen oder
einen separat zugewiesenen Teil des RAMs.  Dann kann der
natürlich auch das MCU[C]SR auslesen und an eine vereinbarte
Stelle speichern.

von m4444x (Gast)


Lesenswert?

Dazu hätt ich auch eine kleine Frage:

Mein Bootloader verwendet nur .noinit-Variablen und keine Interrupts.
Gibt's irgendeinen trick wie ich dem gcc sagen kann das er sich die
vector tabelle und die .data/.bss intialisierung schenken kann? Das
sind zusammen immerhin 100 Bytes...

von Malte _. (malte) Benutzerseite


Lesenswert?

Zur Vektortabelle gibts ne Compiler Option:
http://gcc.gnu.org/onlinedocs/gcc-4.1.1/gcc/AVR-Options.html#AVR-Options

Bei dem Rest kenn ich mich nicht aus. Das schreiben eines eigenen
Bootloaders steht noch an.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

> Zur Vektortabelle gibts ne Compiler Option:

Nö, leider nicht.  -mno-interrupts bewirkt nur, dass bei
Manipulieren des Stackpointers die Interrupts nicht gesperrt
werden.  Die Vektortabelle selbst stammt aus dem gcrt1.S und
ist derzeit nicht optional.  Wenn man sie weglassen will, müsste
man eine eigene modifizierte Kopie dieser Datei für den
Bootloader nehmen.

Theoretisch sollte das Initialisieren von .data und .bss ja mal
optional sein können, aber derzeit fehlt der Code für die
entsprechende Analyse im GCC, daher generiert er immer Referenzen
zu den Symbolen für diese Routinen.  Kann man sich im generierten
Assemblercode (nicht im Disassembler!) gut ansehen und könnte
man genau dort auch manipulieren: wenn man die dort rausstreicht,
hat der Linker keinen Grund mehr, die entsprechenden Funktionen
aus der Bibliothek dazuzulinken.

Allerdings haben solche Verrenkungen natürlich nur Sinn, wenn man
dadurch auch auf die nächstkleinere bootloader section gehen
kann.  Ansonsten bekommt man für nicht genutzten Flash kein Geld
zurück. ;-)

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.