Forum: Mikrocontroller und Digitale Elektronik Controller fällt in (anscheinend) RESET


von Lukas G. (lukas88)


Angehängte Dateien:

Lesenswert?

Hallo zusammen,

Ich hab ein Problem mit meinem Code für einen Atmega48. Und zwar
wird durch eine Taste eine Interrupt  Routine ausgelöst, die per SPI 
Daten an ein Funkmodul sendet. Das tut es eigentlich auch wie gewünscht.

Komischerweise scheint der Controller nach der Ausführung von EXT_INT1 
einen Reset auszulösen. Denn wenn ich die Taste drücke, blinkt die Rote 
LED die eigentlich nur beim init (also beim Start/RESET) kurz auf, die 
signalisieren soll das das Funkmodul initialisiert wurde.

sbi    PORTB,1
rcall rfm_init
cbi    PORTB,1

Wenn ich die Zeile bei EXT_INT1 entferne:

rcall     rfm_send

Läuft das Programm Normal weiter, ohne das die Rote LED blinkt. Als wird 
init nicht ausgeführt, was korrekt wäre.

Also wäre der Fehler logischerweise in im Block rfm_send.

Bis jetzt komme ich aber nicht dahinter, was genau Falsch ist am Code. 
Also nehme ich an, das ich etwas permanent übersehe.

Darum würde ich mich freuen wenn jemand von euch den Code einmal 
überfliegen könnte, um mir etwas auf die Sprünge zu helfen.

Ist übrigens ein Testprogramm für Komponenten auf einer Prototyp PCB. Es 
ist darum auch Code dabei, die mit der eigentlichen Aufgabe nichts zu 
tun haben (TWI, OneWire,ect)

von b0fh (Gast)


Lesenswert?

Bin gerade am Handy,

Sehr wahrscheinlich benutzt deine aufgerufenene Routine delay oder 
ähnliches und läuft somit in den Wächter.

In der ISR ein Flag setzen und in der Main darauf reagieren.

ISR: taste=1
Main: taste==1 && rfm_send()

MfG

von Thomas Z. (usbman)


Lesenswert?

da fehlt ein pop_stock in der Uart Routine.

von S. Landolt (Gast)


Lesenswert?

Ich kann in §rfm12_txbyte das Gegenstück zu 'pop lsb' nicht finden.

von Ralf G. (ralg)


Lesenswert?

1
rfm12_txbyte:
2
3
ldi     msb,0xB8
4
rcall   rfm_trans_ready
5
pop     lsb

Wo wird eigentlich 'lsb' (vielleicht auch unter anderem Namen?) auf dem 
Stack abgelegt?

Oooh dazwischengemogelt ;-) sehe gerade:
S. Landolt schrieb:
> Gegenstück zu 'pop lsb'

: Bearbeitet durch User
von Lukas G. (lukas88)


Lesenswert?

Es war tatsächlich das push lsb das gefehlt hatte!

push   lsb
ldi     msb,0xB8
rcall   rfm_trans_ready
pop     lsb

So wies aussieht hat das Fehlende push das Statusregister/Register bei 
pop_stock  verändert, einen Fehler generiert, der den Controller in den 
Reset zwang. Bei der Uart Routine übringens das gleiche problem.

Ironischerweise hatte ich das mal genau so mit pop/puhs wie es sein 
sollte gehabt, und es funktionierte auch ohne Probleme. Durch das 
ständige abändern des Codes beim Testen, hab ich wohl versehentlich Code 
gelöscht/nicht kopiert, und beim Kontrollieren übersehen. Ich sollte 
mehr mit Git arbeiten...

Trotz allem Vielen lieben dank an die hilfreichen hinweise!

Schöne Festtage!

von S. Landolt (Gast)


Lesenswert?

Und ich sehe gerade, dass es mit dem Aussterben unserer Species trotz 
aller Unkenrufe doch noch eine Weile dauern wird.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Lukas G. schrieb:
> So wies aussieht hat das Fehlende push das Statusregister/Register bei
> pop_stock  verändert, einen Fehler generiert, der den Controller in den
> Reset zwang.
So wie es aussieht, hast du den zugrunde leigenden Mechanismus noch 
nicht richtig durchschaut. Denn wer sollte den Controller auf welche Art 
"in den Reset gezwungen" haben?

