Forum: Mikrocontroller und Digitale Elektronik ATmega644 Watchdog


von Manfred L. (manni)


Angehängte Dateien:

Lesenswert?

Hallo,

ich habe einen ATmega644 und möchte mit dem Watchdog den Controller
booten. Hier mein verwendeter Code:
1
#include <stdio.h>
2
#include <avr/interrupt.h>
3
#include <avr/io.h>
4
#include <avr/wdt.h>
5
6
printf ("ATmega644 Controller Boot\n");
7
cli ();
8
wdt_enable (WDTO_15MS);
9
while (TRUE) {};

Der Controller gibt zwar schön den printf() string auf dem
Atmel-Studio-7 Terminal Window aus, aber er bootet nicht und bleibt
anscheinend irgendwo hängen. Das cli() habe ich eingefügt, damit er 
während der nächsten 15 ms keinen Interrupt mehr verarbeitet. Bei den 
von mir bisher verwendeten Controllern ATmega8 und ATmega32 funktioniert 
dieser Code einwandfrei.
Zur Info: Wie im Fuse-Menu zu sehen, habe ich das WDTON flag nicht
gesetzt.

Weiß jemand, was ich da falsch gemacht habe ?
Danke schon mal für jede Antwort.
Grüße Manni

von Spess53 (Gast)


Lesenswert?

Hi

<> Bei den
>von mir bisher verwendeten Controllern ATmega8 und ATmega32 funktioniert
>dieser Code einwandfrei.

Der ATMega644 ist aber weder ein ATMega8 noch ein ATMega32. Also lies 
das Datenblatt!

MfG Spess

von chris (Gast)


Lesenswert?

Wenn du ein Bootloader installiert hast, dann geht er warscheinlich in 
Dauerreset, erhoehe mal den Timeout auf Sekunden.

von MaWin (Gast)


Lesenswert?

Manfred L. schrieb:
> aber er bootet nicht

Was soll das überhaupt heißen?

von M. K. (sylaina)


Lesenswert?

Manfred L. schrieb:
> Weiß jemand, was ich da falsch gemacht habe ?

Ja, der Watchdog ist der Watchdog. Ein cli() interessiert ihn nicht. Das 
von dir angesprochene Fuse-Bit sorgt nur dafür, wenn ich mich recht 
entsinne, dass man den Watchdog nicht aus versehen ausschalten kann, er 
ist dann IMMER an wenn es gesetzt ist.

Aber deine Code-Zeilen sehen auch komisch aus, ich vermisse hier 
irgendwie mindestens etwas in der Form wie:
1
void main(void){}

Warum genau hast du keine main()?

: Bearbeitet durch User
von Peter D. (peda)


Lesenswert?

M. K. schrieb:
> Warum genau hast du keine main()?

Und meckert der Compiler nicht bei Code außerhalb von Funktionen?
Auf jeden Fall gibt es keine Instanz, die diesen Code ausführt.

: Bearbeitet durch User
von Manfred L. (manni)


Angehängte Dateien:

Lesenswert?

Peter D. schrieb:
> Und meckert der Compiler nicht bei Code außerhalb von Funktionen?
> Auf jeden Fall gibt es keine Instanz, die diesen Code ausführt.

Hallo Peter,
schön dass Du wieder "mitspielst".
Wie üblich hast Du natürlich recht, dass dieser Code-Schnipsel keine 
Instanz ergibt, aber ich wollte den Beitrag hier nicht mit 50 KByte C 
Source-Code voll-müllen.

Der generierte Assembler-Code im .lss file sieht so aus:
1
    printf ("ATmega644 Controller Boot\n");
2
    2416:  81 ed         ldi  r24, 0xD1  ; 209
3
    2418:  91 e0         ldi  r25, 0x01  ; 1
4
    241a:  0e 94 9b 13   call  0x2736  ; 0x2736 <puts>
5
    cli ();
6
    241e:  f8 94         cli
7
        : "r0"
8
    );
