PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Watchdog verbeißt sich unbegrenzt (RNControl, mega1284P)



oberallgeier
23.06.2014, 13:01
Bitte um Hilfe zu meinem Watchdog-Reset. Ich habe bisher keine funktionierende Erfahrung mit Watchdog, die paar Anleitungen haben bisher nicht geholfen - zum Beispiel forumswissen (http://www.rn-wissen.de/index.php/Avr-gcc#Reset_ausl.C3.B6sen) oder dies hier (https://www.roboternetz.de/community/threads/50068-Problem-mit-Watchdog-gel%C3%B6st).

Umgebung: mega1284P auf RNControl, 20 MHz, AVRStudio4, Programmer Pololu USB AVR Programmer, Labornetzteil, etliche Peripherie - andere Platinen über UART und I²C - die aber im Test alle abgeklemmt sind ausser UART und LCD auf PortB.

Der Watchdog wird durch avr/wdt.h eingebunden und als erste ausführbare Codezeile im main disabled. Auslösung durch ein Dreierpaket RC-5-Code aus (IR-FB-) Tastencode "0","0","0".

Codeauszüge:

//...
//
#include <stdlib.h> //
#include <avr/io.h> //
#include <avr/interrupt.h> //
#include <avr/wdt.h> //
// - - - - - - - - - - - - - - - -
// CPU wird NICHT definiert im AVRStudio Current Configuration Options
// wird ab hier von twimaster*.c u. evtl. anderen Libs benötigt
#define F_CPU 20e6//
================================================== =========================== =
// === HAUPTProgramm ================================================== ======== =
// Initialisierungen, LED1 kurzblinken als Signal für Programmstart,
// Ausgabe des Identifizierungsstrings per UART
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
int main(void) //
{ //
uint8_t i; //
uint16_t ADC_ist; //
uint16_t l = 500; // Laufvariable für ADC-Abschaltung unten
....
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Anmerkung: bishier nur Includes, Defines, Deklaratonen und Definitionen
wdt_disable(); //
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Ports+Pins als Ein- (0) od. Ausgänge (1) konfigurieren, Pull Ups (1) aktivieren
// A = Ausgang, E = Eingang ohne , EU = Eingang MIT PullUp
// - - - - - - - - - - - - - - - -
DDRA = 0b00000000; // siehe aktuell oben oder Fortschritt/R2D2
PORTA = 0b00010000; // Für ADC: PA6+PA7 = ADC-Eingang ##>> OHNE Pullup !!
//
DDRB = 0b11111011; // siehe aktuell oben
PORTB = 0b01000000; // L1g on
//
DDRC = 0b11101100; // PC0 .. 7 (!) aktiv bei mega1284 !, PC0=SCL, PC1=SDA
PORTC = 0b11110000; // PC4 ist Eingang für RC-5 (war PB2)
//
DDRD = 0b11111111; // -> siehe unter DDRB
PORTD = 0b00000000; // Ports/Pull Ups (1) aktivieren
//
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
//for(i=0; i<10; i++) // gLED2(PB5) blinken lassen bevor Interrupts erlaubt sind

Und so wird irgendwann durch Eingabe per RC-5 -- drei Bytes der Zifferntaste "0" -- der Watchdog ausgelöst:

if ( iBB16 == 0 ) // bei "000" WatchdogReset auslösen
{ //
// #include <avr/wdt.h>
cli(); // Interrupts global abschalten
wdt_enable (WDTO_15MS); // Watchdog aufziehen auf 15ms
while (1); // warten, bis er zubeisst...
}

Meine Programmierung basiert auf diesem Code (http://www.rn-wissen.de/index.php/Avr-gcc#Reset_ausl.C3.B6sen) aus dem RNW issen.

Der Betrieb des Programms läuft in einer zufälligen Testsequenz - verschiedene Aktionen und Ausgaben - sinnvoll. Der Watchdog wird wunschgemäß ausgelöst, nachdem der oben genannte Code "000" eingegeben und erkannt wurde. Danach läuft der Controller/die Platine nicht mehr (sinnvoll). Es dämmert nur eine LED vor sich hin. Drücken des /RESETknopfes oder [Read Signature] im AVR-Studio hilft nicht. Programmieren/Flashen ist nicht mehr möglich. Ein Wiederstart ist nur möglich durch Abklemmen des UART (RxD/TxD auf PD0 und PD1 über den Pololu-Programmer) und Abschalten der allgemeinen Versorgung.

Bitte um Hilfe und danke im Voraus.

markusj
23.06.2014, 15:11
Hast du dir die Dokumentation der avr-libc zu dem Thema angesehen? (avr/wdt.h)



Note that for newer devices (ATmega88 and newer, effectively any
AVR that has the option to also generate interrupts), the watchdog
timer remains active even after a system reset (except a power-on
condition), using the fastest prescaler value (approximately 15
ms). It is therefore required to turn off the watchdog early
during program startup, the datasheet recommends a sequence like
the following:

\code
#include <stdint.h>
#include <avr/wdt.h>

uint8_t mcusr_mirror __attribute__ ((section (".noinit")));

void get_mcusr(void) \
__attribute__((naked)) \
__attribute__((section(".init3")));
void get_mcusr(void)
{
mcusr_mirror = MCUSR;
MCUSR = 0;
wdt_disable();
}


mfG
Markus

Searcher
23.06.2014, 15:19
... Ein Wiederstart ist nur möglich durch Abklemmen des UART (RxD/TxD auf PD0 und PD1 über den Pololu-Programmer) und Abschalten der allgemeinen Versorgung.

Hallo,
Abschalten der Versorgung löscht auch den RAM. Ein RESET allein beläßt Variable auf ihrem Wert.
Könnte es jetzt sein, daß irgendwelche Variablen nicht korrekt initialisiert sind, vielleicht sogar die "iBB16" und der µC dann dauernd vom Watchdog rückgesetzt wird?

Gruß
Searcher

oberallgeier
24.06.2014, 07:54
Hast du dir die Dokumentation der avr-libc zu dem Thema angesehen? (avr/wdt.h) ...Au weija, Markus. Danke für den Hinweis. Da hab ich ein prächtiges Eigentor - selbst immer auf die Dokumentation hinweisen und dass man die auch lesen muss und nun ... Ok, ich habe die Erläuterungen im Forumwissen gelesen und den Code von dort übernommen (wider besseres Wissen - das hatte nämlich schon bei I²C nix gebracht - dort steht "Code ... geprüft ..." - aber Prüfung heißt ja nicht gleichzeitig "bestanden" *gg*).

Nun habe ich mal den Abschnitt 11.3 Watchdog Timer im Datenblatt für den m1284 überflogen, den Code in meiner Quelle rausgenommen und werde das in zwei Wochen mal ordentlich angehen. Komplett lesen, ein kleines Testprogramm - und dann sehn wa mal scho . . .

Searcher
24.06.2014, 19:39
... und der µC dann dauernd vom Watchdog rückgesetzt wird?
Vielleicht sollte ich näher erläutern, wie ich zu der Annahme komme:


Spannung vom System wird eingeschaltet (SRAM hat vor Programmstart irgendwelche Werte ungleich 0) und System (Programm) läuft wie gewünscht.
Von FB kommt "000" und durch Variable "iBB16" wird Watchdog ausgelöst.
Watchdog erzeugt einen Reset, der die I/O Register auf Defaultwerte zurücksetzt aber den SRAM unberührt läßt.
Das Hauptprogramm beginnt von vorne und die Variable "iBB16" könnte nun im SRAM auf der gleichen Stelle wie vorher liegen und dort den Wert 0 wie vor dem Reset erhalten -> neue Watchdogauslösung.
u.s.w. bis Spannung abgeschaltet wird.


Falls also nicht verhindert wird, das iBB16 nach Watchdogreset bzw nach wdt_disable(); ohne FB den Wert 0 hat, könnte ich mir den Ablauf also so vorstellen.

markusj
25.06.2014, 10:24
Das Hauptprogramm beginnt von vorne und die Variable "iBB16" könnte nun im SRAM auf der gleichen Stelle wie vorher liegen und dort den Wert 0 wie vor dem Reset erhalten -> neue Watchdogauslösung.

ibb16 scheint mir ein Funktionsparameter zu sein, aber unabhängig davon: Deine Theorie scheitert daran, dass der Startup-Code alle globalen/statischen Variablen nach jedem Reset gleich initialisiert, unabhängig davon ob es ein Power-On-Reset oder ein Watchdog-Reset war. Und alle Register (bis auf das Watchdog-Register) werden bei einem Reset durch den AVR selbst auf die Standardwerte zurückgesetzt.

mfG
Markus

Searcher
25.06.2014, 17:31
Deine Theorie scheitert daran, dass ..
:( Mist, mir gefiel sie und hatte bisher nur was zur Initialisierung von statischen Variablen gefunden. Jetzt, nach Deinem Post, find ich auch was zu den globalen. Eigentlich nutze ich Bascom, aber es ist immer wieder interessant anderen Sprachen zuzuhören und hoffentlich durchzublicken.

Gruß
Searcher

The Dude
24.07.2014, 01:30
Probiers mal hiermit, hatte das Problem auch schon, der Code legt den AssemblerCode der den Watchdog deaktiviert in die .init Sektion des Programms, das ist dann das allererste, was das Programm tut. Das Problem ist, das mit dem Reset des Controllers (durch den WDT) auch das Control-Register des WDT gelöscht wird und dieser nun auf 15ms eingestellt ist, das reicht manchmal nicht...

[/code]
void wdt_init(void) __attribute__((naked)) __attribute__((section(".init1")));

void wdt_init(void)
{
MCUSR = 0;
wdt_disable();
DDRA = (1<<PA0);
PORTA &= ~(1<<PA0);

return;
}
[/code]

sollte das Problem beheben, wo das im Programmcode landet ist egal, es wird so oder so ausgeführt

oberallgeier
02.04.2015, 10:50
Nach Monaten mit anderen Baustellen bin ich zurück beim Watchdog. (M)EIN Problem: bei laufendem LCD hängt sich der Controller nach reproduzierbaren 11:15 min auf . . . :-/

Folgende Codeschnippsel wurden erstellt als Zusatz/Einfügung bei sonst problemlosen (bis auf den LCD-Bug) Steuerungsablauf. Damit war ein Test geplant, ob erstmal ne quick´n dirty Lösung per WDT möglich wäre


// Im Main nach Includierung der
#include <avr/interrupt.h> //
#include <avr/wdt.h> //
// Mainmodul
//..

Isecundn = 1; // Sekundenzähler max 9Stunden - NUR hier nullen
Itmr_RES = 0; // Sekundenzähler für RESET

wdt_init( );

TC2TMR_init(); // Init Timer/Cntr2-Interrupt 20 kHz/50 µsec tmr
// . . .
// Ende Main
//

// Im getrennten Timermodul nach erreichen einer Sekunde:
// . . .
Itmr_RES ++; // Resettimer wegen LCD-Fehlfunktion
if ( Itmr_RES == 30 ) // Zeit erreicht ??
{ //
Itmr_RES = 0; // Setze Timer vorsichtshalber zurück
wdt_enable( 1);
} // Ende if ( Itmr_RES ==
//




// ================================================== =========================== =
//void wdt_init(void) __attribute__((naked)) __attribute__((section(".init1")));
// ...
// ENde timer-Funktion

void wdt_init(void)
{
MCUSR = 0;
wdt_disable();
DDRA = (1<<PA0);
PORTA &= ~(1<<PA0);

return;
}
// ================================================== =========================== =

Das funktionierte mit seltsamer Konsequenz: es lief EINMAL ab, stoppte nach dreissig Sekunden, seit der Zeit geht garnix mehr. Nur die Heartbeat-LED - hier üblich auf PC6 - ging auf halbe Kraft bzw. 90 Hz.

Seltsam: Flashen - mit Verify - ist möglich, Fuses setzen und lesen ist möglich. Flashen eines früher sauber lauffähigen Programms ist möglich - aber die Funktion bleibt wie vorher: Heartbeat-LED auf halbe Kraft bzw. 90 Hz. Ansonsten läuft das früher sauber lauffähige Programm nicht :.-.((

Frage: hat jemand von Euch einen ungefähren Tip was los ist?

Danke im Voraus