Hallo,
seit ein paar Monaten habe ich einen ATmega644P in Benutzung.
Das Programm (in c) ist sehr umfangreich und für meine -allgmein
gehaltene- Frage nicht erforderlich.
Deswegen fasse ich mich kurz:
Welche Umstände können alle dazu führen, dass der ATmega644P während des
Betriebs plötzlich neu startet?
Ich hänge nun schon länger an diesem Problem, welches ich beim ATmega32
nicht hatte (auch mit gekürzter Version dieses Programmes...)
Als Möglichkeit habe ich den Watchdog deaktiviert, was aber keine
Wirkung zeigte:
1
voidWDT_off(void){
2
MCUSR&=~(1<<WDRF);
3
WDTCSR|=(1<<WDCE)|(1<<WDE);
4
WDTCSR=0x00;
5
}
Was kann noch zu einem Reset führen?
Spannungs-/Strom-versorgung ist stabil bei 5.0V, 16MHz-Quarz, Display,
Taster, LEDs, Nichts was Spannungsspitzen oder der gleichen zurückwerfen
könnte.
Ich freue mich über jede Antwort bzw Vorschlag/Idee!
Vielen Dank
Gruß Tobias
Tobias Gläser schrieb:> Hallo,>> seit ein paar Monaten habe ich einen ATmega644P in Benutzung.> Das Programm (in c) ist sehr umfangreich und für meine -allgmein> gehaltene- Frage nicht erforderlich.
sagst du
> Deswegen fasse ich mich kurz:> Welche Umstände können alle dazu führen, dass der ATmega644P während des> Betriebs plötzlich neu startet?
Vieles.
Spannungsversorgung
Programmfehler
Bei Programmfehler:
Interrupt freigegeben aber keine ISR dafür (ist ein beliebter Fehler).
Array Überläufe, die den Stack so zerschiessen, dass der µC ins Nirwana
springt und irgendwann wieder am Programmanfang auf die Füsse fällt.
Mit Pointer kann man dasselbe Spielchen treiben
> Als Möglichkeit habe ich den Watchdog deaktiviert, was aber keine> Wirkung zeigte:>
1
voidWDT_off(void){
2
>MCUSR&=~(1<<WDRF);
3
>WDTCSR|=(1<<WDCE)|(1<<WDE);
4
>WDTCSR=0x00;
5
>}
Hattest du denn den Watchdog überhaupt eingeschaltet?
Ok, nur als Aufzählung:
Hardware:
-Instabile Stromversorgung (wirf mal mit nem Oskar nen Blick drauf)
-undefinierter Pegel am Reset-Eingang (über 10k nach vcc legen)
-fehlende Abblock-kondensatoren an vcc
-Spannungsspitzen
Software
-auslösung des Watchdog (ok, den hast du disabled)
-Pufferüberläufe
-Stack under- oder overflows
-Sprung in nicht vorhandene Programmadressen
Ich hatte gerade beim 644p in Verbindung mit avr-gcc auch mal das
Problem, das Zugriffe auf das EPROM einen Reset ausgelöst haben. Hier
half eine aktualisierung des avr-gcc weiter.
Vielen Dank für die schnellen Antworten!
Karl heinz Buchegger schrieb:> Bei Programmfehler:> Interrupt freigegeben aber keine ISR dafür (ist ein beliebter Fehler).> Array Überläufe, die den Stack so zerschiessen, dass der µC ins Nirwana> springt und irgendwann wieder am Programmanfang auf die Füsse fällt.> Mit Pointer kann man dasselbe Spielchen treiben
Array (und mögliche Überläufe) und Pointer werde ich alle nochmal
Prüfen.
Gibt es eine Möglichkeit alle Interrupts komplett zu sperren? Habe da
nichts gefunden was mir weiterhilft. Verwendet habe ich keine. Auch
keine Timer.
> Hattest du denn den Watchdog überhaupt eingeschaltet?
Habe mit ihm rumgespielt, aber letztendlich ist er nun garnichtmehr im
Programm und auch per Fuses deaktiviert.
hacker-tobi schrieb:> Hardware:> -Instabile Stromversorgung (wirf mal mit nem Oskar nen Blick drauf)> -undefinierter Pegel am Reset-Eingang (über 10k nach vcc legen)> -fehlende Abblock-kondensatoren an vcc> -Spannungsspitzen
Werde meinen "Oskar" mal dran hängen, vielleicht hab ich ja doch was
übersehen was stören könnte.. Abblock-C ist überall vorhanden, 10k am
Reset ist auch vorhanden.
> Software> -auslösung des Watchdog (ok, den hast du disabled)> -Pufferüberläufe> -Stack under- oder overflows> -Sprung in nicht vorhandene Programmadressen
Pufferüberläufe? Wie hab ich das zu verstehen?
Bei Stack-Fehler muss ich alle mal kontrollieren.
Sprünge sind alle nur durch Funktionsaufrufe realisiert. Bei Fehlern da
würde der Comiler theoretisch schreien.
> Ich hatte gerade beim 644p in Verbindung mit avr-gcc auch mal das> Problem, das Zugriffe auf das EPROM einen Reset ausgelöst haben. Hier> half eine aktualisierung des avr-gcc weiter.
Da werde ich mich mal weiter Informieren.
Gute Tipps, vielen Dank, ich melde mich nach allen Prüfungen!
Gruß Tobi
Tobias Gläser schrieb:> Gibt es eine Möglichkeit alle Interrupts komplett zu sperren? Habe da> nichts gefunden was mir weiterhilft.
cli();
Tobias Gläser schrieb:> Pufferüberläufe? Wie hab ich das zu verstehen?
Z.B. indem Du mehr Daten in ein Array schreibst, als Du durch die
Dimensionsangabe dafür an Speicher reserviert hast. Dann wird
irgendwelcher anderer Speicher überschrieben => kann zum Reset führen
(Arrayüberläufe, hatte Karl Heinz schon geschrieben)
Matthias
Hallo,
Danke für die Hilfen und Vorschläge,
ich habe nun schon einige der vorgeschlagenen Problemlösungen versucht
und kann das Problem vermutlich einschränken.
Der Reset startet nur bei bestimmten Aktionen im Programm (~800 Zeilen
noch betroffen). Ich werde nun mal versuchen Teil für Teil
auszukommentieren um zu sehen ob eines der Unterprogramme/Funktionen
speziell den Fehler verursacht.
Die Spannungen stehen stabil, die Arrays habe ich alle minimal
überdimensioniert (z.B. 10 Plätze für 8 Werte falls mal eine Schleife
aus Versehen auf 9 Werte zugreifen möchte...), Rückgabewerte gibts kaum
und cli() hatte auch keine Wirkung.
Abblockkondensatoren sind vorhanden und Reset-Pin ist auf 5V definiert
(10k).
Eine avr-gcc Aktualisierung habe ich aber noch nicht durchgeführt.
Gruß Tobias
Hi!
Nach nem reset gibt es ein Register, in dem der Resetgrund steht
(PowerOn, WDT, BrownOut, etc). Vielleicht hilft dir dieses Register
weiter.
Wie häufig tritt der Reset auf? Alle Stunde, Minute, nur bei einer
bestimmten Situation?
Wenn du es übertreiben möchtest, kannst du die ganze Schaltung auch über
eine Batterie betreiben.
Hast du im AVR-Studio bei den Projektkonfigurationen und im
Downloaddialog den richtigen Prozessortyp eingestellt?
Ob das zu nem Reset führen kann weis ich zwar nicht, aber wenn das nicht
stimmt, dann kann alles mögliche verrükte passieren.
Was für ein Programm ist es, also welchen Zweck soll es erfüllen? (nur
aus Neugier)
Paulchen Panther schrieb:> Nach nem reset gibt es ein Register, in dem der Resetgrund steht> (PowerOn, WDT, BrownOut, etc). Vielleicht hilft dir dieses Register> weiter.
Dieses Register konnte ich leider nicht finden. :(
Wie ist der Zurgriff darauf?
WDT + BrownOut sind deaktiviert.
> Wie häufig tritt der Reset auf? Alle Stunde, Minute, nur bei einer> bestimmten Situation?
Bei bestimmten Situationen. (z.B. nach Tasterbetätigung in bestimmten
Funktionen, wobei das Prog nicht direkt an der Stelle sthenbleibt.) Mal
beim 3. Betätigen, mal erst beim 100. betätigen. "Nach Lust und Laune"
> Wenn du es übertreiben möchtest, kannst du die ganze Schaltung auch über> eine Batterie betreiben.
Könnte ich mal testen, aber erst im Laufe des Tages morgen.
David Kress schrieb:> Hast du im AVR-Studio bei den Projektkonfigurationen und im> Downloaddialog den richtigen Prozessortyp eingestellt?
Dort und im Programmier-Dialog auch jeweils "ATmega644P"
Neueste Version vom AVR-Studio wurde auch installiert (incl. SP1, SP2,
SP3 ) und das neueste Firmwareupgrade des AVRISP mkII habe ich auch
gemacht.
> Ob das zu nem Reset führen kann weis ich zwar nicht, aber wenn das nicht> stimmt, dann kann alles mögliche verrükte passieren.
Er meckert viel und falls man mal was programmieren kann schießt er sich
gleich ganz ab.. :D
> Was für ein Programm ist es, also welchen Zweck soll es erfüllen? (nur> aus Neugier)
Es umfasst ein kleines Datenbanksystem mit verschiedenen Werteingaben..
umfangreiche Menüsteuerung usw.
Falls es eine Rolle spielt wie viel Speicher verbraucht ist?:
Program: 35152 bytes (53.6% Full)
Data: 2670 bytes (65.2% Full)
Hier ein Ausschnitt aus den Einstellungen beim Programmieren:
- Boot Flash size=1024 words Boot address=$7C00
- Brown-out detection disabled; [BODLEVEL=111]
- Ext. Crystal Osc. 8.0- MHz; Start-up time: 16K CK + 65 ms
Spezialisierung: SOFTWARE!!!
Nach längeren Tests ist mir aufgefallen, dass der Reset nur in einer
"Programmhälfte" auftritt.
Ganz übertrieben grob dargestellt:
1
[...]
2
while(1){
3
if(/*schiebeschalter auf 1*/){
4
menue=1;
5
}else{
6
menue=0;
7
}
8
9
if(menue==1){
10
// Menü-Führung
11
}elseif(menue==0){
12
// Programm /*FEHLER NUR HIER*/
13
}
14
}
15
[...]
D.h. Hardware-Fehler vorerst ausgeschlossen und ich werde weiter nach
Software-Fehlern suchen.
Neuer ATmega644P wurde auch eingesetzt, 100% identisches Problem.
Weiterhin Danke für Eure guten Vorschläge und Ideen!
Gruß Tobi
Hallo Tobias,
die "Problematik" hatte ich auch schonmal. Das mein Programm ab und zu
durch einen "unerklärlichen" Reset abgeschmiert ist.
Bei mir war es wohl so das ich recht viel RAM gebraucht habe (70-80%)
und die Schachtelungstiefe des Programms (bzw der Unterprogramme) auf
dem Stack sehr hoch war bzw viele Parameter übergeben werden, irgendwann
gabs einen Stacküberlauf. Nachdem ich etwas Speicher freischaufeln
konnte (es waren konfigurierbare Puffer) trat das Problem nicht mehr
auf.
Daher vllt neue Punkte für die Checkliste :
- wie tief werden die Programm/Unterprogrammaufrufe geschachtelt
- wieviele Parameter übergibst du im Schnitt (gerade bei "durchreichen"
von Parametern braucht man viel RAM, soweit ich weiß)
Was auch schonmal gerne passiert : unbeabsichtigte Rekursionen :-)
Edit :
Ich seh gerade das du in der while-Schleife den Schiebeschalter
abfragst. Machst du das direkt oder mit Entprellung ?
Nicht das durch das Prellen des Schalters dein Programm amok läuft.
Rene Böllhoff schrieb:> Daher vllt neue Punkte für die Checkliste :> - wie tief werden die Programm/Unterprogrammaufrufe geschachtelt
also in der Regel nicht mehr als 3 Verschachtelungen.
> - wieviele Parameter übergibst du im Schnitt (gerade bei "durchreichen"> von Parametern braucht man viel RAM, soweit ich weiß)
Ich übergebe normal nur einen int oder mal einen long, ansonsten 'return
0;'.
Könnte es Probleme geben wenn ich sehr viele globale Variablen definiert
habe, die aber im ganzen Programm Zugang haben sollten und auch hier und
da abgeändert werden sollten?
> Was auch schonmal gerne passiert : unbeabsichtigte Rekursionen :-)
Also eine Rekursionsformel ist drin, aber nur eine Mathematische
(ähnlich der 'rand()'-Funktion), keine mit Zugriff auf den Stack.
Der µC durchläuft x mal das selbe Programm mit den selben Funktionen und
Parametern und bei meinetwegen x+3 oder x+300 startet er neu.
> Ich seh gerade das du in der while-Schleife den Schiebeschalter> abfragst. Machst du das direkt oder mit Entprellung ?> Nicht das durch das Prellen des Schalters dein Programm amok läuft.
Hier ein Beispiel für die Abbruchbedingung in einem Programmteil:
(entprellen = 20000)
1
// Abbruchbedingung
2
if(PINB&(1<<PB0)){
3
_delay_us(entprellen);
4
while(PINB&(1<<PB0));// Warten bis Taster losgelassen
Kann man bestimmt einfacher lösen, aber hiermit b in ich auf Nummer
sicher gegangen. Manchmal lese ich auch die dauer des Drucks aus, dann
ist es ganz gut wenn ich die Funktion nur in die vorhandene
while-Schleife einbinden muss.
Danke und Gruß Tobias
Matthias schrieb:> Tobias Gläser schrieb:>> Gibt es eine Möglichkeit alle Interrupts komplett zu sperren? Habe da>> nichts gefunden was mir weiterhilft.>> cli();
Das stimmt insofern, als dann kein Interrupt mehr auftritt.
Allerdings kann man dan meist das Programm nicht mehr so
recht probieren...
Dann ist man mit einer catch all-ISR besser bedient, um einen fehlenden
ISR einzukreisen:
http://www.mikrocontroller.net/articles/AVR_Checkliste#Alle_Interruptvektoren_definiert.3F
Tobias Gläser schrieb:> Also eine Rekursionsformel ist drin, aber nur eine Mathematische> (ähnlich der 'rand()'-Funktion), keine mit Zugriff auf den Stack.> Der µC durchläuft x mal das selbe Programm mit den selben Funktionen und> Parametern und bei meinetwegen x+3 oder x+300 startet er neu.
Jede Funktion nutzt den Stack. Zeig doch mal den Code.
Oliver
Tobias Gläser schrieb:>> Nach nem reset gibt es ein Register, in dem der Resetgrund steht>> (PowerOn, WDT, BrownOut, etc). Vielleicht hilft dir dieses Register>> weiter.> Dieses Register konnte ich leider nicht finden. :(
MCUSR. Sagt den Grund des Resets, falls es Hardware war. Auslesen,
dann rücksetzen (für den nächsten Reset). Nachdem Du das Problem
allerdings auf einen Codebereich isolieren konntest, sieht es weniger
nach Hardware aus (es sei denn, Du schaltest dort z.B. eine induktive
Last).
Hi,
Ich baue fast ausschließlich Uhren und hatte das Problem auch schon ab
und an mal. Das Problem ist (wie oben bereits geschrieben wurde) das
Prellen des Tasters, durch welches der Interrupt immer wieder aufgerufen
wird, was dann zu einem Stacküberlauf führen kann.
Gerade die entprellung mit delay_xx macht da interessanterweise immer
mal wieder Probleme.
hast du nen timer-interrupt frei? wenn ja bau dir damit eine eigene
delay-Funktion und lös die Entprellung mal darüber.
Was auch hilft: Bevor du in die Entprellung gehst, den entsprechenden
Tasten-Interrupt zu deaktivieren, und ihn nach der Entprellung wieder
einzuschalten (Natürlich nur, wenn du schon innerhalb der ISR Interrupts
wieder zulässt).
gruß
tobi
PS. Wie das ganze mit nem timer-interrupt lösbar ist, kannst du z.B. in
der Beispielsoftware (zu finden unter user/user.c) in dem angehängten
File sehen.
-Die Funktion tick_time() wird von einem Timer-Interrupt genau 122 mal
pro Sekunde aufgerufen. Die beinhaltet eine Zählvariable, mit deren
Hilfe u.a. die Tastenentprellung gemacht wird.
-Die Funktion button_press_12 beinhaltet die Abfrage für die Tasten.
(Eigenwerbung: Das File beinhaltet nanoos, ein selbst entwickeltes
multitask-system für den AVR)
http://sourceforge.net/projects/nanoos/files/nanoos-software.zip/download
Tobias W. schrieb:> Das Problem ist (wie oben bereits geschrieben wurde) das> Prellen des Tasters, durch welches der Interrupt immer wieder aufgerufen> wird, was dann zu einem Stacküberlauf führen kann.
Solange du die Interruptfreigabe innerhalb der ISR so lässt, wie sie
ist, passiert da gar nichts. Wenn doch, hast du irgend einen anderen
Fehler in deinem Programm.
Und wenn du die Interrupts innerhalb einer ISR freigibst, solltest du
halt genau wissen, was und warum überhaupt du da was tust.
Tobias W. schrieb:> Gerade die entprellung mit delay_xx macht da interessanterweise immer> mal wieder Probleme.
Nicht nur deshalb sollte man weder einen Externen INT für eine
Tastenauswertung, noch delay_xx zum Entprellen nutzen.
Oliver
Hc Zimmerer schrieb:> MCUSR. Sagt den Grund des Resets, falls es Hardware war. Auslesen,> dann rücksetzen (für den nächsten Reset). Nachdem Du das Problem> allerdings auf einen Codebereich isolieren konntest, sieht es weniger> nach Hardware aus (es sei denn, Du schaltest dort z.B. eine induktive> Last).
Super danke, Habe in der Register-Tabelle gesucht, dort nichts mit Reset
oder dergleichen gefunden. Versuchen werd ichs dennoch mal, schadet
nicht.
Auslesen, Meldung beim Start am Display anzeigen und löschen. (Erinnert
mich etwas an einen Blue-Screen xD)
Tobias W. schrieb:> Das Problem ist (wie oben bereits geschrieben wurde) das> Prellen des Tasters, durch welches der Interrupt immer wieder aufgerufen> wird, was dann zu einem Stacküberlauf führen kann.
Wie aber im Codebeispiel zu sehen, verwende ich hier nichtmal
Interrupts. :(
> Gerade die entprellung mit delay_xx macht da interessanterweise immer> mal wieder Probleme.
Die Delay-Funktion ist zwar drin, aber Interrupts sind komplett
deaktiviert.
Tobias W. schrieb:> PS. Wie das ganze mit nem timer-interrupt lösbar ist, kannst du z.B. in> der Beispielsoftware (zu finden unter user/user.c) in dem angehängten> File sehen.
Ich werds mir auf jeden Fall mal ansehen!
> (Eigenwerbung: Das File beinhaltet nanoos, ein selbst entwickeltes> multitask-system für den AVR)
Ist genehmigt :D
> http://sourceforge.net/projects/nanoos/files/nanoos-software.zip/download
Gruß und Danke
Tobias
Oliver schrieb:> Nicht nur deshalb sollte man weder einen Externen INT für eine> Tastenauswertung, noch delay_xx zum Entprellen nutzen.
Hmm aber das problem umgehe ich doch wenn ich manuell den Pin einlese
und mich dann gemütlich in eine Warteschleife lege. Keine Interrupts.
Dann ist es doch -momentan für mein Verständnis- komplett egal was der
Taster außerhalb am Pin macht.
Liege ich da komplett falsch?
Klaus Wachtler schrieb:> Seit wann ist rand() rekursiv?
Genau lesen. Der Algorithmus hinter rand() ist rekursiv, da er das
Ergebnis des vorherigen Aufrufs wieder in das neue Ergebnis mit
einbezieht.
Tobias Gläser schrieb:> Keine Interrupts.> Dann ist es doch -momentan für mein Verständnis- komplett egal was der> Taster außerhalb am Pin macht.
So sollte es sein. Dein Problem liegt wohl woanders.
Oliver
ok, das code-beispiel habe ich nicht gelesen. Das Thema Interrupts fällt
damit wohl weg. Tritt das Problem denn nur auf, wenn du eine Taste
drückst oder auch so mal sporadisch?
@Oliver:Full Ack. Aber ich bin nicht der TO, ich hatte das Problem nur
mal in der Vergangenheit und wollte ihn darauf hinweisen.