9
    __asm__ __volatile__ (
10
    2420:  98 e0         ldi  r25, 0x08  ; 8
11
    2422:  88 e1         ldi  r24, 0x18  ; 24
12
    2424:  0f b6         in  r0, 0x3f  ; 63
13
    2426:  f8 94         cli
14
    2428:  a8 95         wdr
15
    242a:  80 93 60 00   sts  0x0060, r24  ; 0x800060 <__DATA_REGION_ORIGIN__>
16
    242e:  0f be         out  0x3f, r0  ; 63
17
    2430:  90 93 60 00   sts  0x0060, r25  ; 0x800060 <__DATA_REGION_ORIGIN__>
18
    2434:  ff cf         rjmp  .-2        ; 0x2434 <Menu_KeyEnter+0x32c>
19
    2436:  08 95         ret

Dieser Code entspricht dem in der ATmega644 Dokumentation 
(2593O–AVR–02/12) auf Seite 49-51 vorgeschlagenen Code. Zur weiteren 
Info:
- es läuft kein Bootloader
- es sind keine weiteren externen interrupts enabled
- nur der TIMER0 läuft für eine Tastenabfrage a la PeDa Methode,
  die ich schon in zig Projekten erfolgreich eingesetzt habe
  --> nochmals Dank dafür !

Ich habe einfach den Verdacht, dass an den Fuses etwas nicht stimmt, die 
komplette Übersicht der Fuse-Einstellung nochmals hier im attached Bild.

Spess53 schrieb:
> Der ATMega644 ist aber weder ein ATMega8 noch ein ATMega32. Also lies
> das Datenblatt!

Ist mir bekannt und habe ich auch gelesen, siehe oben :-)
Danke für den hilfreichen Kommentar.

: Bearbeitet durch User
von Peter D. (peda)


Lesenswert?

Daß der Compiler den korrekten Code erzeugt, ist klar. Aber wir wissen 
immer noch nicht, welche Funktion ihn ausgeführt.
Um zu sehen, ob er in der Schleife hängt, laß doch darin ne LED blinken 
(5Hz) und setze den Wachhund auf 2s.

Langen Code anhängen, nicht einfügen.

von Εrnst B. (ernst)


Lesenswert?

Du hast zwar die Startup-Time auf 4.1 ms (+16 Clocks) gestellt, aber 
bist du dir sicher, dass alle deine Initialisierungen durchlaufen, bevor 
der Watchdog ein zweites Mal zuschlägt?

d.H., was passiert könnte folgendes sein:
Power-On
Init (braucht insg. länger als 15ms)
UART-Ausgabe
Watchdog-an auf 15ms
Watchdog reset
Init
Watchdog reset
Init
Watchdog reset
.....


Gegenprobe: Watchdog auf mehr als 15ms stellen, oder ganz am Anfang 
deiner Initialisierung wieder abschalten.


Nachtrag: Im Atmega644 - Datenblatt steht explizit, dass der 
Watchdog-Reset den Watchdog selber nicht abschaltet.
>>  the device will be reset and the Watchdog Timer will stay enabled

: Bearbeitet durch User
von Manfred L. (manni)


Lesenswert?

Peter D. schrieb:
> laß doch darin ne LED blinken
> (5Hz) und setze den Wachhund auf 2s.

