Watchdog timer löst keinen interrupt aus

Gast #2036873
hallo zusammen, mein wdt löst keinen ionterrupt aus, jemand ne ahnung 
warum??? µC ist der tiny2313.

hier mal der zugehörige code:
1
#define WD_PRESCALER  WDT_32MS
2

3
(...)
4

5
ISR(WDT_OVERFLOW_vect)
6
{
7
   WD_cnt++;
8
}
9

10
(...)
11

12
// Init watchdog timer as normal timer with interrupt
13
void init_WDT_IRQ(void)
14
{
15
   disable_IRQ();
16

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

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

23
   WD_cnt  = 0;
24

25
   enable_IRQ();
26
}
Gast
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]
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. ;-)
Gast
> 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");
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.
Gast
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
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.
Gast
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)
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?
Gast
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.
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.
Gast
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
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.
Gast
so, sollte jetzt so stimmen oder:
- timer an, prescaler lt. define, interrupt an, systemreset deaktivert.

code:
1
// Init watchdog timer as normal timer with interrupt
2
void init_WDT_IRQ(void)
3
{
4
   disable_IRQ();
5
   reset_WDT();
6

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

13
   enable_IRQ();
14
   WD_cnt  = 0;
15
}

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

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 15 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.