Forum: Mikrocontroller und Digitale Elektronik Watchdog Reset Fehler


von Jabu (Gast)


Lesenswert?

Hey,

Ich habe ein Problem mit dem Watchdog Reset des ATmega644. Ich möchte an 
einer beliebigen Programmstelle einen Reset des AVRs bewirken und nutze 
dafür den WDT. Das sieht recht simpel aus:

wdt_enable(WDTO_15MS);
while(1); //Reset sollte nach 15ms erfolgen

Das tut er dann auch. Neu starten tut er dann allerdings nicht mehr, 
selbst wenn ich ganz am Beginn der main()

wdt_disable();

einfüge. Vielleicht sollte ich diesen Fehler etwas erklären: Es scheint 
schon ein Start durchgeführt zu werden, das Backlight vom LCD welches in 
ansteuere fängt wie wild an zu flackern (sollte eigentlich einfach nur 
eingeschaltet werden) und das wars dann auch schon. Dieser Zustand 
bleibt erhalten, von einem normalen Programmstart nicht zu reden. Selbst 
bei manuelem Reset wird nach auftreten dieses Fehlers das Programm nicht 
mehr richtig gestartet. Erst nachdem VCC einige Sekunden weg ist und 
dann wieder angelegt wird startet das Programm ordnungsgemäß.

Hat jemand eine Idee?

von Bernd (Gast)


Lesenswert?

Zeile 17 ist falsch.

von Jabu (Gast)


Lesenswert?

Das ist weder witzig noch bringt es irgendjemanden weiter. Ich kann den 
Code hier gerne posten aber aus viel mehr als den 3 Zeilen und der LCD 
Initialisierung, die einwandfrei funktioniert, besteht der nunmal nicht.

von Steffen (Gast)


Lesenswert?

Na dann poste mal.

von Oliver J. (skriptkiddy)


Lesenswert?

Das klingt irgendwie hier nach:
Beitrag "Periodischer Reset trotz wdt_disable();"

Grüße Oliver

von der alte Hanns (Gast)


Lesenswert?

Setzt C das WDIE?
Vielleicht mal den Watchdog-Interrupt programmieren, schaden kann's 
nicht.

von Jabu (Gast)


Lesenswert?

Ich habe den Code nun wie folgt reduziert:

int main()
{
    wdt_disable();
    DDRD|=(1<<PD7);

    PORTD&= ~(1<<PD7);
    _delay_ms(1000);
    PORTD |= (1<<PD7);
    _delay_ms(1000);
    wdt_enable(WDTO_15MS);
    while(1);
}

Hiernach sollte die am PD7 angeschlossene LED mit ca. 1Hz blinken, das 
tut sie allerdings nicht. main() wird nur einmal korrekt ausgeführt, 
danach bleibt die LED aus.

von Steffen (Gast)


Lesenswert?

Jabu schrieb:
> Ich habe den Code nun wie folgt reduziert:
>
> int main()
> {
>     wdt_disable();
>     DDRD|=(1<<PD7);
>
>     PORTD&= ~(1<<PD7);
>     _delay_ms(1000);
>     PORTD |= (1<<PD7);
>     _delay_ms(1000);
>     wdt_enable(WDTO_15MS);
>     while(1);
> }
>
> Hiernach sollte die am PD7 angeschlossene LED mit ca. 1Hz blinken, das
> tut sie allerdings nicht. main() wird nur einmal korrekt ausgeführt,
> danach bleibt die LED aus.

Aus dem Tutorial:

Bei neueren AVR-Typen bleibt der Watchdog auch nach einem Reset durch 
den Watchdog aktiviert. Wenn ein Programm nach dem Neustart bis zur 
erstmaligen Rückstellung des Watchdogs länger braucht, als die im 
Watchdog eingestellte Zeit, sollte man den Watchdog explizit möglichst 
früh deaktivieren. Ansonsten resetet der Watchdog den Controller 
immerfort von Neuem. Die frühe Deaktivierung sollte durch eine Funktion 
erfolgen, die noch vor allen anderen Operationen (insbesondere vor dem 
mglw. länger andauernden internen Initialisierungen vor dem Sprung zu 
main()) ausgeführt wird. Näheres zur Implementierung mit 
avr-gcc/avr-libc findet sich in der Dokumentation der avr-libc 
(Suchbegriffe: attribut, section, init).

