Forum: Mikrocontroller und Digitale Elektronik Atmega644 ISR(WDT_vect)


von D a v i d K. (oekel) Benutzerseite


Lesenswert?

Hi,

ich würde gerne mit dem im Titel genannten Chip den WDT über den ISR 
verwenden.
(Zum testen ausschließlich den Vektor, später im Betrieb dann wie im 
Datenblatt beschrieben erst Vector zum Wegspeichern, dann Reset)

Nun verwende ich:
1
#include <util/delay.h>
2
#include <avr/wdt.h>
3
4
ISR(WDT_vect) {
5
        Beeper_ON();
6
7
8
/* ReEnable the watchdog interrupt,
9
 * as this gets reset when entering this ISR and automatically enables the WDE signal
10
 * that resets the MCU the next time the  timer overflows */
11
  WDTCSR |= (1<<WDIE);
12
}
13
14
void watchdogSetup() {
15
16
    // Reset the watchdog reset flag
17
    wdt_reset();
18
    wdt_enable(WDTO_4S);
19
    // Enable interrupts instead of reset
20
    WDTCSR |= (1 << WDIE);
21
}
22
23
void loop() {
24
    //Beeper_ON();
25
    LED_SW2_ON();
26
    for (int i = 0; i < 8; ++i) {
27
        _delay_ms(100);
28
    }
29
    //Beeper_OFF();
30
    LED_SW2_OFF();
31
    for (int i = 0; i < 8; ++i) {
32
        _delay_ms(100);
33
    }
34
}
35
36
int main() {
37
    watchdogSetup();
38
    ioinit();
39
    while (1) {
40
        loop();
41
    }
42
}

Als Minibeispiel.

Ich erkenne, dass die LED in gleichbleibenden Takt wie gewollt blinkt 
und dann pötzlich eine Unregelmäßigkeit aufweißt, was ich als den RESET 
deute.

Witziger weise, kommt kein Ton (wortwörtlich) aus dem ISR zur gleichen 
Zeit :(.
(Dabei sind LED_SW2_ON() und Beeper_ON() problemlos gegeneinander 
auszutauschen, womit ich 100% einen Fehler in der Ansteuerung 
ausschließen kann)

Vermutlich stimmt die Reihenfolge von
"WDTCSR |= (1 << WDIE);"

zu:    wdt_reset(); und  wdt_enable(WDTO_4S);
nicht. Habe aber bereits alle möglichen Konstellationen durchprobiert.

Daher wollte ich fragen, ob ihr mir auf die Sprünge helfe könnt den ISR 
sachgemäß zu aktivieren?

Danke und noch eine sonnigen Sonntag :)

: Bearbeitet durch User
von g457 (Gast)


Lesenswert?

> Daher wollte ich fragen, ob ihr mir auf die Sprünge helfe könnt den ISR
> sachgemäß zu aktivieren?

Einfach nochmal die Doku zu WDIE lesen.

HTH

von D a v i d K. (oekel) Benutzerseite


Lesenswert?

g457 schrieb:
> Einfach nochmal die Doku zu WDIE lesen.

Ok, damit meinst du wohl den Part mit
1
WDTCSR |= (1 << WDCE) | (1 << WDE);
vor jedem Schreibzyklus.

Zusätzlich habe ich nun noch folgendende Section (die man wohl immer 
haben sollte) hinzugefügt.
1
//TODO: verschieben in *.h?
2
uint8_t mcusr_mirror __attribute__ ((section (".noinit")));
3
4
void get_mcusr(void) \
5
  __attribute__((naked)) \
6
  __attribute__((section(".init3")));//init3 korrekt auch für den Atmega 644?
7
8
void get_mcusr(void) {
9
    mcusr_mirror = MCUSR;
10
    MCUSR = 0;
11
    wdt_disable();//Darf diese nur verwendet werden, weil intern eh ASM steht?
12
}
13
14
bool wd_barked() {
15
    //return (mcusr_mirror & (1 << PC3));
16
    return (mcusr_mirror & (_BV(WDRF)));
17
}


