Forum: Mikrocontroller und Digitale Elektronik Invalid Opcode?


von Torsten O. (Gast)


Lesenswert?

G' Morgen, ich hab' das Forum schon durchsucht und zwei Beiträge zu 
meinem Problem gefunden - leider konnte die mir nicht weiterhelfen.

Ich habe einen Assemblercode wie folgt :

[avrasm]
.include "definition.inc"

.org 0x000
rjmp    Initialize
.org 0x00b
rjmp    PortB
.org 0x10
rjmp    PulseWidthModulation

Initialize:

ldi     Register, 0xff                  ; Stackpointer initialisieren
out     0x3d, Register
ldi     Register, 0x02
out     0x3e, Register

ldi     Register, 0x80                  ; Systemclock dividieren
sts     0x61, Register
ldi     Register, 0x08                  ; auf 78,125kHz
sts     0x61, Register

Timer0:                                 ; steuert die Pulseweite

ldi     Register, 0x01                  ; Overflow - Interrupt setzen
sts     0x6e, Register
ldi     Register, 0x01                  ; Clock dividieren
out     0x25, Register

Timer1:

ldi     Register, 0x02                  ; Interrupt freigeben
sts     0x70, Register
ldi     Register, 0x41                  ; COM2A0=1; COM2A1=0; WGM0=1; 
WGM1=0; WGM2=0;
sts     0xb0, Register
ldi     Register, 0x01
sts     0xb1, Register

PortB_Aus:

ldi     Register, 0x03
out     0x04, Register

sei

Slave:

rjmp    Slave

PulseWidthModulation:

push    Counter
andi    Counter, 0xff
cpi     Counter, 0xff
breq    SetPulseWidth
pop     Counter
inc     Counter
reti

SetPulseWidth:

push    Value
mul     Value, Value
sts     0xb3, R0
andi    Value, 0x0f
cpi     Value, 0x0f
breq    ResetValue
pop     Value
inc     Value
reti

ResetValue:

pop     Value
ldi     Value, 0x00
reti

PortB:

ldi     R17, 0x02
in      Register, 0x05
eor     Register, R17
out     0x05, Register
reti
[\avrasm]

Ich bekomme eine Fehlermeldung :  "Invalid Opcode 0xffff at address 
0x000007". Wo genau soll denn da mein Fehler sein? Kann mir da jemand 
einen Tipp geben?

Vielen Dank im voraus


lg Torsten

von Benedikt K. (benedikt)


Lesenswert?

Meckert der Assembler nicht, wenn du PortB als Label verwendest?

von Torsten O. (Gast)


Lesenswert?

Nein, das scheint ihn nicht zu stören. Ich hab's mal geändert, passiert 
das gleiche.

lg Torsten

von Tobi (Gast)


Lesenswert?

Hi!

Ich sehe auf anhieb auch keinen Fehler. Aber vereinfach doch mal den 
Code. Wenns dann geht, bau immer mehr Teile dazu. Bis der Fehler wieder 
kommt. dann kannst du den Fehler schonmal eingrenzen.

von Benedikt K. (benedikt)


Lesenswert?

Das Problem dürfte auf daran liegen, dass irgendwie der Rücksprung aus 
dem Interrupt schiefgeht, oder dass irgendein Interrupt aktiv ist, der 
an Adresse 0007 springt. Da du aber derart lese freundlich 
programmierst, und auch immer schön die Registernamen verwendest und 
natürlich auch den AVR angegeben hast, den du verwendest habe ich keine 
Lust jetzt alle Datenblätter danach zu durchsuchen was das nicht passen 
könnte.

von Torsten O. (Gast)


Lesenswert?

Ich habe das Problem gefunden. Ich habe den Quellcode Stück für Stück 
neu eingegeben und der Fehler tritt erst auf, wenn ich den Befehl "sei" 
verwende. Es handelt sich um einen ATmega48. Sorry, wegen der 
Unleserlichkeit. Gibt es denn eine andere Möglichkeit alle Interrupts 
global freizugeben?

lg Torsten

von Jens G. (jensig)


Lesenswert?

muß man nicht auch ein paar Register retten in der ISR? Oder ist das nur 
beim PIC nötig gewesen ... (sorry - Atmel-Programmierung liegt 
inzwischen etwas zurück bei mir :-(

von Jens G. (jensig)


Lesenswert?

oder Du hast die falschen ISR-Sprungadressen mit den rjmp's gefüllt am 
Anfang ...

von Benedikt K. (benedikt)


Lesenswert?

Torsten Ohne wrote:
> Es handelt sich um einen ATmega48. Sorry, wegen der
> Unleserlichkeit.

Schau mal ins Datenblatt:
Adresse 7 ist der OC2A Interrupt, und genau den aktivierst du.

Was lernen wir daraus?
Anstelle der Adressen die in der Include File definierten Labels und 
Registernamen verwenden.
Dann kann man das Programm besser lesen, vermeidet solche Fehler, und 
man kann das Programm leichter auf einen anderen AVR anpassen.

von Torsten O. (Gast)


Lesenswert?

Das mit dem Retten der Register ist ein gutes Argument, das hatte ich 
auch vergessen - danke. Das kann aber auch nicht der Fehler sein, da er 
auftritt sobald der Interrupt aufgerufen wird.

@Jens :  Was meinst du mit "falsch gefüllt"? Ich gebe ihm doch mit dem 
Befehl

.org 0x0b                                 ; Interrupt für TIM1_COMPA
rjmp      SpringeZuInterruptRoutine

die Anweisung. Kann ich da auch etwas falsch machen?


lg Torsten

von Torsten O. (Gast)


Lesenswert?

@Benedikt :  Aber Adresse 7 spreche ich doch gar nicht an? Ich habe doch 
die 0x0b angesprochen? Kann es sein, dass ich da bei der Programmieren 
was falsch verstanden habe?

Ich dachte, ich dem Controller einfach die entsprechende Interruptnummer 
geben und ihm sagen springe beim Auslösen an die gewünschte Stelle im 
Quellcode? grübel


lg Torsten

von Benedikt K. (benedikt)


Lesenswert?

Torsten Ohne wrote:
> @Benedikt :  Aber Adresse 7 spreche ich doch gar nicht an?

Du machst das nicht, aber der AVR, wenn er den OC2A Interrupt ausführt.

von Torsten O. (Gast)


Lesenswert?

Hm... okay, ich sollte mal euren Rat annehmen wegen der Register. Ich 
danke euch für eure Hilfe.

lg Torsten

von Jens G. (jensig)


Lesenswert?

@  Torsten Ohne (tome28)

>@Jens :  Was meinst du mit "falsch gefüllt"? Ich gebe ihm doch mit dem
>Befehl

eigentlich genau das, was Benedikt gerade vorher sagte. Offensichtlich 
hast Du den OC2A Interrupt aktiviert, der lt. Benedikt auf Adresse 0x7 
seine ISR Routine vermutet, der aber in deinem Coding leer ist (nicht 
initialisiert, deswegen 0xFFFF als invalid Opcode

von Gast (Gast)


Lesenswert?

Im AVR-Studio gibts übrigens eine durchaus nützliche Einrichtung, die 
sich "Simulator" nennt. Damit soll man der Ursache solcher Probleme sehr 
schnell auf die Spur kommen können. Mal ausprobieren, was das für ein 
Wunderding ist?

>ldi     Register, 0x03
>out     0x04, Register

Kein erfahrener Programmierer auf der Welt pflegt einen solchen 
Codierstil. Vielleicht hast Du Lust, über mögliche Gründe dafür selbst 
nachzudenken.

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.