Versuch mal die Zeit hoch zu stellen.

von g457 (Gast)


Lesenswert?

> Ich habe den Code nun wie folgt reduziert:

Der gegebene Code compiliert so nicht. Was hast Du denn sonst noch so 
alles ausser main()?

von Jabu (Gast)


Lesenswert?

Bei mir kompiliert dieser Code wunderbar, ich habe alle anderen 
Programmteile bis auf dieses main rausgenommen. Auch habe ich nun die 
WDT Zeit auf 500ms hochgesetzt, ohne Unterschied. Auch MCUSR = 0; folgt 
jetzt gleich auf wdt_disable, ohne Änderung.

von Oliver J. (skriptkiddy)


Lesenswert?

g457 schrieb:
> Der gegebene Code compiliert so nicht. Was hast Du denn sonst noch so
> alles ausser main()?

Wahrscheinlich das hier am Anfang der Datei:
1
#include <avr/io.h>
2
#include <avr/wdt.h>

: Bearbeitet durch User
von Jabu (Gast)


Lesenswert?

Vollständigkeitshalber hier nochmal der an den bisherigen Kommentaren 
verbesserte, nicht funktionierende Code:

#include <avr/io.h>
#include <avr/wdt.h>

int main()
{
    wdt_disable();
    MCUSR = 0;        //Nachgebessert (Interrupt Flag Reset)
    DDRD|=(1<<PD7);

    PORTD&= ~(1<<PD7);
    _delay_ms(1000);
    PORTD |= (1<<PD7);
    _delay_ms(1000);
    wdt_enable(WDTO_500MS);  //Nachgebessert auf 500ms
    while(1);
}

von (prx) A. K. (prx)


Lesenswert?

Ist der Watchdog per Fuse eingeschaltet? Dann lässt er sich nämlich 
überhaupt nicht abschalten.

von Steffen (Gast)


Lesenswert?

Versuch mal ohne den wdh.h auf manuellen weg.
1
//einschalten
2
MCUSR = (1<<WDRF);
3
WDTCSR = (1<<WDE); // keine Prescale 16ms
4
5
//ausschalten
6
MCUSR = 0;
7
WDTCSR = 0;

Datenblatt s.53 es gibt keine 15ms.
Dann die Fuse WDTON keinen Haken setzen.

von (prx) A. K. (prx)


Lesenswert?

Steffen schrieb:
> Datenblatt s.53 es gibt keine 15ms.

15ms = 16ms. So arg genau ist der sowieso nicht.

von (prx) A. K. (prx)


Lesenswert?

Steffen schrieb:
> Versuch mal ohne den wdh.h auf manuellen weg.

Ohne WDCE?

von Jabu (Gast)


Lesenswert?

int main()
{
    //wdt_disable();
  //ausschalten
  MCUSR = 0;
  WDTCSR = 0;

    DDRD|=(1<<PD7);

    PORTD&= ~(1<<PD7);
    _delay_ms(1000);
    PORTD |= (1<<PD7);
    _delay_ms(1000);
    //wdt_enable(WDTO_500MS);
  //einschalten
  MCUSR = (1<<WDRF);
  WDTCSR = (1<<WDE); // keine Prescale 16ms
    while(1);
}

Keine Besserung. WDTON Fuse wird vom AVR Studio 5 Programmer als 0 
gelesen.

von g457 (Gast)


Lesenswert?

Oliver schrub:
> Wahrscheinlich das hier am Anfang der Datei:

Es ist uninteressant was es ∗wahrscheinlich∗ ∗ungefähr∗ ist - der TO 
soll mit seinem ∗echten∗ Code rausrücken, sonst ist das nur Fischen im 
Nebel.

Zum echten Code zählt alles, nicht nur etwas das ungefähr ein bisschen 
fast so ähnlich aussieht.

von Steffen (Gast)


Lesenswert?

A. K. schrieb:
> Steffen schrieb:
>> Versuch mal ohne den wdh.h auf manuellen weg.
>
> Ohne WDCE?

naja muss man testen.