Trotzdem verstehe ich die Logig noch nicht ganz.
Wenn ich folgendes auf den Chip bringe:
1
if (!wd_barked()) {
2
        WDTCSR |= (1 << WDCE) | (1 << WDE);
3
        MCUSR &= ~(1 << WDRF);
4
        unsigned char temp = ((1 << WDIE) | (1 << WDP3) | (1 << WDP0));//8sec
5
        //unsigned char temp = (1 << WDIE) | (1 << WDP3);//4sec
6
        WDTCSR |= (1 << WDCE) | (1 << WDE);
7
        WDTCSR = temp;
8
    }
9
    ioinit();
10
    sei();

Ertöhnt (direkt nach dem bestromen) das Piepen aus dem ISR genau 1x kurz 
und er startet neu.

Ich hätte, wie man hoffentlich aber erkennt, erst 8sec normalen Betrieb 
bzw, möchte das "if" hier nicht für den wdt verwenden, sondern 
anderweitig.
Wenn ich den wdt-init Teil hier aber ohne if lasse, habe ich ein 
endloses ISR-Restart drin.

Habt ihr nicht noch einen Rat?
Die Allgemeinen Infos und Datenblätter bringen mich hier nicht weiter 
und erst recht nicht diese Arduino Schnipsel, welche man überall findet.

LG

von HildeK (Gast)


Angehängte Dateien:

Lesenswert?

Ich bin nicht gut genug, um deine SW zu debuggen, aber ich habe dir ein 
ganz ähnlich funktionierendes Programm für den TinyX5 angehängt.
WD-Timer, WD-Interrupt, WD-Reset - alles enthalten.
Dient mir als Beispiel und sollte mit nur wenig Änderung auch beim 644 
funktionieren.

von D a v i d K. (oekel) Benutzerseite


Lesenswert?

HildeK schrieb:
> Ich bin nicht gut genug, um deine SW zu debuggen, aber ich habe dir ein
> ganz ähnlich funktionierendes Programm für den TinyX5 angehängt.

Beim Vergleichen erkenne ich keinen Makanten Unterschied.
Egal was ich mache, der WDTCSR scheint nicht lange genug zu warten.

Kurz nach dem Setup steht noch WDTCSR = 72 drin (debugged)
Und im ISR ist nur noch WDTCSR = 8.

Wo sind allso die verdammten Bits hin, oder muss ich die ALLE (WDIE ist 
klar) nach einem IR neu sezten?

Ich weiß zwar nicht, ob der WDT im Debugg weiter läuft, aber wenn ich 
die Breakpoints raus nehme, sollte ich doch an der blöden LED 2/4/8 Sek 
erkennen können.:(

von S. Landolt (Gast)


Angehängte Dateien:

Lesenswert?

Haben Sie sich so etwas vorgestellt?

von D a v i d K. (oekel) Benutzerseite


Lesenswert?

S. Landolt schrieb:
> Haben Sie sich so etwas vorgestellt?

Lieb gemeint, aber da entdecke ich einige Fehler und keine Neuerungen zu 
meinem Wissen/Fehler:

Sollte nicht im ISR sein...
1
ISR (WDT_vect) {
2
  WDTCSR = (1<<WDIE);
3
}

interrupt kann den kritischen Bereich unterbrechen:
1
  sei();
2
  WDTCSR = (1<<WDE) | (1<<WDCE);//aktivieren und sofort ...
3
  WDTCSR = (1<<WDE) | (1<<WDIE) | (1<<WDP3);        // interrupt&reset, 4 s

Ich glaube ich beschreibe lieber PORTB:
1
    PINB = 0b00000001;

von S. Landolt (Gast)


Lesenswert?

Es ging mir darum, ein lauffähiges Minimalprogramm anzubieten. Dass es 
nicht weiterhilft, ist schade.

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


Lesenswert?

Habe gerade mal ein eigenes Projekt angesehen, in dem ich den 
Watchdog-Interrupt als regelmäßigen Interrupt (ohne Reset) benutze.

Aus dem Kopf, ohne ins Datenblatt zu gucken:

WDTCSR beschreibt man am besten jeweils komplett, also kein "|=", 
sondern eine direkte Zuweisung.

Eine erfolgreiche Änderung des WDE-Bits benötigt unmittelbar zuvor ein 
aktives WDCE (watchdog change enable).

Vor allem Gefummel an WDTCSR zur Sicherheit immer erstmal den 
Watchdog-Counter auf Anschlag setzen.
1
static void
2
xxo_sleep(void)
3
{
4
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);
5
6
  cli();
7
  wdt_reset();
8
  WDTCSR = _BV(WDCE) | _BV(WDE);
9
  WDTCSR = _BV(WDIF) | _BV(WDIE) | 6; /* 1 s interrupts */
10
  sei();
11
}
12
13
static void
14
xxo_unsleep(void)
15
{
16
  set_sleep_mode(SLEEP_MODE_IDLE);
17
18
  cli();
19
  wdt_reset();
20
  WDTCSR = _BV(WDCE) | _BV(WDE);
21
  WDTCSR = 0;           /* turn off */
22
  sei();
23
}
24
25
ISR(WDT_vect)
26
{
27
  if (++trigger_seconds == TRIGGER_LEVEL)
28
    {
29
      trigger_seconds = 0;
30
      timer_triggered = true;
31
      xxo_unsleep();
32
    }
33
  else
34
    {
35
      xxo_sleep();
36
    }
37
}

