Forum: Mikrocontroller und Digitale Elektronik ATmega644P Unbekannte Resetprobleme während des Programmes


von Tobias G. (t-g-laeser)


Lesenswert?

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
void WDT_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

von Karl H. (kbuchegg)


Lesenswert?

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
void WDT_off(void){
2
>   MCUSR &= ~(1<<WDRF);
3
>   WDTCSR |= (1<<WDCE) | (1<<WDE);
4
>   WDTCSR = 0x00;
5
> }

Hattest du denn den Watchdog überhaupt eingeschaltet?

von hacker-tobi (Gast)


Lesenswert?

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.

von Tobias G. (t-g-laeser)


Lesenswert?

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

von Matthias (Gast)


Lesenswert?

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

von Tobias G. (t-g-laeser)


Lesenswert?

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

von Paulchen Panther (Gast)


Lesenswert?

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.

von David K. (kresley81)


Lesenswert?

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)

von Tobias G. (t-g-laeser)


Lesenswert?

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
  }else if(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

von Rene B. (themason) Benutzerseite


Lesenswert?

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.

von Tobias G. (t-g-laeser)


Lesenswert?

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
5
      _delay_us(entprellen);
6
      if(!(PINB & (1 << PB0))){ // Taster sicher losgelassen?
7
        bestaetigung = 1;
8
      }
9
    }
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

von Klaus W. (mfgkw)


Lesenswert?

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

von Oliver (Gast)


Lesenswert?

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

von Klaus W. (mfgkw)


Lesenswert?

Seit wann ist rand() rekursiv?

von Hc Z. (mizch)


Lesenswert?

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).

von Tobias W. (hacker-tobi)


Lesenswert?

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

von Tobias W. (hacker-tobi)


Lesenswert?

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

von Oliver (Gast)


Lesenswert?

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

von Tobias G. (t-g-laeser)


Lesenswert?

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

von Tobias G. (t-g-laeser)


Lesenswert?

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?

von Simon K. (simon) Benutzerseite


Lesenswert?

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.

von Oliver (Gast)


Lesenswert?

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

von Tobias W. (hacker-tobi)


Lesenswert?

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.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.