Aus dem Datenblatt:
> This bit is used in timed sequences for changing WDE and prescaler bits. > To 
clear the WDE bit,
> and/or change the prescaler bits, WDCE must be set.

prescaler wird ja nicht gesetzt.

von g457 (Gast)


Lesenswert?

> WDTON Fuse wird vom AVR Studio 5 Programmer als 0 gelesen.

..also an :-)

von Steffen (Gast)


Lesenswert?

g457 schrieb:
>> WDTON Fuse wird vom AVR Studio 5 Programmer als 0 gelesen.
>
> ..also an :-)

genau...also wenn das die Ursache ist... mann mann mann

von Peter D. (peda)


Lesenswert?

Jabu schrieb:
> wdt_disable();
>     MCUSR = 0;

Die Reihenfolge ist falsch.

von (prx) A. K. (prx)


Lesenswert?

Steffen schrieb:
> naja muss man testen.

Ist eindeutig. Um WDE zurückzusetzen muss WDCE gesetzt sein. Hat ja auch 
einen Sinn, das soll nicht aus versehen geschehen dürfen.

Er soll mal ruhig beim wdt_reset() bleiben.

von Jabu (Gast)


Lesenswert?

Um sämtliche fehlerhaften Einflüsse auszuschließen habe ich ein neues 
Projekt angelegt in dem nichts weiter als folgendes steht:

#include <avr/io.h>
#include <avr/wdt.h>
#include <avr/delay.h>

#define F_CPU = 8000000

int main()
{
    wdt_disable();
    MCUSR = 0;        //Nachgebessert (Interrupt Flag Reset)
    DDRD|=(1<<PD7);

    PORTD&= ~(1<<PD7);
    _delay_ms(1000);
    PORTD |= (1<<PD7);
    _delay_ms(1000);
    wdt_enable(WDTO_500MS);  //Nachgebessert auf 500ms
    while(1);
}

WDTON Fuse habe ich testweise auf 1 gesetzt, die LED bleibt dan 
dauerhaft aus. Wenn diese auf 0 ist geht sie wie vorher bereits nur 
einmal an.

von (prx) A. K. (prx)


Lesenswert?

Jabu schrieb:
>     wdt_disable();
>     MCUSR = 0;        //Nachgebessert (Interrupt Flag Reset)

Immer noch falsch rum. Solange WDRF an ist geht der Wachdog nicht aus.

von Steffen (Gast)


Lesenswert?

A. K. schrieb:
> Steffen schrieb:
>> naja muss man testen.
>
> Ist eindeutig. Um WDE zurückzusetzen muss WDCE gesetzt sein. Hat ja auch
> einen Sinn, das soll nicht aus versehen geschehen dürfen.
>
> Er soll mal ruhig beim wdt_reset() bleiben.

Naja sollte ja ein Test sein ob es vielleicht an der wdt.h liegt. So 
weit wie ich das gelesen habe macht er keinen wdt_reset irgendwie... tut 
ja auch sonst wie Geheimsnissvoll um den Quelltext. Nuja jetzt sind wir 
bei der Minimalanforderung und beim Lernen wie der WDT funktioniert 
angekommen :-D

von Jabu (Gast)


Lesenswert?

Ich habe das löschen von WDRF von ganz an den Anfang geschrieben, keine 
Änderung.

von (prx) A. K. (prx)


Lesenswert?

Jabu schrieb:
> Ich habe das löschen von WDRF von ganz an den Anfang geschrieben, keine
> Änderung.

Und die Fuse?

von Jabu (Gast)


Lesenswert?

Fuse habe ich als 0 und auch als 1 getestet. Als 0 leuchtet die LED 
einmal auf, als 1 bleibt alles dunkel.

@ Steffen:
Ich möchte auch keinen wdt_reset() machen, ich möchte den AVR 
softwareseitig zum reset zwingen und das funktioniert nach meinem Wissen 
nur über den WDT Reset. Wen du eine bessere Methode kennst bitte teile 
sie mir mit.

von Peter D. (peda)


Lesenswert?

Jabu schrieb:
> Fuse habe ich als 0 und auch als 1 getestet.