Bei mir wacht der Watchdog (in etwa) jede Sekunde auf, aber nur um 
nachzusehen, ob "was zu tun ist". Das ist immer dann der Fall, wenn die 
TRIGGER_LEVEL Anzahl an Sekunden erreicht ist. Dann wird der WDT erstmal 
abgeschaltet, damit die Firmware normal arbeiten kann. Wenn sie fertig 
ist, ruft sie wieder xxo_sleep() auf.

Ja, das sei() gibt, wenn die Funktionen aus der ISR heraus aufgerufen 
werden, die Interrupts vorzeitig frei. Stört hier nicht. Man könnte 
natürlich auch die übliche Logik drumrum bauen, SREG retten, cli(), und 
am Ende SREG wieder herstellen.

: Bearbeitet durch Moderator
von S. Landolt (Gast)


Lesenswert?

D a v i d K. schrieb:
> keine Neuerungen zu
> meinem Wissen/Fehler

Da möchte ich denn doch widersprechen.
Mein Programm macht, in seiner Schlichtheit, zumindest das, was es soll: 
eine LED an B0 blinkt gleichmäßig. Ihr Programm hingegen läuft offenbar 
nicht korrekt, es lässt sich in der eingangs vorgestellten Version nicht 
einmal übersetzen, da Teile nicht gezeigt wurden; so ließ sich auch der 
Verdacht nicht bestätigen, dass es am fehlenden sei lag.
  Eine Kritik jetzt anzubringen, ist etwas merkwürdig - vor zwei Tagen 
wäre man in gemeinsamer Arbeit&Diskussion sicher weitergekommen.

von D a v i d K. (oekel) Benutzerseite


Lesenswert?

S. Landolt schrieb:
> D a v i d K. schrieb:
>> keine Neuerungen zu
>> meinem Wissen/Fehler
>
> Da möchte ich denn doch widersprechen.
> Mein Programm macht, in seiner Schlichtheit, zumindest das, was es soll:

Bei mir leider nicht. Hab es 1:1 eingespielt.
Erst danach, sind mir die Dinge aufgefallen,  welche ich als Hinweise 
aus dem Datenblatt habe.

Meine Experimentierzeit beschränkt sich leider derzeit aufs Hotel unter 
der Woche, weswegen ich leider nicht so spontan antworte.

von D a v i d K. (oekel) Benutzerseite


Lesenswert?

Jörg W. schrieb:
>...
> Bei mir wacht der Watchdog (in etwa) jede Sekunde auf, aber nur um
> nachzusehen, ob "was zu tun ist". Das ist immer dann der Fall, wenn die
> TRIGGER_LEVEL Anzahl an Sekunden erreicht ist. Dann wird der WDT erstmal
> abgeschaltet, damit die Firmware normal arbeiten kann. Wenn sie fertig
> ist, ruft sie wieder xxo_sleep() auf.


Danke das werde ich so noch mal testen!

von S. Landolt (Gast)


Lesenswert?

> Bei mir leider nicht.

Auf einem ATmega644 im Auslieferungszustand? Seltsam. Einer von uns 
beiden macht etwas falsch - allerdings ist C nicht meine Sprache.

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.