Forum: Mikrocontroller und Digitale Elektronik Fehlermeldung AVR Studio und GCC


von Pascal (Gast)


Lesenswert?

Hi,

kann mir jemand erläutern wie ich folgende Fehlermeldung zu verstehen 
habe? Die Meldung erschein beim compilieren eines ATMega88 mit dem AVR 
Studio + GCC:

"/cc7GY9hV.s:124: Error: illegal opcode jmp for mcu atmega88"

Hab schon die Suche bemüht, doch leider nichts passendes gefunden.


Gruß

von abc (Gast)


Lesenswert?

Anscheinend kennt der 88 den Assemblerbefehl JMP nicht. Richtigen µC-Typ 
im AVR-Studio eingestellt?

von Pascal (Gast)


Lesenswert?

Danke!

JMP gibt es beim ATM88 nicht. Mit RJMP gehts....!!!!!

von Hc Z. (mizch)


Lesenswert?

Den Opcode „jmp“ gibt es beim ATmega88 nicht.

Hast Du einen Assembler-Source compiliert?  Dann gibt es jmp erst ab 
168.  Ändern in rjmp.

Hast Du C mit Makefile kompiliert?  Dann hast Du vermutlich den 
Prozessor-Typ geändert.  Es muss alles neu kompiliert werden, z.B. durch 
Aufruf von „make -B“.

von Stefan B. (stefan) Benutzerseite


Lesenswert?

> "/cc7GY9hV.s:124: Error: illegal opcode jmp for mcu atmega88"
In Zeile 124 von cc7GY9hV.s taucht ein jmp auf.

Das ist für den Atmega88 nicht erlaubt, denn
Datenblatt Atmega88: 31. Instruction Set Summary: jmp(1)
(1): Note: 1. These instructions are only available in ATmega168.

Die offenen Fragen sind:

1. ist der nicht gezeigte C-Quellcode, der nach cc7GY9hV.s übersetzt 
wurde, fehlerhaft?

2. ist die nicht näher bezeichnete Toolchain aus AVR Studio und gcc 
fehlerhaft? Hier gab es einen ähnlichen Fall:
http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=55290

3. sind die nicht gezeichten Compileroptionen (Projekteinstellungen, 
Makefile) fehlerhaft?

Zur Klärung der Symptome (das ist noch noch nicht die Diagnose oder die 
Kur) würde der Tipp von TimothyEBaldwin aus dem avrfreaks.net Thread 
weiterhelfen.

von Jens M. (dl4aas) Benutzerseite


Lesenswert?

Hallo Pascal,

es ist nicht zufällig eine große switch-Konstruktion, die die Meldung 
erzeugt? Ich habe es schon gehabt, dass der Prozessor die vom Compilter 
gewünschten JMPs nicht beherrschte, wenn der Sprung zu weit wurde..

Gruss
Jens

von abc (Gast)


Lesenswert?

Das wäre dann eher ein "out of reach", tritt vorzugsweise bei RJMP auf.

von Jens M. (dl4aas) Benutzerseite


Lesenswert?

abc, da hast Du wohl recht...

von Pascal (Gast)


Lesenswert?

Hi,

hier die Funktion die anscheinend Probleme macht:
1
 