IMHO muß man nach dem 1 setzen erstmal ausschalten, damit die Fuse auch 
übernommen wird.

von der alte Hanns (Gast)


Lesenswert?

Die 'unmaßgebliche Meinung' ist korrekt.

von (prx) A. K. (prx)


Lesenswert?

Jabu schrieb:
> #include <avr/delay.h>
>
> #define F_CPU = 8000000

Erstens heisst das
#define F_CPU 8000000

Zweitens hast du den Stall zugesperrt, nachdem das Pferd schon ausgebüxt 
ist. Denn F_CPU wird von delay.h benötigt.

von (prx) A. K. (prx)


Lesenswert?

der alte Hanns schrieb:
> Die 'unmaßgebliche Meinung' ist korrekt.

Er ist bloss bescheiden.

von Jabu (Gast)


Lesenswert?

Tut mir leid für den Tippfehler mit dem "=" ! Die delay routine 
funktioniert dennoch problemlos! Habe dies jetzt korrigiert.

von Steffen (Gast)


Lesenswert?

Jabu schrieb:
> Fuse habe ich als 0 und auch als 1 getestet. Als 0 leuchtet die LED
> einmal auf, als 1 bleibt alles dunkel.
>
> @ Steffen:
> Ich möchte auch keinen wdt_reset() machen, ich möchte den AVR
> softwareseitig zum reset zwingen und das funktioniert nach meinem Wissen
> nur über den WDT Reset. Wen du eine bessere Methode kennst bitte teile
> sie mir mit.

Aach ja....
Die LED kann ja nicht an gehn, nach 16ms kommt der Reset die macht das 
so schnell das man das nicht sieht. Stell mal den WDT auf 1s

von Jabu (Gast)


Lesenswert?

Habe nach der Programmierung der Fuse bits jeweils einen kompletten 
Reset = Spannung weg vorgenommen.

von (prx) A. K. (prx)


Lesenswert?

Steffen schrieb:
> Die LED kann ja nicht an gehn, nach 16ms kommt der Reset die macht das
> so schnell das man das nicht sieht. Stell mal den WDT auf 1s

Du hängst etwas. Er steht schon bei 500ms. Ausserdem ist für die Dauer 
der LED das Delay zuständig.

von (prx) A. K. (prx)


Lesenswert?

Jabu schrieb:
> Tut mir leid für den Tippfehler mit dem "=" ! Die delay routine
> funktioniert dennoch problemlos! Habe dies jetzt korrigiert.

Die tut auch ganz ohne F_CPU. Nur nicht unbedingt mit der gewünschten 
Zeit.

von Jabu (Gast)


Lesenswert?

Letzter Stand des Programms:

#include <avr/io.h>
#include <avr/wdt.h>
#include <avr/delay.h>

#define F_CPU 8000000

int main()
{
    MCUSR = 0;
    wdt_disable();
    DDRD|=(1<<PD7);

    PORTD&= ~(1<<PD7);
    _delay_ms(1000);
    PORTD |= (1<<PD7);
    _delay_ms(1000);
    wdt_enable(WDTO_500MS);
    while(1);
}

Getestet mit WDTON Fuse 0/1 (Wobei Haken raus die korrekte Belegung zu 
sein scheint, bezogen auf AVRStudio 5.0 ISP Programmer), VCC jeweils 
mehrere Sekunden weggenommen nach programmieren von den Fuses, Problem 
besteht weiterhin.

Danke für die große Resonanz und die viele Vorschläge, hier nurmal kurz 
eingeschoben.

von Steffen (Gast)


Lesenswert?

A. K. schrieb:
> Steffen schrieb:
>> Die LED kann ja nicht an gehn, nach 16ms kommt der Reset die macht das
>> so schnell das man das nicht sieht. Stell mal den WDT auf 1s
>
> Du hängst etwas. Er steht schon bei 500ms. Ausserdem ist für die Dauer
> der LED das Delay zuständig.

ja das simmt, der Tatort lenkt mich ab. Also ich würder bei der 
manuellen WDT Routine bleiben und am Anfang alles ausschalten. Dann das 
Programm laufen lassen und dann den Reset Starten. Das muss gehen. 
Wichtig die Fuse auf 1

von Jabu (Gast)


