Controller fällt in (anscheinend) RESET

OP #6521391
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)
Angehängte Dateien:
Gast #6521402
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
OP #6521452
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!
Moderator (Firma: Titel) Persönliche Seite #6521513
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.
Moderator (Firma: Titel) Persönliche Seite #6521534
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.
#6521535
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
Gast #6522150
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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren