Moin,
ich stehe gerade vor einem für mich völlig unverständlichen Problem.
Bei mir verursacht die _delay_ms() Funktion plötzlich einen ständig
wiederholten Reset am ATmega328.
Codeausschnitt:
1
lcd_init(LCD_DISP_ON);
2
lcd_clrscr();
3
lcd_gotoxy(0,0);
4
lcd_puts("UI-Logger-Solar");
5
//Warten damit der OpenLog initialisiert ist
6
_delay_ms(250);
7
lcd_gotoxy(15,0);
8
lcd_putc('9');
9
// wdt_reset();
10
_delay_ms(250);
11
lcd_gotoxy(15,0);
12
lcd_putc('8');
13
// wdt_reset();
14
_delay_ms(250);
15
lcd_gotoxy(15,0);
16
lcd_putc('7');
Das passiert aber nur wenn ich die Schaltung "frisch" an die Versorgung
anklemme. Sobald ich einmal einen Reset auslöse, oder den Chip neu
flashe funktioniert alles.
Nehme ich die delays raus geht es auch. Nun wird es besonders schräg:
Setze ich ein delay vor den obigen Bereich resettet das Programm bei dem
delay. Lasse ich den Abschnitt wie oben, dann läuft der Zähler runter
(geht bis 0) und dann erfolgt der Reset.
- WDT ist aus. Habe es aber auch mit WDT probiert.
- Der Wert für die Funktion spielt keine Rolle, habe ab 1ms vieles
probiert.
- Verschieden Werte für die Optimierung habe ich auch probiert
Es hat die ganze Zeit funktioniert und plötzlich nicht mehr! Ich habe
versucht möglichst genau die letzte Änderung auszukommentieren, aber der
Reset bleibt. Leider weiß ich nicht genau ab welcher Änderung es
angefangen hat, weil es beim neu flashen ja nicht auftritt.
Dirk S. schrieb:> WDT ist aus. Habe es aber auch mit WDT probiert.
Bist du dir sicher?
Wenn der Wachhund einmal gebissen hat, muss man ihn explizit beim Booten
bedienen (WDRF zurücksetzen), ansonsten bleibt er bis zum nächsten
Powercycle aktiv.
Wie arbeitet delay?
Wann tritt der reset auf? (Hast du ein oszi/LSA? Dann vorher Pin wackeln
Was passiert nach Zähler=0?
Was meinst Du mit "wenn ich reset auslöse"? Den delay-reset oder per
Pin? Tritt es nur nach Power-on auf? -> Reset-Beschallung
Welche Funktionen triggern den wdt?
Stromaufnahme/Begrenzung?
Das geht ja schnell.
Es tritt nur auf wenn die Versorgung weg war. Nach einem Reset per Pin,
oder einem read vom programmer ist es weg. Das ist für mich ja der
zentrale Knackpunkt. Weil ab dem Reset alles sauber läuft...
Der Wert des delay macht keinen Unterschied.
Ich habe nur eine minimale Programmierumgebung mit im Weihnachtsurlaub
:-)
Oszi etc. sind zu Hause im Keller.
Auch wenn ich den WDT korrekt bediene tritt der Reset beim ersten Aufruf
von _delay_ms() auf, allerdings nicht wenn die weiteren Aufrufe im
oberen Code-Ausschnitt da sind.
Stromaufnahme ist okay, ein DMM habe ich dabei.
So, nun habe ich den WDT aktiviert und setze ihn in nicht zurück.
Nach dem flashen startet das Programm, geht sauber in die Hauptschleife
und nach einiger Zeit löst der Wachhund aus. So soll es sein.
Trenne ich nun die Versorgung, dann läuft der Countdown durch und es
erfolgt der Reset weit vor dem WDT.
Setzte ich nun wdt_reset() dazwischen ändert sich nichts!
1
intmain(void)
2
{
3
wdt_reset();
4
/* Start timed sequence */
5
WDTCSR|=(1<<WDCE)|(1<<WDE);
6
/* Set new prescaler(time-out) value */
7
WDTCSR=(1<<WDE)|(1<<WDP3);
8
9
DDRB=0b00111111;
10
DDRC=0b00110000;
11
DDRD=0b11111110;
12
13
SETBIT(PORTB,1);
14
SETBIT(PORTB,2);
15
16
SPCR=(1<<SPE)|(1<<MSTR);//Enable SPI Master
17
18
UBRR0H=(unsignedchar)(11>>8);//Baudrate setzen bei 3,6864 MHz: 23=9600; 11=19200
Nochmal,
welche Fuse-Bits sind gesetzt, ist BOD Level eingestellt?
Alle Kondensatoren, i.A. 100nF verbaut?
Alle Vcc, AVcc und (AGnd) Gnd angeschlossen?
Wie weich ist die Versorgungsspannung an Vcc?
Sleep Einstellungen machen keinen Unterschied, hatte ich schon komplett
auskommentiert.
Der Code ist derweil etwas wild, da ich am rumprobieren bin.
Anbei der Schaltplan.
Und wie gesagt: Es hat die ersten Tage funktioniert, heute habe ich
weiter gemacht und nun tritt es auf. Da es nur bei einem Kaltstart
passiert habe ich es erst im Laufe des Tages bemerkt.
Werde es jetzt weiter reduzieren...
Dirk S. schrieb:> Trenne ich nun die Versorgung, dann läuft der Countdown durch und es> erfolgt der Reset weit vor dem WDT.
Eventuell mal die Brownout Detection deaktivieren bzw. herabsetzen.
Es kann unter Umständen sein das das Display wenn es noch nicht
initialisiert ist deutlich mehr Strom zieht als deine Versorgung
hergibt?
Karl M. schrieb:> Nachfrage,>> ist es ein ATmega328 oder ein ATmega328p?> Da gibt es Unterschiede.
ATmega328, AtmelStudio ist mit der Signatur zufrieden...
Da sind noch Antworten ausstehend,
Und dann wird noch im Register UCSR0B der "RX Complete Interrupt Enable"
und ich sehe keinen Interrupt Routine dafür.
Warum?
Dirk S. schrieb:> Karl M. schrieb:>> Nachfrage,>>>> ist es ein ATmega328 oder ein ATmega328p?>> Da gibt es Unterschiede.>> ATmega328, AtmelStudio ist mit der Signatur zufrieden...
Das meine ich nicht, es gibt zwei Datenblätter!
Mal sehen ob das klappt.
Ich versuche ein mp4-Video hochzuladen auf dem das Verhalten zu sehen
ist.
Erst die Dauerschleife mit dem ungeklärtem Reset nach dem Countdown,
dann ein "read" mit dem AtmelICE und es läuft (bis der Wachhund
anbeisst).
Nach einem Kaltstart hängt es wieder...
Hallo,
Was passiert ist alles durch die Hardware, das gesamte Programm und
dem aktivierten WDT per Fuse-Bit erklärbar.
Aber da Du nicht alles offenlegen möchtest und auch immer wieder von
anderen Softwareversionen und Tests schreibst, weiß niemand - außer Dir
- genau, was zusammen hängt.
Versuche mal deine Posts aus unserer Sicht (Informationsstand) zu sehen.
Das alles ist Vergleichbar mir eine Buchstabensuppe.
Hallo Karl,
was Du schreibst mag ja stimmen, aber bis dort kommt das Programm
überhaupt nicht nach einem Kaltstart und nach einem Reset funktioniert
es einwandfrei!
Auch wenn es mit Sicherheit alles andere als sauber programmiert ist.
Thomas E. schrieb:> Karl M. schrieb:>> Das meine ich nicht, es gibt zwei Datenblätter!>> Nein.>> ATmega48A/PA/88A/PA/168A/PA/328/P sind in einem Datenblatt.
Hallo,
in der Atmel Zeit war dies wie folgt:
Beitrag "Re: Atmega 328 oder 328P ?"
Karl M. schrieb:> in der Atmel Zeit war dies wie folgt:> Beitrag "Re: Atmega 328 oder 328P ?"
Was willst du mit diesem uralten Thread aussagen? Dass du lange nicht
mehr auf einen Kalender geguckt hast?
@ Dirk
Hm. Die Beschreibung ist leider wirklich sehr schwer verständlich,
teilweise unverständlich und unklar. Schwierig da was Definitives zu
sagen.
Allerdings gibt es diese Reset-Probleme in Zusammenhang mit dem delay
immer wieder und - wenn ich mich recht entsinne - in den meisten Fällen
liegt es nicht am delay selbst.
Ich weiß, dass ist schwer zu verstehen, wenn doch verschiedene Varianten
mit und ohne delay unterschiedliches Verhalten zeigen. Dennoch ist es
oft wahr. Lies mal ein paar von den erwähnten Threads.
Dummerweise kann man häufig nicht gleich den Finger auf den Punkt legen,
der ausschlaggebend ist und in Verbindung mit dem delay ein Problem
darstellt.
Daher die Hinweise auf sonstige Fehler, die scheinbar nichts damit zu
tun haben, was Du als Ursache vermutest.
Wenn man nicht so recht weiß, dann ist das einer der beiden Erfolg
versprechenden Ansätze.
1. Probleme beseitigen, auch wenn sie scheinbar abseitig sind - nichts
mit der eigenen Vermutung zu tun haben. (Fehler sind ohnehin Fehler und
müssen irgendwann sowieso beseitigt werden).
2. So viel wie möglich und detaillierte Information geben. Hier
insbesondere Schaltplan, Beschreibung der Stromversorgung,
Compileroptionen.
Manchmal waren es auch hohe Lasten, wie Relais, welche die
Stromversorgung beeinflussten und die delays haben nur den zeitlichen
Ablauf verändert - waren aber nicht selbst verantwortlich.
Schwierig die Sache, aber wenn Du es über Dich bringen kannst, dann
folge einmal den Hinweisen, auch wenn sie Dir zuerst sinnlos vorkommen.
Versprechen kann ich natürlich nichts, aber die Erfahrung zeigt, dass
das in die richtige Richtung führt.
Da ist wohl etwas Wahres dran.
Ich habe nun die UART Ausgabe auskommentiert und der Fehler ist weg.
Und das obwohl diese an der Problemstelle im Programm noch nicht
aufgerufen wurde...
Dirk S. schrieb:> Und das obwohl diese an der Problemstelle im Programm noch nicht> aufgerufen wurde...
Ist das tatsächlich so, oder glaubst du das nur?
Schalte zur Kontrolle innerhalb der Funktion eine LED an, dann bist du
sicher.
Dirk S. schrieb:> Da ist wohl etwas Wahres dran.> Ich habe nun die UART Ausgabe auskommentiert und der Fehler ist weg.> Und das obwohl diese an der Problemstelle im Programm noch nicht> aufgerufen wurde...
Wie ist RX extern beschalten? Da du den Pullup nicht aktiviert hast und
den RX-Int aktiviert, aber keine ISR, hast könnte bei offenem Eingang
schon mal was triggern.
Sascha
Genau, Sascha!
Ich Trottel!
Das Problem war der OpenLog, oder besser der Typ, der den OpenLog
benutzt.
Und Karl hatte auch recht...
Der OpenLog initialisiert sich nur nach dem Trennen der Versorgung und
gibt seinen Status aus. Mit der UART Konfiguration hat er einen
Interrupt ausgelöst der keine ISR hat...
Euch einen guten Rutsch :-)
Dirk S. schrieb:> Ich Trottel!
Nun, einfach zur Gewohnheit machen, dass du für jedes Interruptbit, was
du irgendwo in einem Register aktivierst, sofort irgendwo eine
(zumindest leere) ISR hinschreibst. Dann weißt du später, dass du da
noch was ausfüllen musst.
Schön, dass ihr's gefunden habt.
Jörg W. schrieb:> Dirk S. schrieb:>> Ich Trottel!>> Nun, einfach zur Gewohnheit machen, dass du für jedes Interruptbit, was> du irgendwo in einem Register aktivierst, sofort irgendwo eine> (zumindest leere) ISR hinschreibst. Dann weißt du später, dass du da> noch was ausfüllen musst.
Ich würde es sogar umgekehrt machen: Den Interrupt überhaupt erst
aktivieren, nachdem ich die dazugehörige ISR geschrieben habe.
Schließlich habe ich dann erst ein Interesse daran, dass der Interrupt
auch aktiv ist.
Karl M. schrieb:> Und hier knallt es entsprechend auch durch die unterschiedlichen> Datentypen und einem Aufruf in einer Interrupt Service Routine.> void ausgabe(char text[16]);
ausgabe ist nicht reentrant, da es eine globale Variable beschreibt.
Außerdem darf man keine Stringliterale übergeben, da es auch in den
übergebenen String schreibt.
Die fehlende Reentranz kann dazu führen, dass bei gleichzeitiger
Ausführung aus dem Hauptprogramm und der ISR über das Stringende hinaus
geschrieben wird und damit andere Speicherinhalte überschrieben werden.