Lesenswert?

F_CPU steht im geposteten über den includes, sry.

von Jabu (Gast)


Lesenswert?

Wenn ich ein Haken in WDTON setze ist die LED nach wie vor dauerhaft 
aus.

von Steffen (Gast)


Lesenswert?

Jabu schrieb:
> Wenn ich ein Haken in WDTON setze ist die LED nach wie vor dauerhaft
> aus.

also eins fällt mir noch ein, Programmer abgesteckt?, JTAG Debugger 
abgesteckt?

von Jabu (Gast)


Lesenswert?

Habe den ISP Stecker jeweils abgezogen. Das einzige was ich mir hierzu 
noch vorstellen kann ist, dass es sich um irgendeinen Hardwarefehler 
handelt, auch wenn ich diesen Controller in seiner Umgebung schon Wochen 
problemlos programmiere. Ich werde morgen mal ein anderes Board 
ausprobieren, vielleicht ergibt sich da was.

von Steffen (Gast)


Lesenswert?

Jabu schrieb:
> Habe den ISP Stecker jeweils abgezogen. Das einzige was ich mir hierzu
> noch vorstellen kann ist, dass es sich um irgendeinen Hardwarefehler
> handelt, auch wenn ich diesen Controller in seiner Umgebung schon Wochen
> problemlos programmiere. Ich werde morgen mal ein anderes Board
> ausprobieren, vielleicht ergibt sich da was.

Naja oder das Programm (diesen Testcode) in einem komplett neuen Project 
erstellen.

von Jabu (Gast)


Lesenswert?

