Forum: Mikrocontroller und Digitale Elektronik MCUCSR Reset ATMEGA32 - warum?


von daniel (Gast)


Lesenswert?

Hallo,

auf meinem Board (ATMEGA32) werden zufällige Resets ausgelöst. Jetzt 
würde ich gerne die Ursache herausfinden. Dazu - so dachte ich - wäre es 
schlau, bei Adresse 0x00 im Flash einen Breakpoint zu setzen und dann 
ins MCUCSR register zu schauen.

Leider ist das Register 0x00! Sprich, es ist kein Bit gesetzt dass auf 
einen bestimmten Reset-Auslöser schließen ließe. In einem anderen Thread 
habe ich gelesen, dass eine nicht gesetzte CKOPT-Fuse eine Ursache sein 
kann. Das kann ich aber ausschließen, CKOPT ist programmiert.

Gibts noch eine Idee wie ich herausfinden könnte, warum der Reset 
ausgelöst wird?

Gruß,
Daniel

von holger (Gast)


Lesenswert?

>Gibts noch eine Idee wie ich herausfinden könnte, warum der Reset
>ausgelöst wird?

Dein Quellcode?
Resets werden z.B. ausgeführt wenn ein Interrupt
enabled wird, aber keine ISR dafür vorhanden ist.

von Stefan E. (sternst)


Lesenswert?

holger schrieb:

> Dein Quellcode?
> Resets werden z.B. ausgeführt wenn ein Interrupt
> enabled wird, aber keine ISR dafür vorhanden ist.

Und da das dann kein echter Hardwarereset ist, sondern nur ein Sprung 
zur Adresse 0, gibt es in dem Fall auch nichts Interessantes in MCUCSR 
zu sehen. ;-)

von daniel (Gast)


Lesenswert?

Hallo,

gibt es eine Möglichkeit zu sehen, welches die zuletzt abgearbeitete 
Stelle im Code vor dem Reset war?
Bei TI µCs kann man direkt nach dem Reset die letzte Adresse aus dem 
Link Register auslesen.

Gruß,
Daniel

von Peter D. (peda)


Lesenswert?

Lies einfach den Stackpointer aus.
Wenn er 0 ist, dann war es ein Reset.
Ansonsten zeigt er auf den SRAM, der die letzte Returnadresse enthält.


Peter

von holger (Gast)


Lesenswert?

>gibt es eine Möglichkeit zu sehen, welches die zuletzt abgearbeitete
>Stelle im Code vor dem Reset war?

Per SingleStep duch den Code gehen?

>Bei TI µCs kann man direkt nach dem Reset die letzte Adresse aus dem
>Link Register auslesen.

Hast du es noch nicht geschnallt?
Es muss kein echter Reset sein. Es könnte auch ein
Jump to Zero sein. Ausgelöst durch eine fehlende
Interruptroutine. Oder ein Stacküberlauf.

von Peter D. (peda)


Lesenswert?

Setze mal nen BADISR Handler auf, ob der getriggert wird.


Peter

von daniel (Gast)


Lesenswert?

Hallo,

für alle 20 Interrupt-Vektoren existiert ein Handler nach folgendem 
Schema:

ISR(<vector1..20>)
{
  lastIRQ = <vectornummer>;
  ...
}

Es scheint kein richtiger Reset zu sein da A) nichts im MCUCSR steht und 
B) da der Stackpointer einen Wert ungleich 0 hat. Allerdings hat der 
Stackpointer leider keinen konstanten Wert, sondern er zeigt auf eine 
zufällige Adresse im Flash (aber auf plausible), mal in einer ISR, mal 
im normalen Code. Und dort werden unterschiedliche Operationen.

Das interessante ist, dass ich von allen drei Timern die Ausgangspins 
nutze. Wenn ich an diese Ausgänge nicht verbinde tritt dieses Problem 
nicht auf. Sobald ich jedoch die Pins mit Eingängen eines anderen ICs 
verbinde tritt das Problem sehr schnell auf.

Komische Sache das...

von holger (Gast)


Lesenswert?

>Das interessante ist, dass ich von allen drei Timern die Ausgangspins
>nutze. Wenn ich an diese Ausgänge nicht verbinde tritt dieses Problem
>nicht auf. Sobald ich jedoch die Pins mit Eingängen eines anderen ICs
>verbinde tritt das Problem sehr schnell auf.

Dann hast du ein Schaltungsproblem.
Ich bin jetzt aber zu müde dir den Arsch
aufzureissen weil du wichtige Informationen unterschlagen hast.

