Hallo zusammen,
nachdem ich vergeblich versucht habe den DFU-Bootloader so abzuspecken,
dass man ihn auch mit AVR-GCC kompilieren kann damit er in den 4KB
Bootbereich des Xmega32A4U passt (weniger als 6K schafft man
offensichtlich mit avr-gcc nicht), habe ich einen anderen Weg gefunden
den Boot-Port für meine Ansprüche anzupassen und zwar ohne den
IAR-Compiler zu verwenden.
Dafür habe ich einfach mit objdump mit den Assembler-Code des Hex-Files
ausspucken lassen und dank des mitgelieferten Quellcodes auch schnell
die paar Werte gefunden um den Port und Portpin der den Bootloader
aktiviert (standardmäßig PC3 beim Atxmega32a4u) anzupassen. Prinzipiell
geht das bei jedem DFU-Bootloader binary.
Nachdem man sich Paket mit dem DFU 1.04 von der Atmel Seite
runtergeladen hat läd man einfach das passende Hex-File im Editor.
Parallel dazu sollte man das µC-Spezifische Datenblatt öffnen und im
Kapitel "Peripheral Module Address Map" nachschauen wie die Adresse des
gewünschten Ports ist. Die Adresse des vom Bootloader vorgesehen Ports
variiert je nach Xmega:
XMEGA_A1U: PORTF PIN 0
XMEGA_A3U, XMEGA_A3BU, XMEGA_C3: PORTE PIN 5
XMEGA_A4U, XMEGA_C4: PORTC PIN 3
XMEGA_B PORTC: PIN 6
Oder man schaut einfach direkt iox*.h File nach.
Die Hex-Files zwischen den verschiedenen Xmegas unterscheiden sich
natürlich etwas, aber über objdump bekommt kommt man schnell die
gewünschte Position, da die Abfragen immer gleich sind:
Nun ändert man die Adresse des Ports (bzw. PortRegister) im Hexfile ab.
Es sind genau 3 Adressen (PORT-Adresse, PORT-CTRL, PORT.IN) und eine
Pin-Nummer die angepasst werden müssen. Glücklicherweise befinden sie
sich alle in den ersten 4-Zeilen des Hex-Files.
Da jeder Port immer einen Offset von 0x20 zum nächsten hat ist es recht
einfach.
Für den Atxmega32a4u bei dem der Default-Port PORTC.3 und man ihn auf
PORTA.2 ändern will sieht das so aus:
1
Vorher Adresse | Nachher Adresse
2
PORTC_DIR 0x640 | PORTA_DIR 0x600
3
PORTC_IN 0x648 | PORTA_IN 0x608
4
PORTC_PIN3CTRL 0x653 | PORTC_PIN2CTRL 0x612
Die entsprechenden Adressen können direkt ins iHex eingetragen werden
(achtung Big-Endian, also Bytes verdrehen)
Hier das Original Hex-File:
1
:020000020000FC
2
:1080000000C00091780005FD6AC0F092400608E1CA
3
^^^^-> PORTC_DIR = 0x0640
4
:10801000009353060FEF0A950023E9F700914806F5
5
^^^^-> PORTC_PIN3CTRL ^^^^-> PORTC_IN = 0x0648
6
:1080200003FFECC0E0E0F0E0079116910F3F19F478
7
^^-> PIN3
und hier die geänderte Version für PORTA.2
1
:020000020000FC
2
:1080000000C00091780005FD6AC0F092000608E10A
3
^^^^-> PORTA_DIR = 0x0600
4
:10801000009312060FEF0A950023E9F70091080676
5
^^^^-> PORTA_PIN2CTRL ^^^^-> PORTA_IN = 0x0608
6
:1080200002FFECC0E0E0F0E0079116910F3F19F479
7
^^-> PIN2
Natürlich muss noch jeweils am Ende jeder Zeite die Checksumme neu
berechnet werden. Das kann man am einfachsten machen indem man das
geänderte Hex-File einfach mit obj-dump läd, das sagt einem dann welche
Checksumme erwartet wird (leider in Dez, muss also noch in Hex
umgerechnet werden). Also z.B. "obj-dump -D -m avr c:\boot_neu.hex"
Vielleicht hilft's ja noch jemanden.
Ah, interessant... habe mir aber dazu den IAR geladen... da ja bis 4 kb
die Liezens nicht abläuft...
Zwei Fragen:
Wie hast du die XMega Hex Dissambliert? Gibts da ein Programm oder
musstest du das händisch machen? (Hab das vom AtMega probiert, dass will
aber nicht mit der XMega Hex)
und dann noch: Hast du das Problem auch, wenn du USB als VirtualCom drin
hast und dann zum Bootloader springst, dass das USB Laden im Bootloader
fehl schlägt?
Hier wurde das Problem angesprochen:
http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=122461
Die habens dann über den Zwischenspeicher im EEPROM gelöst... und einen
Watchdog reset... nicht besonders schön :-/
Grüße
BAsti
Basti M. schrieb:> Wie hast du die XMega Hex Dissambliert? Gibts da ein Programm oder> musstest du das händisch machen? (Hab das vom AtMega probiert, dass will> aber nicht mit der XMega Hex)
Hab ich doch geschrieben, das geht mit objdump (ist ja beim avr-gcc
dabei). "objdump.exe -D -m avr hex_file.hex"
> und dann noch: Hast du das Problem auch, wenn du USB als VirtualCom drin> hast und dann zum Bootloader springst, dass das USB Laden im Bootloader> fehl schlägt?
Ich habe bisher nichts mit dem USB gemacht außer eben den
DFU-Bootloader.
Basti M. schrieb:> Ah, interessant... habe mir aber dazu den IAR geladen... da ja bis 4 kb> die Liezens nicht abläuft...
Kannst Du mir erklären, wie Du dies gemacht hast? Ich versuche dies auch
mit dem Code für den ATXMEGA 128A4U. Dies funktioniert bei mir aber
nicht.
Vorgehensweise:
- IAR KickStart Version (4k) installiert.
-
common.services.usb.class.dfu_atmel.device.bootloader.atxmega128a4u.zip
entpackt
- Projekt in IAR geöffnet.
- Make
-> Es erscheint die Meldung:
Building configuration: bootloader_xmega - Debug
Updating build tree...
isp.c
main.c
nvm.c
sysclk.c
udc.c
udi_dfu_atmel.c
udi_dfu_atmel_desc.c
usb_device.c
Linking
Fatal Error[e89]: Too much object code produced (more than 0x1000 bytes)
for this package
Error while running Linker
Total number of errors: 1
Total number of warnings: 0
Funktioniert das mit der 4k Version nur bei bestimmten Controllern? Oder
gibt es hier einen Trick?. Wäre schön, wenn Du, oder jemand anderes, mir
hierbei helfen könnte.
Gruß
Lars
Hi
>- IAR KickStart Version (4k) installiert.
Wenn dein Compiler nur max. 4k Code erzeugen kann, was vestehst du dann
an der Meldung
>Fatal Error[e89]: Too much object code produced (more than 0x1000 bytes)
nicht? 0x1000 = 4096 Byte.
MfG Spess
spess53 schrieb:> Wenn dein Compiler nur max. 4k Code erzeugen kann, was vestehst du dann> an der Meldung>>>Fatal Error[e89]: Too much object code produced (more than 0x1000 bytes)>> nicht?
Dass das erwartete Resultat ja kleiner als 4 KiB sein sollte, weil
es sonst ohnehin nicht in die boot section passt.
Optimierungen im Projekt eingeschaltet?
Naja der 128A4U hat ja 8k Bootbereich, dennoch sollte man natürlich die
Compiler Optimierungen an machen. Denn der freie IAR hat ja auch ne 4k
Begrenzung.
Ich glaube im bootloader sind Optimierungen drin die nur bei Controllern
mit 4k bootloader Bereich aktiv ist. Die größeren xmegas kommen dann mit
4k nicht mehr aus. Muss man noch mal genauer gucken.
Zumindest beim AVR-GCC erhöht Inlining den Code drastisch.
Er macht nämlich keine Analyse, wie oft was aufgerufen wird.
D.h. er inlined ohne mit der Wimper zu zucken auch 100 mal.
Timmo H. schrieb:> Ich glaube im bootloader sind Optimierungen drin die nur bei Controllern> mit 4k bootloader Bereich aktiv ist. Die größeren xmegas kommen dann mit> 4k nicht mehr aus. Muss man noch mal genauer gucken.
Da ich gerade das selbe Problem habe, habe ich genau dies gemacht. Es
fallen ja schon die Größenunterschiede bei den mitgelieferten Files auf:
Only in atxmega128a4u/common/services/usb/class/dfu_flip/device/bootloader/xmega: atxmega128a4u
3
Only in atxmega32a4u/common/services/usb/class/dfu_flip/device/bootloader/xmega: atxmega32a4u
4
Only in atxmega32a4u/common/services/usb/class/dfu_flip/device/bootloader/xmega: sysclk_opt.c
5
Only in atxmega128a4u/common/services/usb/udc: udc.c
6
Only in atxmega32a4u/common/services/usb/udc: udc_dfu_small.c
Insbesondere in udc/udc_dfu_small fällt auf, dass die abgespeckte
Variante deutlich mehr statische Annahmen macht, wobei ich das jetzt
auch nicht weiter verfolgen werde, sondern den "bequemen" Weg mit
Patchen des Hex-Files gehe ;)
Grüße
Moritz
Klar die anderen Controller haben mehr Platz im Boot Bereich, darum wird
dort auch weniger abgespeckt. Aber im Prinzip steht am Anfang genau das
gleiche. Schau dir mal das hex mit objdump an der gleichen Adresse an.
Timmo H. schrieb:> Vielleicht hilft's ja noch jemanden.
Ja, Danke!
Ich habe bei meinem ATXmega128A4U den Boot-Pin auf Port E, Pin 1
gesetzt.
Für den ATXmega128A4U ist der Boot-Pin "PC3", also 0x640 + 0x13
1. Wert in der Obj-Datei ändern:
Gleich am Anfang des Object-Codes der Datei "atxmega128a4u_104.hex" ist
der Eintrag für den zu testenden Pin.
0x640 = PortC, Pin3 = +13 => 0x653
//-------------------------------------------------------------
Der Hinweis auf die Fehlermeldung des objdump-Befehls war gut, so muss
man die Prüfsumme nicht selbst berechnen.
Wenn man den "avr-objdump"-Befehl noch mal auf der veränderten
"atxmega128a4u_104.hex" ausführt, dann wird ein Fehler ausgegeben mit
der Nachricht welche Prüfsumme erwartet wird.
Beim ersten mal ausführen wurde zum Beispiel gesagt dass 50(0x32) als
Prüfsumme erwartet wird, aber anstatt dessen 114(0x72) gefunden wurde.
Hier sind die richtigen Prüfsummen:
Start/Byteanzahl/Adresse/Typ/Daten/Prüfsumme