mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Watchdog timer löst keinen interrupt aus


Autor: micha s. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hallo zusammen, mein wdt löst keinen ionterrupt aus, jemand ne ahnung 
warum??? µC ist der tiny2313.

hier mal der zugehörige code:

#define WD_PRESCALER  WDT_32MS

(...)

ISR(WDT_OVERFLOW_vect)
{
   WD_cnt++;
}

(...)

// Init watchdog timer as normal timer with interrupt
void init_WDT_IRQ(void)
{
   disable_IRQ();

   // Start timed Sequence
   WDTCSR |= (1<<WDCE) | (1<<WDE);

   // Set new prescaler(time-out) value
   WDTCSR  = (1<<WDIE) | (1<<WDE) | | (WD_PRESCALER);

   WD_cnt  = 0;

   enable_IRQ();
}

Autor: micha s. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ups jetzt hab ich ein fehler in die zeile getippt:
[c]
   // Set new prescaler(time-out) value
   WDTCSR  = (1<<WDIE) | (1<<WDE) | | (WD_PRESCALER);
[\c]
muss natürlich so heissen:
[c]
   // Set new prescaler(time-out) value
   WDTCSR  = (1<<WDIE) | (1<<WDE) | (WD_PRESCALER);
[\c]

Autor: Jan S. (jan_s)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Weil "WDE" den System Reset einschaltet, würde ich sagen, lass dieses 
Bit mal 0.

Autor: micha s. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
klar ist mir bewusst aber vor dem system reset sollte ja der interrupt 
einmal ausgeführt werden!

Autor: Jan S. (jan_s)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hmm ja stimmt, sorry hatte ich vergessen.
Allerdings musst du danach wieder WDIE setzen, sondern ist der nächste 
Timeout ein Reset, ist dir das auch klar?

Autor: Jan S. (jan_s)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ansonsten besteht noch die Möglichkeit, das dir der Compiler etwas 
wegoptimiert, "WD_cnt++;" in dem Fall.

Wie sieht die Definition dafür aus?
Mal ins Listing geschaut was rauskommt?

Ich stochere bei GCC ein wenig im Dunkeln, ich nutze den nicht weil ich 
ihm nicht traue. ;-)

Autor: micha s. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> weil ich ihm nicht traue. ;-)

das kommt mir irgenwie seltsam bekannt vor ;)
WD_cnt ist ne globale volatile mit 8bit, soll später mal in EEPROM 
geschrieben werden.
ja ist mir klar aber die init wird ja nach jedem systemneustart (was 
nicht vorkommen sollte) neu aufgerufen und somit auch das Ir flag.

und nach dem watchdog_reset(); bleibt das flag ja normalerweise erhalten 
oder? hinter watchdog_reset(); steckt asm("WDR");

Autor: Jan S. (jan_s)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
micha s. schrieb:
> und nach dem watchdog_reset(); bleibt das flag ja normalerweise erhalten
> oder? hinter watchdog_reset(); steckt asm("WDR");

Ja das fasst das Flag nicht an.

Hast du das Ganze mal durch den AVR Simulator gejagt?

Mir fehlt so ein wenig die Information, wie Du das Ganze denn testest, 
zwischen Interrupt und dem kompletten Reset liegen schließlich nur 
wenige Millisekunden.

Also führe mal ein bisschen detailierter auf wie du testest, reduziere 
dein Programm auf den Tesfall und stelle das hier >komplett< ein.

Autor: micha s. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
testen eben im avr simulator.
hm das ganze programm (selbst nur den test hier rein zu stellen) wird 
viel zu viel, sind 5 files + enstspr. header...
wie gesagt der test ist im avr simulator, mit breakpoint beim IRQ von 
wdt ovr. kommt aber nie soweit obwohl ich den wdt nie zurücksetze.
aber ich werde sehen was ich machen kann, allerdings erst wenn ich 
wieder daheim bin, habs nicht dabei.
eventuell könnte es noch sein da ich recht viele interrupts habe das es 
nie soweit kommt weil er am interruot abarbeiten ist.
aber in der simulation funktioniert es soweit bis auf den wd

Autor: Jan S. (jan_s)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
micha s. schrieb:
> eventuell könnte es noch sein da ich recht viele interrupts habe das es
> nie soweit kommt weil er am interruot abarbeiten ist.
> aber in der simulation funktioniert es soweit bis auf den wd

