Hallo zusammen.
Ich habe ein Problem mit meinem ATMega1284:
Ich versuche einen Bootloader zu schreiben, der Daten per I2C entgegen
nimmt.
Das Programm ist zur Hälfte fertig - Ich kann Daten per I2C senden und
empfangen. Nun möchte ich aber das Programm in die entsprechende
Bootloadersektion 0xF000 schreiben.
Ich habe die BOOTRST Fuse gesetzt, und anschließend in der Linker GUI
die Sektion .text=0xF000 definiert, woraufhin das Studio einen
Linkeraufruf mit .text=0x1E000 erzeugt.
Wenn ich nun dieses Programm flashe, funktioniert aber leider nichts.
Beim Laden per JTAG springt er im Assembler an Adresse 0xF306. Es sieht
aber so aus, als ob das Programm an die Stelle 0xF000 geschrieben worden
wäre.
Habe ich noch irgendwas vergessen? Hat jemand schon selbst einen
Bootloader in AVR Studio 6 erstellt?
Gruß,
Dirk
Das sieht etwas nach dem byte-word Problem bei den AVRs aus. 0xF000
sieht nach einem 8kB Bootloader aus, damit liegt der Bootloader bei
0x1E000, soweit ich weiß braucht der Linker immer die Adressen im byte
Format und nicht Word Format, damit musst du im Linker die text sction
auf 0x1E000 legen.
Wenn du interrupts verwendest musst du diese auch an den Bootloader
anpassen.
Es kann auch ganz hilfreich sein sich das Hexfile mal mit einem anderen
Tool anzuschauen, um herauszufinden wo der Code nun wirklich liegt, ich
verwende dazu immer das Segger J-Flash Tool.
Ich habe die Ursache gefunden:
Das Problem lag am MCUCR:
Der Code
1
temp = MCUCR;
2
MCUCR = temp | (1<<IVCE);
3
MCUCR = temp | (1<<IVSEL);
funktioniert bei mir nie (Weder im AVRSim, noch auf der HW). Auf
höchster Otimierungsstufe scheint er die geforderten 4 Takte nicht
einhalten zu können.
1
MCUCR = (1<<IVCE);
2
MCUCR = (1<<IVSEL);
Funktioniert dagegen ab Compilerstufe 1!!! Damit funktionieren nun
endlich die Interruptroutinen...
Das ORI zwischen den beiden OUT-Befehlen dauert ja nur einen Takt, damit
sollte die 4-Takte-Bedingung noch erfüllt sein.
Allerdings gibt es keinen wirklich Grund für diese Veroderung.
Dirk Hölscher schrieb:> Nur halt -O0 geht nicht...
Ohne Optimierung wird der Index von mcucr_write zur Laufzeit
ausgewertet, das dauert halt länger als 4 Zyklen.
Allerdings ist die Verwendung eines Arrays an dieser Stelle völlig
überflüssig, vor allem, da der erste Wert für beide Fälle eh immer
gleich ist.
KISS - keep is simple and stupid
Oliver
Dirk Hölscher schrieb:> Ihhh, Assembler :-)
Das ist der vom Compiler generierte Assemblercode.
Ich versteh' dein Gewürge mit dem Rücklesen des existierenden MCUCR
nicht. Das Teil hat nach einem Reset einen wohl definierten Wert
(nämlich 0), da kannst du doch einfach drauf schreiben, statt solche
Verrenkungen zu machen.
Oliver schrieb:> Ohne Optimierung wird der Index von mcucr_write zur Laufzeit> ausgewertet, das dauert halt länger als 4 Zyklen.
Nachtrag:
Zumindest der gcc 4.3.3, den ich hier auf dem Rechner habe, erzeugt ohne
Optimierung auch ohne Array solch umständlichen Code, der schafft die 4
Zyklen ohne Optimierung auch ohne Array nicht.
Oliver
Jörg Wunsch schrieb:> Ich versteh' dein Gewürge mit dem Rücklesen des existierenden MCUCR> nicht. Das Teil hat nach einem Reset einen wohl definierten Wert> (nämlich 0), da kannst du doch einfach drauf schreiben, statt solche> Verrenkungen zu machen.
Stimmt schon. Ich komme halt aus einer großen Softwareschmiede, und da
ist es fatal einfach Andererleuts Register zu überschreiben. Also lieber
chirurgisch nur die Bits anpassen, die ich brauche... Geschmackssache...
Mir ging es aber hauptsächlich um folgende Aussage:
1
--- Bootloader.c --------------------------
2
MCUCR = (1<<IVCE);
3
0000F084 LDI R24,0x55 Load immediate
4
0000F085 LDI R25,0x00 Load immediate
5
0000F086 LDI R18,0x01 Load immediate
6
0000F087 MOVW R30,R24 Copy register pair
7
0000F088 STD Z+0,R18 Store indirect with displacement
8
MCUCR = (1<<IVSEL);
9
0000F089 LDI R24,0x55 Load immediate
10
0000F08A LDI R25,0x00 Load immediate
11
0000F08B LDI R18,0x02 Load immediate
12
0000F08C MOVW R30,R24 Copy register pair
13
0000F08D STD Z+0,R18 Store indirect with displacement
Danke für den Hinweis mit dem Dissassembler.
Das ist der Code, den der Compiler bei -O0 aus den beiden MCUCR =
Anweisungen macht. Wie man sieht, werden daraus pro Aufruf je 5
Anweisungen, was das Nicht-Funktionieren erklärt.
Kann es sein, dass er garnicht auf das MCUCR Register 0x35 zugreift? Ich
kenne mich in Assembler leider nur sehr schlecht aus...
Dirk H. schrieb:> Kann es sein, dass er garnicht auf das MCUCR Register 0x35 zugreift? Ich> kenne mich in Assembler leider nur sehr schlecht aus...
Doch, tut er. Nur hat das Register beim Zugriff per ld die Adresse 0x55.
Der Optimierer nutzt dann den out-Befehl, damit heisst das Register dann
0x35.
Datenblatt lesen bildet.
Oliver
Dirk H. schrieb:> Ich komme halt aus einer großen Softwareschmiede, und da> ist es fatal einfach Andererleuts Register zu überschreiben.
Du bist aber hier bei Mikrocontrollern, und bei denen ist oft genug
Effektivität wichtiger als stures Befolgen nicht immer sinnvoller
Richtlinien.
Aktionen wie das Einrichten der Vektortabelle gehören ohnehin mit
zu den ersten Dingen, die man nach einem Reset erledigt, insofern
ist es völlig legitim, dass sie vom Resetzustand des Controllers
ausgehen.
> Das ist der Code, den der Compiler bei -O0 aus den beiden MCUCR => Anweisungen macht.
Ja, -O0 eben. Das will man nicht benutzen, nicht freiwillig. Ist
wie einen Porsche zu fahren, aber die Handbremse angezogen zu lassen.
Jede Ente fährt dann schneller los.