Hallo werte Gemeinde,
ich habe auf einem Arduino etwas mit dem Watchdog herumexperimentiert.
Bis er sich irgendwann nicht mehr abschalten ließ. Die Programmierung
von dem Ding ging dann auch nicht mehr. Die funktioniert über einen
Bootloader, der sich seinen Code aus einem USB-zu-RS232 Wandler zieht.
Also habe ich versucht back to the roots zu gehen, meinen avr910
Programmer angehängt, die fusebits für den Bootloader entfernt und
programmiere den Arduino jetzt mit avrdude und dem avr-gcc. Code kann
ich aufspielen.
Jetzt zu folgendem Code:
1 | #define F_CPU 16000000UL
|
2 |
|
3 | //HEADER
|
4 | #include <avr/io.h> // AVR Register und Konstantendefinitionen
|
5 | #include <inttypes.h> // erweiterte stdint.h
|
6 | #include <avr/interrupt.h> // Anpassung des Interruptregisters
|
7 | //#include <util/delay.h> // Header mit definierten Zeitverzögerungen
|
8 | #include <avr/wdt.h> //Watchdog
|
9 | #include "schaltparameter.h" // Parameterdatei
|
10 |
|
11 |
|
12 | void wdt_init(void) __attribute__((naked)) __attribute__((section(".init1")));
|
13 |
|
14 | void wdt_init(void)
|
15 | {
|
16 | cli();
|
17 | wdt_reset();
|
18 | MCUSR = 0;
|
19 | WDTCSR |= (1 << WDCE) | (1 << WDE);
|
20 | WDTCSR = 0x00;
|
21 | wdt_disable();
|
22 | DDRB = 0xFF;
|
23 | PORTB = WDTCSR;
|
24 |
|
25 | return;
|
26 | }
|
27 |
|
28 | int main()
|
29 | {
|
30 | //setup();
|
31 |
|
32 | while(1)
|
33 | {
|
34 | cli();
|
35 | wdt_reset();
|
36 | MCUSR = 0;
|
37 | WDTCSR |= (1 << WDCE) | (1 << WDE);
|
38 | WDTCSR = 0x00;
|
39 | wdt_disable();
|
40 | DDRB = 0xFF;
|
41 | PORTB = WDTCSR;
|
42 | }
|
43 |
|
44 | return 0;
|
45 | }
|
Das ist ein Auschnitt aus dem, wa sich eigentlich programmieren will,
was aber alles auskommentiert ist. schaltparameter.h enthält nur
Konstantendefinitionen.
wdt_init() ist kopiert aus diesem Forum. Da hatte jemand das Problem,
dass der Watchdog aktiv bleibt, wenn der uC startet. Wenn die
Initialisierungen zu lange brauchen, löst der wd aus, bevor er im
Usercode deaktiviert werden kann. So sollte das nicht mehr auftreten.
Die Mainloop deaktiviert den Watchdog mit der Bibliotheksfunktion und
von Hand mit Registerzugriffen (feste Sequenz mit WDCE (Watchdog change
enable) wurde wie im Datenblatt eingehalten).
Dann gibt sie den Inhalt des Watchdogkonfigurationsregisters auf PORTB
aus, den schaue ich mir mit einem Logic-Analyzer an:
Direkt nach dem Aufspielen vom Programm lesen sich alle Bits des
Registers zu null. Erst nach einem Power-Reset ist das
Watchdog-Enablebit plötzlich gesetzt, obwohl es kurz zuvor zurückgesetzt
wird. Das unterste Prescalerbit ist auch gesetzt. Der Watchdog ist also
doch aktiv. Er löst aber nicht aus (ich vermute Mal, weil er immer
wieder doch kurz deaktiviert wird)
Wenn ich das Deaktivieren vom Watchdog in der Mainloop auskommentiere
und nur das Statusregister in PORTB schreibe (die Deaktivierung in
wdt_init() bleibt aber im Code), dann löst der Watchdog auch aus. PORTB
flackert. Die Zeit vom Watchdogprescaler findet sich im Signal wieder.
Compileroptimierung ist aus, das Highfuse ist D9, was die
Standardeinstellung ist, in der das fusebit WDTON true, also
unprogrammiert ist.
Hat jemand eine Idee, wie ich den Watchdog deaktivieren kann, ohne dass
er selbstständig wieder angeht?
Vielen Dank