Search code examples
assemblymicrocontrolleravratmega32

Why am I getting this error in proteus: " Invalid opcode 0xFFFF at PC=0x002A"


I wrote this code for avr atmega328P in assembly language. It turns on and off an LED using a push button, but in proteus I am getting this error:

Invalid opcode 0xFFFF at PC=0x002A

This is my code:

.INCLUDE "M328Pdef.inc"


ldi r16,HIGH(RAMEND)
out SPH, R16
ldi r16,LOW(RAMEND)
out SPL, R16

start:
ldi r16,0xFF
out DDRB,r16
ldi r17,0x00
out DDRD,r17
ldi r21,0x00
ldi r23,0x01

Forever:
in r20,PIND
cp r20,r21
BREQ ledon
cp r20,r23
BREQ ledoff
rjmp Forever


ledon:
ldi r22,0x01
out PORTB,r22 
ret

ledoff:
ldi r24,0x00
out PORTB,r24
ret

Does anyone have a solution for it?


Solution

  • Problem is here:

    BREQ ledon  ; branch
    cp r20,r23
    BREQ ledoff ; branch
    rjmp Forever
    
    ledon:
    ldi r22,0x01
    out PORTB,r22 
    ret ; return from subroutine, but never used [R]CALL.
    
    ledoff:
    ldi r24,0x00
    out PORTB,r24
    ret ; return from subroutine, but never used [R]CALL.
    

    You are branching to ledon resp. ledoff, which is just a conditional jump. But at the end of the respective blocks, you are using ret as if you called the code by means of [r]call.

    The ret will pop 2 bytes from the stack and use these as a word-address to return to. The code target will very likely have uninitialized flash, which holds 0xff's, and two 0xff's are 0xffff which is not a legal AVR opcode. 0x002a is the byte-address of the last ret which issued the illegal jump.

    To fix, you could rjmp Forever instead of ret, but it depends on what you want to achieve with the code.