Gute Nacht ;)

von Thomas (kosmos)


Lesenswert?

Vielleicht fehlt irgendwo ein "ret" mit der Zeit addiert es sich und der 
Stackpointer läuft über, dann gehts auch wieder bei 0 los.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Peter Dannegger schrieb:
> Lies einfach den Stackpointer aus.
> Wenn er 0 ist, dann war es ein Reset.

Bei den neueren AVRs steht er nach einem Reset übrigens auf der
obersten RAM-Adresse.

von Hc Z. (mizch)


Lesenswert?

Bei avr-gcc laufen Interrupts, für die keine ISR definiert ist, über 
__bad_interrupt (das ist der Default-Vektor).  Wenn Du einen Breakpoint 
dahin setzt, weißt Du sicher, ob so etwas vorliegt.  Falls ja, kannst Du 
Breakpoints auf "verdächtige" Interrupt-Vektoren setzen und Dich so 
nähern.

von daniel (Gast)


Lesenswert?

Hallo alle,

vorab:

- alle nicht benutzten Eingänge sind auf Masse
- alle benutzten Pins sind mit 100nF versorgt, der Reset-Pin mit 1k 
gegen Masse und 100nF
- die Pegel schwanken nicht (mit Oszi an allen belegten Pins 
nachgemessen)


Da das MCUCSR Register kein Bit setzt wird wohl gewollter Reset 
passieren.
Holger sagt "Schaltungsproblem" - das klingt ja plausibel, aber welches 
elektrische Problem hat Einfluss auf den µC und bringt ihn dazu, bei 
Adresse 0x00 anzufangen ohne einen Reset auszulösen? Wenn ich das 
Datenblatt richtig verstehe dann gibt es keinen v. extern ausgelösten 
Reset der nicht im MCUCSR stehen müsste. Stimmts?

Hallo Holger,

das scheint mir auch zu schmerzhaft.

Hallo Thomas,

das fehlende "ret" müsste dann der Kompiler verursacht haben 
(programmiere in C) - Optimierungsgrad 0. Wäre aber technisch denkbar, 
aber ich halte das für höchst unwahrscheinlich. Ein Bugfix wäre dann 
auch nur schwer möglich. :)

Hallo Hazeh,

ich werde nochmal Breakpoints in den BADISR legen und sicherstellen, ob 
dieser nicht angefahren wird.

Gruß und Dank,
Daniel

von daniel (Gast)


Lesenswert?

Hallo nochmal,

der Interrupthandler für BADISR_vect wird nicht angesprungen.

von Hc Z. (mizch)


Lesenswert?

Das Ding heißt __bad_interrupt (mit zwei __ vorne).

von Simon K. (simon) Benutzerseite


Lesenswert?

Hazeh Zimmerer schrieb:
> Das Ding heißt __bad_interrupt (mit zwei __ vorne).

Der Interrupt Handler heißt BADISR_vect, das stimmt schon so.
1
ISR(BADISR_vect)
2
{
3
...
4
}

von daniel (Gast)


Lesenswert?

Hallo Hazeh,

"__bad_interrupt" habe ich in WinAVR-20081205 gesucht aber nicht 
gefunden.

In der avr-libc Referenz steht Folgendes:

Catch-all interrupt vector

If an unexpected interrupt occurs (interrupt is enabled and no handler 
is installed, which usually indicates a bug), then the default action is 
to reset the device by jumping to the reset vector. You can override 
this by supplying a function named BADISR_vect which should be defined 
with ISR() as such. (The name BADISR_vect is actually an alias for 
__vector_default. The latter must be used inside assembly code in case 
<avr/interrupt.h> is not included.)

#include <avr/interrupt.h>

ISR(BADISR_vect)
{
    // user code here
}