Das wäre denkbar, der WDT Interrupt hat den Vektor 0x0012, also am A. 
der Welt und somit niedrigste Priorität. ;-)
Allerdings würde ich mir dann grundlegend Gedanken machen ob das Design 
sinnvoll ist, wenn das Programm so dermassen viele und lange Interrupts 
abarbeitet.

Autor: micha s. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
lang sind sie nicht, eher im geegnteil sie sind so kurz wie möglich.

es gibt den input capture, T1 ovr, pwm im modus 1 bzw 5 (phase correct), 
dazu noch den T0 overflow (und eventuell noch den ocr0a)

Autor: micha s. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
und der icp vector wird ja erst ausgelöst wenn ein flankenwechsel kommt, 
und das ist im simulator ja nicht der fall.-.

Autor: Jan S. (jan_s)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Tja, also mit der momentanen Informationslage kann Dir dann aber hier 
kaum jemand helfen.

Mein Vorschlag wäre, dass Du dein Programm auf der Kernproblem 
reduzierst.
Dann kann man weiter sehen.

Ansonsten viel mir jetzt noch Stack zu klein ein?

Autor: micha s. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hm wie prüfe ich den stack...?

Autor: micha s. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
werd ich aber wie gesagt erst heut abend da ich noch beim arbeiten 
bin...

Autor: Jan S. (jan_s)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
micha s. schrieb:
> hm wie prüfe ich den stack...?

Überprüfen ob der Stackpointer in einen SRAM Bereich läuft in dem schon 
was liegt.

Autor: micha s. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
das ist ja eig assembler ebene, sollte mich ja nicht unbedingt 
interessieren oder?
okay, wie komme ich an die größe des stacks? adresse müsste ja im db 
stehen.

Autor: Thomas Eckmann (Firma: Thomas Eckmann Informationst.) (thomase)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
So geht das:

//Watchdog Interval Timer
  WDTCSR |= (1<<WDCE) | (1<<WDE); //Enable Watchdog(Reset)
  MCUSR &= ~(1<<WDRF);     //Clear WDRF in MCUSR
  WDTCSR |= (1<<WDCE);  //Watchdog Change Enable
  WDTCSR = 0x46;     //Enable Interrupt, Disable Reset, Set Prescaler 1s

Beim Ändern es Watchdogs muß zum Schutz gegen unbeabsichtigtes 
Überschreiben ein bestimmter Ablauf in einer definierten Zeit 
eingehalten werden.

mfg.

Autor: spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

Also mit dieser Initialisierung, allerdings Assembler:

   ldi r16,(1<<WDCE) | (1<<WDE) ; Start timed sequence
   sts WDTCSR, r16
   ldi r16, 1<<WDE|1<<WDIE|7<<WDP0
   sts WDTCSR, r16
   sei

bekomme ich auf einem ATMega48 genau dein gewünschtes Verhalten: 
Interrupt und danach Reset. Debugt mit AVR Dragon. Den Simulator kannst 
du vergessen. Funktioniert nicht -> Known Issues.

MfG Spess

Autor: Jan S. (jan_s)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
micha s. schrieb:
> okay, wie komme ich an die größe des stacks? adresse müsste ja im db
> stehen.

SPH und SPL sind die Stackpointer "Register", diese werden idR auf die 
letzte SRAM Adresse gesetzt, das erledigt der Startup Code der mit 
verlinkt wird. Der SP zählt dann abwärts.

Und doch, das hat dich sehr wohl zu interessiern, wenn dein Stack zu 
groß wird, z.B. durch viele Subroutinen Aufrufe, dann überschreibst du 
damit evtl. Werte im SRAM.

Lies dir mal die Beschreibung des AVR Core durch, ist im DS des 
ATtiny2313 drinne. Dann wirds evtl. bissel klarer.

Autor: micha s. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
super dank euch dreien :)

Autor: micha s. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
so, sollte jetzt so stimmen oder:
- timer an, prescaler lt. define, interrupt an, systemreset deaktivert.

code:
// Init watchdog timer as normal timer with interrupt
void init_WDT_IRQ(void)
{
   disable_IRQ();
   reset_WDT();

   WDTCSR |=  (1<<WDCE) | (1<<WDE); // Start timed Sequence
   MCUSR  &= ~(1<<WDRF);            // Clear WDRF in MCUSR
   WDTCSR |=  (1<<WDCE);            // Watchdog Change Enable
   WDTCSR  =  (1<<WDIE)             // Enable Interrupt, Disable Reset 
           |  (WD_PRESCALER);       // Set Prescaler

   enable_IRQ();
   WD_cnt  = 0;
}

