PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Problem mit Watchdog [gelöst]



damfino
26.09.2010, 16:40
Ich kämpfe jetzt gerade mit dem Watchdog, und zwar gibt es das Problem dass er, wenn er angeschlagen hat, in einer Endlos Reset Schleife gefangen ist.
Ich hab den empfohlenen Code aus der AVR Lib eingefügt mit dem man den Watchdog schnell abschalten kann, nutzt aber nichts:

unsigned char 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();
}

Und am Anfang von main steht das:

if (mcusr_mirror & (1 << WDRF))
{
LED_gr_ein;LED_rot_ein;
lcd_gotoxy(0,0);lcd_puts_p(PSTR("!WATCHDOG! "));
Motor_li_stop();Motor_re_stop();Mower_faststop();
while(1);
}

else wdt_enable(WDTO_1S);

sei();

Ist ein Atmega644 mit 16Mhz mit max Startup Zeit für den Quarz. Die Watchdog Fuse ist deaktiviert, habs auch schon mit und ohne Fuse getestet.

Was kann man noch probieren?

LG!

damfino
14.11.2010, 21:37
Hat da keiner eine Idee?

Im AVR Studio mit Simulator 1 kommt es wie auch in der Realität zu endlosen Resets, mit Simulator 2 funktioniert der Code.

Und warum will der Atmega644 nicht?

LG!

021aet04
14.11.2010, 22:04
Kannst du den gesamten Code posten. Wäre leichter den Fehler zu finden.

MfG Hannes

damfino
15.11.2010, 17:29
Ich glaube kaum dass 4500 Zeilen für mehr Übersicht sorgen, deshalb hier genau die Teile die das Programm beim Start durchläuft


Code Anfang:


#ifndef F_CPU
#define F_CPU 16000000
#endif

#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdlib.h>
#include <lcd.h>
#include <math.h>
#include <string.h>
#include <avr/pgmspace.h>
#include <i2cmaster.h>
#include <avr/eeprom.h>
#include <avr/wdt.h>


unsigned char mcusr_mirror __attribute__ ((section (".noinit"))); // Watchdog ausschalten

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

#define LED_gr_ein (PORTB &= ~(1<<PB0))
#define LED_gr_aus (PORTB |= (1<<PB0))
#define LED_rot_ein (PORTB &= ~(1<<PB1))
#define LED_rot_aus (PORTB |= (1<<PB1))



danach kommen defines und globale Variablen, kein setzen von Registern!

Diese Interrupts sind definiert:


/* Interrupts */
volatile unsigned char timecount;
volatile short radcount,i_summe,v_alt;
volatile unsigned char odo_messer,odo_m;

ISR(ISR_Timer2)
{
timecount++; if (timecount>250) timecount=250;
radcount++; if (radcount>10000) radcount=10000;

//static short ;
short v, mowersp;

if (timecount==25)
{timecount++;
odo_m=odo_messer;
odo_messer=0;

if (messer_aus==0)
{
v = (short)(drehzahl-odo_m); //Vergleich
i_summe = i_summe + v; //Integration I-Anteil //mit "vergessen": (i_summe*9)/10 + v;
if (i_summe < -1280) i_summe = -1280; //Begrenzung I-Anteil
if (i_summe > 1280) i_summe = 1280;

// mowersp=1*v+3*(i_summe*25)/100+1*((v -v_alt)*100)/25; // stabile Ausgangsbasis
// mowersp=(3*v+5*((i_summe)/4)+3*((v -v_alt)*4)+320)/4; // 320 (320/4=80) als Startwert, alles /4 für geringe PWM Stufung
mowersp=(5*v+3*((i_summe)/4)+5*((v -v_alt)*4)+560)/7;
v_alt=v;

if (mowersp < 40) mowersp = 40; //Begrenzung Stellgröße
if (mowersp >= 255) mowersp = 255;

mowerspeed=(unsigned char)(mowersp);
Mower=mowerspeed;
}
}
}




ISR(INT2_vect)
{odo_messer++;}


ISR(PCINT0_vect)
{
radcount=0;
}

SIGNAL (__vector_default) // falsche Interrupt erkennen, abbrechen
{cli();PORTC &= ~( (1<<PC2) | (1<<PC3) );PORTC &= ~( (1<<PC4) | (1<<PC5) );PORTC |= (1<<PC6) | (1<<PC7);
lcd_gotoxy(0,0);lcd_puts_p(PSTR("Bad Interrupt "));
while(1);
}



und hier der Anfang von main:



int main(void)
{
//char buffer[10];
short richtung_temp, richtung_soll,x_temp,y_temp;
char korr_l,korr_r, modus;
unsigned short speed_li, speed_re, felder,speed_fakt; //
unsigned char x,y, z, sekunde, sekk, sekkk,sek_f, min,minstd,temp; //, odo_m, sek_gps

modus=0;

richtung_soll=1;korr_l=0;korr_r=0;
sekunde=0;sekk=0;sekkk=0;sek_f=0; min=0;minstd=0;
radcount=0;odo_m=0;
x_temp=0;y_temp=0;


//odo_li=14;odo_re=4;pos_x=2000;pos_y=1800;richtung= 4700;Pos_odo(0); // Odometrie Test für Simulator
//pos_x=300;pos_y=1300;GotoXY(1000,1300,1); // Test Navi

// Watchdog
LED_rot_aus;LED_rot_aus;

// Watchdog-Reset
if (mcusr_mirror & (1 << WDRF))
{
LED_gr_ein;LED_rot_ein;
while(1);
}

else wdt_enable(WDTO_1S);



sei(); //Interupt ein

while(1); //Test für Watchdog

init(); //Porteinstellungen, PWM, LCD


lcd_clrscr();
i2c_init();


Hier habe ich die Wachtdog Abfrage ganz am Anfang eingebaut, hier extra für den Test noch bevor die einzelnen Register für I/O, PWM, LCD, USART; TWI etc gesetzt werden.

Und genau dieser Code funktioniert im Simulator, nach 1s schlägt der Watchdog an, beim Neustart erkennt er das WDRF gesetzt ist, "schaltet" die LED's ein und bleibt wie er soll dort in der while Schleife.

Am Atmega funktioniert das nicht, sieht so aus als hängt er in endlosen Resets fest. Anscheinend wird der Watchdog am Anfang nicht ausgeschalten, aber das soll genau dieser Beispielcode aus der gcc lib erledigen.

LG!

damfino
16.11.2010, 18:40
Hab den Fehler gefunden, weil es immer heisst die Watchdog Erkennung ganz am Anfang des Programmes einzubauen war er einfach zu weit vorne.