Das dürfte der Vektor sein den du meintest. Wird leider nicht 
aufgerufen. :(

von Hc Z. (mizch)


Lesenswert?

Den meinte ich zwar nicht, aber nach der obigen Beschreibung sollte das 
auch gehen (ich hätte halt einfach 'b __bad_interrupt' im gdb eingegeben 
und gesehen, dass es den gibt.  Es ist eine weak reference für die Jumps 
im Vektorbereich, die aber wahrscheinlich nicht mehr vorhanden ist, wenn 
Du einen BADISR_vect hast).

Was aber gar nicht passt, ist, dass MCUCSR 0 ist.  Das sollte nach 
jedem Reset mindestens ein Bit gesetzt haben.  Bist Du sicher, dass Du 
es Dir auf der richtigen Adresse anschaust (->I/O-Bereich, also nicht 
0x34, sondern 0x54)?  Wenn es 0 ist, muss Dich Software nach 0x0 
geschickt haben.

von Läubi .. (laeubi) Benutzerseite


Lesenswert?

daniel schrieb:
> Da das MCUCSR Register kein Bit setzt wird wohl gewollter Reset
> passieren.
Nö, ich würde erstmal das MCUCSR in ein 'nomales' Register retten, das 
wird nämlich zurückgesezt wenn man es nicht schnell genug ausliest das 
Problem gabs hier meine ich schonmal im Zusammenhang mit einem watchdog 
reset.

von Simon K. (simon) Benutzerseite


Lesenswert?

MCUCSR muss nach dem Starten und auslesen auch zurückgesetzt werden.

von holger (Gast)


Lesenswert?

>Holger sagt "Schaltungsproblem" - das klingt ja plausibel, aber welches
>elektrische Problem hat Einfluss auf den µC und bringt ihn dazu, bei
>Adresse 0x00 anzufangen ohne einen Reset auszulösen? Wenn ich das
>Datenblatt richtig verstehe dann gibt es keinen v. extern ausgelösten
>Reset der nicht im MCUCSR stehen müsste. Stimmts?

Erstmal Entschuldigung für die etwas rüde Ansprache gestern Abend :(

Da du ja nur Probleme hast wenn an den Pins etwas angeschlossen
ist, muss es ja ein Schaltungsproblem sein. Vorstellbar ist z.B.
ein Spannungseinbruch. Da kann der uC schon Mist bauen
wenn er gerade noch so Saft hat. Um den Fall abzudecken
solltest du den Brown-Out Reset aktivieren. Andererseits
können auch hohe Peaks auf Vcc den uC aus dem Tritt bringen.
Z.B. ein Relais ohne Freilaufdiode. Oder, wie schon oft
hier berichtet wurde, wenn du irgendeine induktive Last mit 230V
schaltest. Dann hilft ein Snubber.

Interessant wäre also was du an den Pins angeschlossen hast
und was damit geschaltet wird.

von Hc Z. (mizch)


Lesenswert?

Läubi .. schrieb:

> Nö, ich würde erstmal das MCUCSR in ein 'nomales' Register retten, das
> wird nämlich zurückgesezt wenn man es nicht schnell genug ausliest

Nö.  MCUCSR wird nur bei Spannungsausfall (Power-On Reset) gelöscht - 
und das ist erkennbar, denn danach ist das dafür zuständige Bit (PORF) 
gesetzt.  In allen anderen Fällen muss vom Programm explizit gelöscht 
werden (d.h. die Bits bleiben sonst stehen).

von daniel (Gast)


Lesenswert?

Hallo,

@Hazeh:
Beim ersten Einschalten ist das Power-On Flag im MCUCSR natürlich 
gesetzt. Aber ich setze in der main als erstes das MCUCSR auf 0x00, um 
ev. getriggerte Interrupts zu erkennen. Allerdings war noch nie ein Bit 
gesetzt, und ich bin mir inzwischen 100% sicher dass es kein 
getriggerter Reset ist, da die Register weiterhin gesetzt sind (z.B. 
TIMSK, die OCRx, usw.).

Zum eigentlichen Anwendungsfall:

Beim AVR (es ist ein ATMEGA32) werden nur die 3 Timer-Compare-Ausgänge 
benutzt. Jeder Ausgang geht zu einem L297 auf einer extra Platine.
Mit den Timer-Compare-Pins erzeuge ich die Schrittfrequenz, die die 
L297/L298 Kombination und den dahinter hängenden Schrittmotor steuert.

Das Interessante ist: wenn zwei, einer oder kein Motor angeschlossen 
ist, läuft das Programm ohne eine Unterbrechung. Sobald aber alle drei 
Motoren angeschlossen sind, bricht das Programm unglaublich schnell ab 
und springt auf 0x0.

Das klingt jetzt zwar nach Versorgungsspannung, aber ich habs so oft auf 
dem Oszi mitgemessen, und die Spannung nach dem 7805 ist glatt wie ein 
Babypopo.
Außerdem hab ich testhalber die BOD angeschalten und auf 4V eingestellt 
- schlägt aber nicht an. Passt also dazu dass nichts im MCUCSR gesetzt 
wird.

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.