Danke Dir für den Hinweis. Aber den String "ATmega644 Controller Boot" 
gibt er ja ordnungsgemäß auf dem Terminal Window aus, d.h. bis dahin 
lebt der Controller noch. Nur danach beibt er "hängen". Aber an dem " 
_asm__ __volatile_ ( ..." Code kann ich ja nichts ändern da er mit 
Assembler aus wdt.h vom Compiler erzeugt wird.

Ich werde Deinen Vorschlag trotzdem mal ausprobieren.

von Stefan F. (Gast)


Lesenswert?

Es geht darum, nachzuweisen, dass er nach 2 Sekunden (blinken) wirklich 
neu startet und erst danach irgendwo hängen bliebt.

Es wäre auch hilfreich, wenn du ganz am Anfang vom Init einen freien I/O 
Pin ganz kurz auf low-high-low setzt. Dieses Muster kann man mit einem 
Oszilloskop oder Logic Analyzer anzeigen und sehen, ob es sich 
regelmäßig (z.B. in Intervall des Watchdog Timeouts) wiederholt.

von Manfred L. (manni)


Lesenswert?

Εrnst B. schrieb:
> Nachtrag: Im Atmega644 - Datenblatt steht explizit, dass der
> Watchdog-Reset den Watchdog selber nicht abschaltet.
>>>  the device will be reset and the Watchdog Timer will stay enabled

Hei der Daus --> Sauerei:
den Satz im Datenblatt habe ich gelinde gesagt beim Lesen offensichtlich 
total verpennt. Jetzt ist mir klar, warum der Controller nach dem 
Watchdog Setzen Code sich nicht mehr zurück meldet --> weil ich den 
Watchdog im Code nicht mehr zurücksetze. So einfach ist die Sache, grrrr 
!

Bei den ATmega8 und ATmega32 Controllern war das nicht der Fall, die 
meldeten sich ordnungsgemäß zurück und der Watchdog war abgeschaltet.

Vielen Dank für diesen hilfreichen Kommentar !

Jetzt rufe ich einfach diese Methode auf und das funktioniert 
einwandfrei.
1
void Menu_SoftwareReset (void)
2
  {
3
  void (*reboot)() = 0x0000 ;
4
  (*reboot)();
5
  }

von Peter D. (peda)


Lesenswert?

Manfred L. schrieb:
> Jetzt rufe ich einfach diese Methode auf und das funktioniert
> einwandfrei.void Menu_SoftwareReset (void)
>   {
>   void (*reboot)() = 0x0000 ;
>   (*reboot)();
>   }

Quark, das macht keinen Reset, alle IO-Register bleiben gesetzt.

Im Datenblatt steht, wie man es richtig macht:
"WDE is overridden by WDRF in MCUSR. This means that WDE is always set 
when WDRF is set. To clear WDE, WDRF must be cleared first."

von S. Landolt (Gast)


Lesenswert?

Mir ist nicht klar, weshalb das ursprüngliche Programm nicht 
funktioniert - sollte da nicht im 15 ms-Takt diese Textzeile auf dem 
Terminal erscheinen, 115.2 kBd vorausgesetzt?

von Stefan F. (Gast)


Lesenswert?

Kommt drauf an wie lange die Initialisierung davor dauert. Siehe der 
vorherige Hinweis von Ernst B.

von S. Landolt (Gast)


Lesenswert?

Nun ja, 15-4.1-2.3 = 8.6 ms für die Initialisierung - erscheint mir 
viel.

von S. Landolt (Gast)


Lesenswert?

Jetzt habe ich nicht aufgepasst: wie kommt Ernst B. auf
> Startup-Time auf 4.1 ms (+16 Clocks) gestellt
? Das Fuse-Low-Byte steht auf 0xEF, dazu lese ich im Datenblatt '14CK + 
65 ms', oder?

von Stefan F. (Gast)


Lesenswert?

S. Landolt schrieb:
> Jetzt habe ich nicht aufgepasst: wie kommt Ernst B. auf
>> Startup-Time auf 4.1 ms (+16 Clocks) gestellt
> ? Das Fuse-Low-Byte steht auf 0xEF, dazu lese ich im Datenblatt '14CK +
> 65 ms', oder?

Kommt drauf an, ob es ein ATmega644 (65ms) oder ein ATmega644P (4.1ms) 
oder ein Atmega644PA (0ms) ist.

von S. Landolt (Gast)


Lesenswert?

Manfred L. schrieb:
> ich habe einen ATmega644

Und im Screen-shot steht ebenfalls nur 'ATmega644'. Woher dann dort der 
Text mit 'Start-up time ...' kommt, verstehe ich nciht.

von S. Landolt (Gast)


Lesenswert?

Entschuldigung: in der Zeile verrutscht. Das ist jetzt peinlich.

von Ron-Hardy G. (ron-hardy)


Angehängte Dateien:

Lesenswert?

laut Signatur 0x1E9609 ein ATMega644

von M. K. (sylaina)


Lesenswert?

Manfred L. schrieb:
> Hei der Daus --> Sauerei:
> den Satz im Datenblatt habe ich gelinde gesagt beim Lesen offensichtlich
> total verpennt. Jetzt ist mir klar, warum der Controller nach dem
> Watchdog Setzen Code sich nicht mehr zurück meldet --> weil ich den
> Watchdog im Code nicht mehr zurücksetze. So einfach ist die Sache, grrrr
> !

So ausführlich hab ich es nicht gesagt aber in meinem ersten Post hier 
habe ich dir bereits gesagt, dass dein Watchdog an ist. Und der würde 
versuchen in der main() (oder einem Äquivalent davon) zu starten...die 
du nicht hast...und daher auch nix passieren kann...

Manfred L. schrieb:
> Bei den ATmega8 und ATmega32 Controllern war das nicht der Fall, die
> meldeten sich ordnungsgemäß zurück und der Watchdog war abgeschaltet.

Mit Sicherheit, wenn das Programm genauso wie hier aufgebaut war, war 
das auch beim ATMega8 und ATMega32 so. Die CPUs sind nämlich identisch, 
die Teile unterscheiden sich (mehr oder weniger) nur in ihrer 
Peripherie. Aber vielleicht hattest du den obigen Code beim ATMega8 und 
ATMega32 ja doch in der main() stehen, dann war das Verhalten ganz 
gewiss anders. Aber nochmal, was du anscheinend auch nicht verstanden 
hattest: Ein cli() deaktiviert den Watchdog nicht...und das ist auch gut 
so ;)