> So wies aussieht hat das Fehlende push
... dazu geführt, dass die Rücksprungadresse auf dem Stack falsch 
interpretiert wurde und beim Rücksprung dann in einen gelöschten 
Flashbereich mit vielen 0xFF gesprungen ist. Das 0xFF resultiert beim 
AVR zu einem SBRS, und weil da viele solcher SBRS hintereinander stehen, 
läuft der Controller munter bis ans "Ende" des Flashs und fängt "vorne" 
bei 0 wieder an. Und diese 0 ist ja dann auch der Resetvektor.

: Bearbeitet durch Moderator
von S. Landolt (Gast)


Angehängte Dateien:

Lesenswert?

> Das 0xFF resultiert beim AVR zu einem SBRS

?

von Lukas G. (lukas88)


Lesenswert?

Das mit der Rücksprungadresse hab ich mir auch irgendwie gedacht. Im 
Nachhinein eigentlich Logisch, da die Adresse beim zurückspringen ja 
auch nicht mehr stimmt, genau wie die anderen Registerwerte die auf dem 
Stack liegen.

Vielen dank für deine Erläuterung!

von S. Landolt (Gast)


Lesenswert?

Wobei noch anzumerken wäre, dass ein Sprung zum Resetvektor nicht einem 
Reset entspricht - Letzterer setzt zum Beispiel die SFRs auf ihre 
'initial values'.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

S. Landolt schrieb:
>> Das 0xFF resultiert beim AVR zu einem SBRS
> ?
Ignoriere mal einfach diese 0 im Bit 4, die hat nur der Assembler zu 
beachten, denn der darf entsprechend der Doku aus dem SBRS R31,7 kein 
0xFFFF machen, sondern ein 0xFFF7.

Wenn aber im Speicher ein 0XFFFF steht, dann gibt es beim AVR keinen 
Mechanismus, der einen Interrupt für einen "falschen Opcode" auslöst. 
Das Bit 4 wird da einfach ignoriert.

von Martin V. (oldmax)


Lesenswert?

Hi

Lothar M. schrieb:
> So wie es aussieht, hast du den zugrunde leigenden Mechanismus noch
> nicht richtig durchschaut. Denn wer sollte den Controller auf welche Art
> in den Reset "gezwungen" haben?


Nun ja, eine ISR arbeitet ähnlich, wie ein CALL. Da wird die 
Rücksprungadresse auf den Stack gelegt und beim RETI wieder in den 
Programmcounter gesschrieben. Auch die Push und Pop Befehle legen Werte 
auf den Stack und holen diese dort wieder ab. Zur Adressierung dient der 
Stackpointer, der beim Ablegen von Werten auf den Stack herunterzählt 
und beim Zurückholen wieder hochzählt. Der Grund für Push und POP, bei 
einer ISR weiß ja niemand, wann diese aufgerufen wird. So kann ein 
Ergebnis im Statusregister verloren gehen, wenn es nicht vor dem 
Ausführen von Befehlen, die das Statusregister verändern, gesichert 
wird. Und dies geschieht natürlich am Anfang einer ISR mit einem 
Push-Befehl, der erst einmal wichtige Registerinhalte sichert. Am Ende 
der ISR holt mal diese Werte mit POP Befehl wieder zurück und kann die 
ISR mit RETI verlassen. Das funktioniert solange problemlos, wie die 
Anzahl der POP Befehle auch der Anzahl der Push Befehle entspricht, da 
der Stackpointer dann auch auf die abgelegte Rücksprungadresse zeigt. 
Ein POP ohne ein Push holt aber einen teil der Rücksprungadresse und der 
Stackpointer zeigt dann auf eine Speicherstelle, die alles mögliche 
beinhaltet, aber nicht die sichere Rücksprungadresse. Daher fängt aller 
Wahrscheinlichkeit dein Programm wieder bei Null an.
Gruß oldmax

von c-hater (Gast)


Lesenswert?

Lothar M. schrieb:

> Wenn aber im Speicher ein 0XFFFF steht, dann gibt es beim AVR keinen
> Mechanismus, der einen Interrupt für einen "falschen Opcode" auslöst.
> Das Bit 4 wird da einfach ignoriert.

So sieht's aus.

Und das gibt's/gab's bei vielen µC/µP, nennt sich typischerweise 
"undokumentierte Opcodes". Ist hier aber nur die leichte Form davon, 
nämlich eine simple Doublette. Es gibt halt mehr als einen möglichen 
Opcode für eine konkrete Operation.

Dank der hohen "Dichte" des AVR8-Instructionset gibt es im Vergleich zu 
anderen µC/µP nur recht wenige dieser "undokumentierten Opcodes" und 
davon sind wiederum sehr viele einfach nur Doubletten.

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.