Was ich bereits, wie oben erwähnt, getan habe (-;

von der alte Hanns (Gast)


Lesenswert?

Jetzt tun Sie mir doch den Gefallen und belegen, wie schon vor 
anderthalb Stunden vorgeschlagen, und auch nur als Schuss ins Blaue 
hinein, den Watchdog-Interrupt, wie auch immer das in C aussieht.
Dann kann ich nämlich endlich zu Bett gehen, die Nachtschwester meckert 
schon.

von Jabu (Gast)


Lesenswert?

Wie der in C aussieht weiß ich leider genauso wenig und bevor ich da 
jetzt etwas hinklatsche werde ich das lieber die tage mal ausprobieren, 
Dennoch danke für die Idee. Wundern tut es mich trotzdem warum es nicht 
ohne zu gehen scheint...

von g457 (Gast)


Lesenswert?

Hast do einen Bootloader am laufen? Falls ja wirf den mal raus.

Und: Pack das wdt_disable() mal in die .noinit [0] - main() ist 
regelmäßig zu spät.

[0] http://www.nongnu.org/avr-libc/user-manual/group__avr__watchdog.html

von g457 (Gast)


Lesenswert?

s/.noinit/.init3/g;
</ingrid>

von Jabu (Gast)


Lesenswert?

Verwende keinen Bootloader. Sry, wo soll ich das wdt_disable() 
reinschreiben? s/.noinit/.init3/g; sagt mir nichts.

Tut mir leid wenn diese frage unnötig unwissend ist /-:

von g457 (Gast)


Lesenswert?

> Sry, wo soll ich das wdt_disable() reinschreiben?

Auf den angegebenen Link klicken und lesen.

von Thomas E. (thomase)


Lesenswert?

1
#ifndef F_CPU
2
  #error F_CPU not defined.
3
#endif
4
5
#include <avr/io.h>
6
#include <avr/wdt.h>
7
#include <util\delay.h>
8
9
int main(void)
10
{  
11
  MCUSR &= ~(1<<WDRF);
12
  wdt_disable();
13
14
  DDRD |= (1 << 7);
15
16
  for(unsigned char nInd = 0; nInd < 20; nInd++)
17
  {
18
    PIND |= (1 << 7);
19
    _delay_ms(50);
20
  }
21
22
  wdt_enable(WDTO_1S);  
23
24
  while(1)
25
  {
26
    PORTD &= ~(1 << 7);    
27
  }
28
}

Led blinkt 1s, leuchtet 1s, Watchdog schlägt zu, Spiel beginnt von vorn.

Ist die Watchdog-Fuse gesetzt, schlägt der Watchdog 16ms nach Reset zu, 
löst einen Reset aus... Die LED blinkt heftig.

Wenn das nicht so ist, ist deine Schaltung im A..., der Controller 
kaputt oder irgend jemand zu doof für diese Welt.

mfg.

von Jabu (Gast)


Lesenswert?

Was machst du da mit PIND? Und warum läuft die for-Schleife um 20 mal 
eine Warteschaleife aufzurufen? Wie kommt es dass du PORTD &= ~(1 << 7) 
wieder und wieder in der while-schleife auf 0 setzt?

Ich habe das Programm so aufgespielt und es zeigt sich das gleiche wie 
mit dem anderen. Kein blinken. Hast du das Programm auf einem AVR 
getestet?

von (prx) A. K. (prx)


Lesenswert?

Jabu schrieb:
> Was machst du da mit PIND?

Schnell blinken. Eine 1 schreiben nach PINx toggelt den Pin.

von (prx) A. K. (prx)


Lesenswert?

Jabu schrieb:
> Ich habe das Programm so aufgespielt und es zeigt sich das gleiche wie
> mit dem anderen. Kein blinken. Hast du das Programm auf einem AVR
> getestet?

Gibts irgendwelche Fehler oder Warnungen, die "völlig unwichtig" sind? 
Es ist auch garantiert der richtige Controller und die Hardware hat 
alles, was das hiesige Tutorial empfiehlt?

Soll heissen: Mach mal ein Bild vom Aufbau.

: Bearbeitet durch User
von Thomas E. (thomase)


Lesenswert?

Jabu schrieb:
> Was machst du da mit PIND?
Toggeln.

> Und warum läuft die for-Schleife um 20 mal eine Warteschaleife
> aufzurufen?
Damit es 20 Mal blinkt.

> Wie kommt es dass du PORTD &= ~(1 << 7)
> wieder und wieder in der while-schleife auf 0 setzt?
Das PORTD &= ~(1 << 7) kann auch vor der while-Schleife stehen. Aber dem 
Controller ist das sowas von egal...

> Ich habe das Programm so aufgespielt und es zeigt sich das gleiche wie
> mit dem anderen. Kein blinken. Hast du das Programm auf einem AVR
> getestet?
Ja.

Übliche Fehler:
CKDIV8-Fuse gesetzt?
Falsches Hex-File geflasht?
Ich mache alles richtig!

Aber dann würde es laufen.

mfg.

von Jabu (Gast)


Lesenswert?

Das Problem hat sich gelöst. Es hatte tatsächlich mit dem programmieren 
der FUSE bits zu tun, diese Programmierung wurde wohl nicht korrekt 
ausgeführt und eine unscheinbare Fehlermeldung ist erschienen.

Danke nochmal für die Hilfe.

von (prx) A. K. (prx)


Lesenswert?

Naja, glauben wir das mal... ;-)

von Steffen (Gast)


Lesenswert?

Jabu schrieb:
> Das Problem hat sich gelöst. Es hatte tatsächlich mit dem programmieren
> der FUSE bits zu tun, diese Programmierung wurde wohl nicht korrekt
> ausgeführt und eine unscheinbare Fehlermeldung ist erschienen.
>
> Danke nochmal für die Hilfe.

Das ist nicht dein Ernst.

A. K. schrieb:
> Naja, glauben wir das mal... ;-)

Ich nicht so wirklich.

Mir ist da glaub ich noch n Fehler aufgefallen mit der while(1);

Jabu schrieb:
> Letzter Stand des Programms:
>     while(1);

Sollte das nicht so aussehen?
1
while(1) {}

von g457 (Gast)


Lesenswert?

>> Letzter Stand des Programms:
>>     while(1);
>
> Sollte das nicht so aussehen?
>
> while(1) {}

das ist semantisch äquivalent.

von (prx) A. K. (prx)


Lesenswert?

Steffen schrieb:
>> Naja, glauben wir das mal... ;-)
>
> Ich nicht so wirklich.

Ich ja auch nicht. Ich vermute, dass er seit Stunden das immer gleiche 
alte Hexfile reinjagte. Und sich nicht traut, das zuzugeben.

> while(1) {}

Ist egal.

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.