richtig?

Autor: spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

>richtig?

Sieh dir das Assemblerlisting an. Das ganze braucht ein bestimmtes 
Timing. Möglicherweise versaut dir C das. Das Codebeispiel aus dem 
Datenblatt kennst du?

MfG Spess

Autor: Thomas Eckmann (Firma: Thomas Eckmann Informationst.) (thomase)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
micha s. schrieb:
> reset_WDT();

Ist an dieser Stelle überflüssig, da der WDT noch gar nicht 
initialisiert ist. Schadet aber wohl auch nicht.

mfg.

Autor: micha s. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ja das codebeispiel war mal die grundlage zu der init funktion...
soll ich alles in assembler schreiben?
blöde frage wie packe ich mehrere asm befehle in eine funktion?

asm("befehl1",
    "befehl2");
usw oder?

Autor: micha s. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
übrigens der wd startet immer mit und ist immer aktiv ausser man 
schaltet ihn ab, also sollte man einen reset durchführen!

Autor: spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

>soll ich alles in assembler schreiben?

Nein. Aber sich mal ansehen, was der Compiler daraus macht.

MfG Spess

Autor: micha s. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
mach ich und zum vgl nehm ich mal dein code

Autor: Micha S. (e-tec)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
omg...das macht mir der compiler aus der init funktion...!!!
kann der dads nicht schlauer anstellen??? hilfe...back to the asm roots 
:)
71:       {
+00000304:   95A8        WDR                      Watchdog reset
74:          WDTCSR |=  (1<<WDCE) | (1<<WDE); // Start timed Sequence
+00000305:   B581        IN      R24,0x21         In from I/O location
+00000306:   6188        ORI     R24,0x18         Logical OR with immediate
+00000307:   BD81        OUT     0x21,R24         Out to I/O location
75:          MCUSR  &= ~(1<<WDRF);            // Clear WDRF in MCUSR
+00000308:   B784        IN      R24,0x34         In from I/O location
+00000309:   7F87        ANDI    R24,0xF7         Logical AND with immediate
+0000030A:   BF84        OUT     0x34,R24         Out to I/O location
76:          WDTCSR |=  (1<<WDCE);            // Watchdog Change Enable
+0000030B:   B581        IN      R24,0x21         In from I/O location
+0000030C:   6180        ORI     R24,0x10         Logical OR with immediate
+0000030D:   BD81        OUT     0x21,R24         Out to I/O location
77:          WDTCSR  =  (1<<WDIE)             // Enable Interrupt, Disable Reset
+0000030E:   E481        LDI     R24,0x41         Load immediate
+0000030F:   BD81        OUT     0x21,R24         Out to I/O location
80:          WD_cnt  = 0;
+00000310:   921000AF    STS     0x00AF,R1        Store direct to data space
81:       }
+00000312:   9508        RET                      Subroutine return


Autor: Jan S. (jan_s)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Jaholla...

Ja, lieber mit inline Assembler von Hand bauen. Ist ja jetzt auch nicht 
so schlimm oder?

Autor: Micha S. (e-tec)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
jup das denke ich mir auch...
ich mein mal im ernst, optimieren geht anders... werd in zukunft glaub 
echt lieber die hex oder binär zahlen ins register schreiben (wenns auch 
unübersichtlicher ist) aber besser als 3 befehle wenn ich ein 
besch...bit setzen will!

Autor: Spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
HI

So richtig verstehe ich deine Reihenfolge nicht. Erst WDTCSR ohne 
richtige Aktion, Dann MCUSR. WDRF ist nach Reset gelöscht. Dann wieder 
WDTCSR.

Mach doch einfach mal

   MCUSR  &= ~(1<<WDRF);
   WDTCSR  =  (1<<WDCE) | (1<<WDE);
   WDTCSR  =  (1<<WDE) | (1<<WDIE) | (WD_PRESCALER);

Das Assemblerlisting passt schon. Kürzer kann es C nicht.

MfG Spess

Autor: Micha S. (e-tec)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
doch kann es,
register = 0xneuer wert;

WDTCSR  =  (1<<WDCE) | (1<<WDE);
wdce brauchst du wenn du am wd irgendwas ändern willst (lt db)

und wde um den watchdog in der timing sequenz zu starten (auch db)

stimmt den rest von wdtcsr hätte ich in eine zeile schreiben können :)

Autor: Spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

MCUSR gehört aber nicht zum Watchdog! Das brauchst du nur für WDTCSR.

MfG Spess

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.