2
#include <avr/io.h>
3
#include <avr/pgmspace.h>
4
#include <util/delay.h>
5
6
#include "aesglobal.h"
7
#include "bootldr.h"
8
#include "loader.h"
9
#include "bus.h"
10
#include "crc.h"
11
12
13
//=============================================================================
14
// Starts here!
15
//=============================================================================
16
17
int main(void)
18
{
19
    // enable pullup - give port time to settle
20
    set_bit(PORTD, PD2);
21
22
    busInit();
23
24
    // Loop forever (loops only if Application Section is damaged)
25
    for (;;)
26
    {
27
        // Key pressed? Yes -> run the loader routine
28
        if (!(PIND & (1 << PD2)))
29
        {
30
            loader();
31
        }
32
33
#if defined(CRC_CHECK)
34
        // Check that the Application Section contents is undamaged
35
        // by calculating the CRC of the whole memory.
36
        {
37
      #ifndef RAMPZ
38
              uint16_t p = 0x000000;
39
      #else
40
              uint32_t p = 0x000000;
41
      #endif
42
43
      uint16_t crc = 0;
44
45
            do
46
            {
47
      #ifndef RAMPZ
48
        crc = CRC(crc, pgm_read_byte(p));
49
      #else
50
                crc = CRC(crc, pgm_read_byte_far(p));
51
      #endif
52
            }
53
            while (++p < MEM_SIZE);
54
55
            // Application Section damaged
56
            //   -> do not jump to Reset Vector of the Application Section
57
            if (crc)
58
            {
59
                DDRB = 0xff;
60
                for(;;)
61
                {
62
                    PORTB ^= 0xff;
63
                    _delay_ms(500);
64
                }
65
            }
66
        }
67
#endif
68
69
        asm volatile ("rjmp 0");
70
    }
71
}

Mir scheint als der der Sprung and die Adresse 0 nicht 
funktioniert......

von Pascal (Gast)


Lesenswert?

Das Programm hängt an dieser Stelle:

while (++p < MEM_SIZE);

von Pascal (Gast)


Lesenswert?

Sorry, Alarm zurück!

Hab es gerade mal durch den Debugger direkt am Controller laufen lassen.

Das Programm springt anscheinend wirklich nicht an die Adreese 0, 
sondern es wird immer wieder die Main im Bootloader ausgeführt.

von Hc Z. (mizch)


Lesenswert?

Ich mag mich täuschen, aber ich denke, den Fall hatte ich auch mal und 
das Problem ist, dass die „0“ bei „rjmp 0“ relativ zur Text Section 
(genauer: zum Beginn dieser) ist.  Somit kommt die 
Bootloader-Startadresse raus.

Du musst ein absolutes Symbol definieren und das als Argument zum rjmp 
mitgeben, also
1
    asm volatile ("rjmp Application");
schreiben.  Und dem Linker die absolute Adresse von Application entweder 
im Linkerscript mitgeben oder auf der avr-ld-Kommandozeile mit
1
  --defsym Application=0
oder dem Compiler (avr-gcc) mit
1
  -Wl,--defsym,Application=0
.

von Pascal (Gast)


Lesenswert?

Super HC! Funktioniert einwandfrei!


Vielen Dank!

von Mario (Gast)


Lesenswert?

Schau mal in den Wiki-Artikel
AVR Bootloader in C - eine einfache Anleitung

Dort steht auch wie es geht ,z.B.
1
void (*start)( void ) = 0x0000;

und dann der  Aufruf mit:
1
start();

Die Beispiele sind übrigens alle für den Atmega88 geschrieben...

von Robert K. (murdok)


Lesenswert?

Mario schrieb:
> Schau mal in den Wiki-Artikel
> AVR Bootloader in C - eine einfache Anleitung
>
> Dort steht auch wie es geht ,z.B.
>
1
> void (*start)( void ) = 0x0000;
2
>
>
> und dann der  Aufruf mit:
>
1
> start();
2
>
>
> Die Beispiele sind übrigens alle für den Atmega88 geschrieben...

Diese Methode funktioniert allerdings nur wenn auf 0x0000 gesprungen 
werden soll.

Beim ATmega644 z.B. ist mit aufgefallen, dass mit diesem Code der Sprung 
auf eine Word-Adresse generiert wird. Wenn dann beispielsweise start 
nicht auf 0x0000 zeigt sondern auf 0xE000, wird auf 0x6000 (wordadress) 
gesprungen obwohl er bei 0x7000 landen sollte.

Mein Workaround bisher:
1
#define BOOTLOADER_START_ADDRESS    0xE000
2
#define jump_to_bootloader()   asm volatile ("jmp %a0 :: "i" \
3
                                 ((uint32_t)(BOOTLOADER_START_ADDRESS) & 0x0000FFFFuL));

Leider ohne automatischer Unterscheidung bei Sprungadressen grösser 
0xFFFF.

Hat hierzu vlt. jemand noch eine Idee?

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.