AVR: .init nach reset überspringen

Gast #2749367
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
Gast #2749642
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
}
Moderator Persönliche Seite #2749650
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.
Gast #2749664
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
Persönliche Seite #2749844
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
#2750826
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
Moderator Persönliche Seite #2750849
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.

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 14 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.