von MaWin (Gast)


Lesenswert?

Die Bootsektor-Fuse BOOTRST ist nicht gesetzt. Deshalb springt er zur 
main statt zum Bootloader.

von M. K. (sylaina)


Lesenswert?

MaWin schrieb:
> Die Bootsektor-Fuse BOOTRST ist nicht gesetzt. Deshalb springt er zur
> main statt zum Bootloader.

Vor allem zu einer nicht existierenden main() ;)

von Εrnst B. (ernst)


Angehängte Dateien:

Lesenswert?

S. Landolt schrieb:
> Jetzt habe ich nicht aufgepasst: wie kommt Ernst B. auf
>> Startup-Time auf 4.1 ms (+16 Clocks) gestellt
> ? Das Fuse-Low-Byte steht auf 0xEF, dazu lese ich im Datenblatt '14CK +
> 65 ms', oder?

Das habe ich einfach aus dem Screenshot von manni übernommen, ohne da 
nochmal exakt im Datenblatt nachzuforschen…

von S. Landolt (Gast)


Lesenswert?

an Ernst B.:
Nochmals Entschuldigung; ich schrieb ja, dass ich mich da völlig vertan 
hatte.

von Εrnst B. (ernst)


Lesenswert?

S. Landolt schrieb:
> an Ernst B.:
> Nochmals Entschuldigung; ich schrieb ja, dass ich mich da völlig vertan
> hatte.

Nicht nötig. Ich lag eh falsch, hab das erste "K" bei den "16K CK" 
übersehen :)

von Manfred L. (manni)


Lesenswert?

M. K. schrieb:

Danke Dir für die weiteren Hinweise.

M. K. schrieb:
> Und der würde
> versuchen in der main() (oder einem Äquivalent davon) zu starten...die
> du nicht hast...und daher auch nix passieren kann...
Ich arbeite seit fast 20 Jahren mit den Dingern --> wieso soll ich keine 
main() haben ? Mein oben zietierer Code ist nur ein Schnipsel von ca 50 
KByte C-Source Code, den ich, wie schon gesagt, nicht hier im Beitrag 
einfügen / anhängen wollte, da er mit dem Problem nichts zu tun hat. Ja 
in der Tat: die 50 KByte haben wirklich eine main() und da springt er 
auch schön hin, wenn der Watchdog Reset ausgelöst wird.

Wie Du schon richtig bemerkt hast, ist der Watchdog leider dann immer 
noch aktiv und löst immer wieder einen Reset aus, weil ich ihn im 
Init-Teil des Source Codes nicht ausschalte. Und das war genau mein 
eingebauter Fehler, weswegen ich diesen Beitrag gestartet hatte.

M. K. schrieb:
> Mit Sicherheit, wenn das Programm genauso wie hier aufgebaut war, war
> das auch beim ATMega8 und ATMega32 so.

Nicht ganz, denn ich habe dies heute nochmals ausprobiert, d.h.: 
gleichen kurzen Test-Code auf ATmega644 und ATmega32 geflashed. Der 
Unterschied ist, dass der ATmega644 sich nicht mehr meldet, aber der 
ATmega32 meldet sich wieder und arbeitet ordnungsgemäß alles ab.

Es gibt demzufolge doch Unterschiede im Aufbau, wie z.B. die Fuse 
CKDIV8, die das Clock-Signal durch 8 teilt, wenn enabled. Das hat mich 
einen ganzen Abend gekostet, bis ich das endlich herausgefunden hatte.

M. K. schrieb:
> Aber nochmal, was du anscheinend auch nicht verstanden
> hattest: Ein cli() deaktiviert den Watchdog nicht...und das ist auch gut
> so ;)

Wie gesagt: ich bin kein Neuling und weiß, dass cli() nix mit dem 
Watchdog zu tun hat.

------------
Trotzdem vielen Dank für Deinen ersten Beitrag, der mich auf das Problem 
aufwerksam gemacht hat. Hoffe, man trifft sich mal wieder.

Grüße Manni

von S. Landolt (Gast)


Lesenswert?

> Trotzdem vielen Dank für Deinen ersten Beitrag, der
> mich auf das Problem aufwerksam gemacht hat.

Das verstehe ich nun nicht - war es nicht eher der erste Beitrag von 
Ernst B.?
  Der Unterschied ist doch, dass in der ATmega8-Generation der 
Watchdog-Reset den Watchdog abschaltet, beim ATmega644 bleibt er aktiv.

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.