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ß
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“.
> "/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.
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
Das wäre dann eher ein "out of reach", tritt vorzugsweise bei RJMP auf.
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......
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.
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 |
.
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...
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.