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


von micha s. (Gast)


Lesenswert?

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
}

von micha s. (Gast)


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]

von Jan S. (jan_s)


Lesenswert?

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

von micha s. (Gast)


Lesenswert?

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

von Jan S. (jan_s)


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?

von Jan S. (jan_s)


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. ;-)

von micha s. (Gast)


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");

von Jan S. (jan_s)


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.

von micha s. (Gast)


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

von Jan S. (jan_s)


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.

von micha s. (Gast)


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)

von micha s. (Gast)


Lesenswert?

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

von Jan S. (jan_s)


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?

von micha s. (Gast)


Lesenswert?

hm wie prüfe ich den stack...?

von micha s. (Gast)


Lesenswert?

werd ich aber wie gesagt erst heut abend da ich noch beim arbeiten 
bin...

von Jan S. (jan_s)


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.

von micha s. (Gast)


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.

von Thomas E. (thomase)


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.

von spess53 (Gast)


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

von Jan S. (jan_s)


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.

von micha s. (Gast)


Lesenswert?

super dank euch dreien :)

von micha s. (Gast)


Lesenswert?

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?

von spess53 (Gast)


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

von Thomas E. (thomase)


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.

von micha s. (Gast)


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?

von micha s. (Gast)


Lesenswert?

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

von spess53 (Gast)


Lesenswert?

Hi

>soll ich alles in assembler schreiben?

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

MfG Spess

von micha s. (Gast)


Lesenswert?

mach ich und zum vgl nehm ich mal dein code

von Micha S. (e-tec)


Lesenswert?

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

von Jan S. (jan_s)


Lesenswert?

Jaholla...

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

von Micha S. (e-tec)


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!

von Spess53 (Gast)


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

von Micha S. (e-tec)


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 :)

von Spess53 (Gast)


Lesenswert?

Hi

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

MfG Spess

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.