Forum: Mikrocontroller und Digitale Elektronik AVR: .init nach reset überspringen


von Klemens (Gast)


Lesenswert?

Hallo an Alle,

nach einem Reset soll meine Software nach der Reset-Ursache schauen 
(watchdog, brown-out, extern oder powerup) und je nach Ursache z.B. die 
section init_4 überspringen. Nur bei Powerup und brown-out sollen die 
Variablen neu initialisiert werden.

Wer weiß Rat?

Klemens

von Klemens (Gast)


Lesenswert?

Ich hab es dann doch hinbekommen:

die Konstruktion hinter dem "goto" ist ja schon "kniffelig" :-)
1
void __attribute__ ((naked, section (".init_3")))  _my_init_3 ( void );
2
void __attribute__ ((naked, section (".init_5")))  _my_init_5 ( void );
3
4
void _my_init_3 ( void )
5
{
6
   if ( MCUSR & ( (1<<WDRF) + (1<<EXTRF) ) )
7
      goto *((void **)) _my_init5);
8
}
9
10
.init4    <hier werden die Variablen vom Flash in Ram kopiert>
11
12
void _my_init_5 ( void )
13
{
14
   <hier geht es mit meinem Code weiter>
15
}

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


Lesenswert?

Du hättest lieber die entsprechenden Variablen in die section
".noinit" legen und diese dann beim Power-On-Reset manuell
initialisieren sollen.

Dein Code hat übrigens noch einen grundlegenden Fehler: MCUSR wird
nicht wieder gelöscht.  Damit würde nach einem vorangegangenen
Extern-Reset und jetzt neu hinzugekommenen Brown-Out-Reset (nach
dem ja die RAM-Daten nicht mehr verlässlich sind) die Initialisierung
beispielsweise trotzdem noch übersprungen.  Noch schlimmer: beim
"neuen" Watchdog (der, der auch im Interrupt-Modus arbeiten kann)
lässt sich der Watchdog anschließend nicht mehr deaktivieren und
schlägt aller 15 ms immer wieder zu.

von Klemens (Gast)


Lesenswert?

Beim regulären Einschalten sollen ja alle Variablen initialisiert 
werden. Bei Watchdog oder externen Reset will ich die Variablen auslesen 
können.

Na gut - viele Wege führen nach Rom. ich wollte es halt so lösen.

Klemens

von Klemens (Gast)


Lesenswert?

Jörg Wunsch schrieb:

> MCUSR wird nicht wieder gelöscht. [...]
> lässt sich der Watchdog anschließend nicht mehr deaktivieren und
> schlägt aller 15 ms immer wieder zu.

Okay, das ändere ich noch. :-)

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Es genügt folgendes:
1
#include <avr/io.h>
2
3
uint8_t mcusr __attribute__((section (".noinit")));
4
5
static void __attribute__((section(".init3"),naked,used))
6
init3 (void)
7
{
8
    mcusr = MCUSR;
9
    MCUSR = 0;
10
}

mcusr kann dann zB in main ausgewertet werden. Beachte daß die Section 
nicht .init_3 heißt sondern .init3

von Klemens (Gast)


Lesenswert?

Die .init4 wird ja vom Linker eingefügt. Mein Problem war, die .init4 
bei bestimmten Bedingungen zu überspringen.

von Hagen R. (hagen)


Lesenswert?

Klemens schrieb:
> Die .init4 wird ja vom Linker eingefügt. Mein Problem war, die .init4
> bei bestimmten Bedingungen zu überspringen.

...um die Vorinitialisierung bestimmter globaler Variablen durch den 
Compiler zu unterdrücken. Und dafür hättest du auch alle betroffenen 
Variablen einfach als .noinit deklarieren können statt am Init-Code zu 
doktorn. In deiner Main() dann diese Variablen abhängig vom Startup der 
MCU von Hand initialisieren.

Gruß hagen

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


Lesenswert?

Hagen Re schrieb:
> In deiner Main() dann diese Variablen abhängig vom Startup der
> MCU von Hand initialisieren.

Geht übrigens gut zu automatisieren, indem man alle diese Daten in
eine einzige .noinit-Struktur packt und dann eine entsprechende
Initialwerte-Struktur in den Progmem legt, aus der die Daten bei
der passenden Kombination von Reset-Flags geladen werden.

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.