Hallo miteinander, Ich habe mir einen Bootloader (UART) für die Tinys und Megas geschrieben. Der funktioniert auch soweit gut; jedoch habe ich eine Sache nicht berücksichtigt: Die Lines aus der Hex/EEP müssen alle gleich lang sein. Ich habe gedacht, dass die boot Funktionen (mit page fill/write) das selbsttändig erledigen - aber nein. Wenn ich nun eine File sende, wo mal kurze und lange Einträge vorhanden sind kommt im Programm quark raus. Einheitlich genormt auf eine Länge funktioniert es wunderbar. Habe zwar ein Programm gefunden, welches das "umwandelt", aber leider nicht den Quellcode dazu. Mein Terminal läuft in VisualBasic - also dort müsste dann das Parsen passieren. Dieses Terminal verbindet sich auch via Serielle-Schnittstelle mit dem Controller. Das wandelt für die EEP habe ich hinbekommen (einfach den Rest mit FF aufgefüllt und die Checksumme angepasst). Das geht aber bei den Hex-Lines nicht. Die Checksumme bekomme ich berechnet, und ich weiß auch das man die Daten vom nächsten String "einfach" anhängt, aber wie verhalten sich dabei die Adresse? Klappt das auch so dann noch bei 256kb AVRs? Ich hoffe, jmd. kann mir helfen - ich würde es lieber in meinem Terminal (VB) machen, da der Bootloader mit knapp 2kb an der Grenze liegt (gerade bei den Tinys).
Dann machst du aber etwas grundlegend falsch beim Einlesen der Datei. Hier
1 | :1000000014C026C025C024C023C022C021C020C0E7 |
2 | ** |
steht die Länge der Daten in Bytes. Brauchst du nur lesen und auswerten bzw. im Programm berücksichtigen. Wenn du natürlich in deinen Programmen (Bootloader) davon ausgehst, dass das immer 16 Bytes wären, dann musst du eben mal ein wenig universeller und mit weniger Annahmen programmieren.
:
Bearbeitet durch User
Ach Karlheinz, Das klappt nicht wirklich, denn der TO wird vermutlich kaum den Linker oder Locator dazu überreden können, Zeilen fester Länge zu produzieren. Das ginge ja nur, wenn der erzeugte Code auch tatsächlich in solchen Stücken anfällt - und das tut er in aller Regel NICHT. Ihn dann aufzufüllen, wäre Mumpitz, denn da würde man ja Speicherstellen aud irgendwas festlegen, die garnicht Inhalt des MC sind. Das einzige, was der TO tun kann ist, seinen Bootlader den Regeln des Hex-Fileformates anzupassen - oder sich sein eigenes Format zu kreieren. Für die ganz kleinen PIC's gibt es sowas, da braucht der Bootlader nur exakt 100 Befehle und er läuft nur mit einem passenden Programm auf dem PC. Aber das dürfte ja sowieso nötig sein, denn zum Brennen eines längeren Programms brauct es nen Handshake zwischen PC und µC, weil das eigentliche Programmieren je nach Alter des Flashes im µC unterschiedlich lange brauchen kann. W.S.
- Im Terminalprogramm ein "binäres" Feld mit der Größe des Bootladers definieren und mit 0xff oder einer anderen genehmen Konstante füllen. - Das Hexfile in dieses Feld einlesen. - Die Daten des Feldes wieder in Hex mit konstanter Rekordlänge wandeln und programmieren. Alles andere geht auf Grund der Seitenstruktur des AVR Programmspeichers nur sehr mühsam. In einem Hexfile müssen nämlich nicht die Rekords mit den Adressen aufeinander folgend abgelegt sein.
Unmögliches wird sofort erledigt, Wunder dauern etwas länger. In Anbetracht der Tatsache, dass spätestens die letzte Zeile ihre "eigene" Anzahl an Bytes enthält, sollte es egal sein, wenn noch ein paar gute "Bekannte" dabei sind.
Amateur schrieb: > die letzte Zeile Das ist üblicherweise der Rekord mit der Startadresse. Der interessiert beim Flashen nicht.
Sorry, ich meinte natürlich die letzte "Code"-Zeile. Dass die Enderkennung nicht unbedingt übernommen werden muss, ist bei mir auch schon angekommen.
Hallo Marius, Marius Dege schrieb: > Die Checksumme > bekomme ich berechnet, und ich weiß auch das man die Daten vom nächsten > String "einfach" anhängt, aber wie verhalten sich dabei die Adresse? So wie du es in "Gewandelte.txt" gemacht hast wäre es richtig. Aber: In einer hex-Datei können auch Lücken entstehen, z.B. wenn man die sections explizit positioniert. Das Format lässt sogar zu, dass Fragmente in beliebiger Reihenfolge auftauchen oder Speicher sogar zweimal geschrieben wird - das wird in der Praxis aber wohl eher nicht auftauchen. Also entweder so wie von Georg vorgeschlagen den Flash-Speicher im Terminalprogramm nachbilden, die hex-Datei komplett einlesen, und dann den Speicher wieder als hex-Datei rausschreiben. Oder aber, besser, wie von Karl-Heinz empfohlen den Bootloader so erweitern dass er beiebige Längenbytes und Adressen verarbeiten kann und Fragmente sauber in den seitenweisen Flash programmiert. Marius Dege schrieb: > Klappt das auch so dann noch bei 256kb AVRs? Bei denen enthält die hex-Datei immer nach 64kB Typ 02 Einträge. Siehe http://de.wikipedia.org/wiki/Intel_HEX. LG, Sebastian
Sebastian Wangnick schrieb: > Oder aber, besser, wie von Karl-Heinz empfohlen den Bootloader so > erweitern dass er beiebige Längenbytes und Adressen verarbeiten kann und > Fragmente sauber in den seitenweisen Flash programmiert. Na ja. Ob das 'besser' ist, lass ich mal dahin gestellt. Besser ist es sicherlich im allgemeinen Fall nicht, weil ja, wie du richtig sagst, im Prinzip es keine Garantie gibt, dass die Records in aufeinanderfolgende Adressen zu liegen kommen. Aber: Im speziellen Fall hat man es meistens nicht mit dem allgemeinen Fall zu tun. Man kennt seine Tools und wie sie das Hex-File generieren und das ändert sich normalerweise nicht. Solange man damit leben kann, einen kleineren Subset von Hex-Files per Bootloader zum AVR zu übertragen, müsste das eigentlich möglich sein (Ohne jetzt den Aufbau seines Bootloaders zu kennen), den soweit zu pimpen, dass er wenigstens mit unterschiedlichen Längen im Data-Record klar kommt. Frickellösung ist es - zweifellos. Ob sie akzeptabel ist, dass muss der TO entscheiden. Zumal auch das Erstellen eines übertragbaren Files (muss ja kein HEx-File sein) aus einem Hex-File auf dem PC für einen Programmierer keine große Herausforderung ist. Georg G. hat ja schon angesprochen wie man das macht: Speicher bereitstellen und dann einfach das Hex-File Zeile für Zeile lesen und das was man dort vorfindet als Befehl auffassend auf diesen Speicher anwenden. Zum Schluss hat man ein 'Speicherimage' aus dem man sich dann das zu übertragende File generiert, egal welches Format dieses dann hat.
:
Bearbeitet durch User
Hallo Jungs, ich habe keine Mails bekommen, dass jmd. geantwortet hat, deswegen kommt jetzt erst meine Antwort. Dachte schon, es würde niemand schreiben. Mein Bootloader ist recht einfach aufgebaut: Ich sende immer eine ganze Zeile/Line der Hex-File welche ich im VB-Terminal einzeln zerlege (damit ich auch Processbar usw. verwenden kann). Die gesendete Line wird dann im BL zu HEX convertiert und es wird dort Checksum, Data, Rekord, Adresse gebildet. Damit hat man erstmal alles um via boot_fill_page eine Seite zu füllen. Danach wird dann (wenn die Seite voll ist), diese geschrieben. Blöd nur oben genanntes Problem. Wie kann der BL denn mit unterschiedlichen Längen klar kommen - ich stehe da echt auf dem Schlauch, wie man das dann auf eine Länge zusammenführen kann. Ich habe leider z.Zt. keine Ahnung wie ich das Problem im Bootloader oder im Terminal (Terminal wäre mir lieber, BL würde aber auch gehen wenn es einfacher ist) lösen kann, weil ich nicht so wirklich weiß, wie dieses Programm die "Gewandelte.txt" erstellt hat (außer das die Daten von der nächsten Line an die vorherige angehängt werden, und dann die Checksum neu berechnet wird; Datenlänge wird natürlich auch angepasst). Aber wie das tolle Programm da die Adressen berechnet - ?! Wie Sebastian Wangnick bereits gesagt hat: Die Adressen können in beliebiger Reihenfolge auftauchen, das tuen Sie dort auch, und deswegen bin ich dort mit der Adressenberechnung nicht durchgestiegen. Hast du evtl. eine Ahnung wie das "Gewandelte.txt" entstanden ist?! Ich kann euch gerne auch den Bootloader hochladen wenn gewünscht.
Karl Heinz schrieb: > Dann machst du aber etwas grundlegend falsch beim Einlesen der Datei. > Hier >
1 | > :1000000014C026C025C024C023C022C021C020C0E7 |
2 | > ** |
3 | > |
> steht die Länge der Daten in Bytes. Brauchst du nur lesen und auswerten > bzw. im Programm berücksichtigen. Wenn du natürlich in deinen Programmen > (Bootloader) davon ausgehst, dass das immer 16 Bytes wären, dann musst > du eben mal ein wenig universeller und mit weniger Annahmen > programmieren. Ich versuche eigentlich universell zu programmieren - hier hat es mich voll erwischt; habe ich ehrlich gesagt auch gar nicht dran gedacht an sowas. Weißt du denn, wie der BL auch mit unterschiedlich langen Lines klar kommen kann, bzw wie er diese handhabt?
Marius Dege schrieb: > Karl Heinz schrieb: >> Dann machst du aber etwas grundlegend falsch beim Einlesen der Datei. >> Hier >>
1 | >> :1000000014C026C025C024C023C022C021C020C0E7 |
2 | >> ** |
3 | >> |
>> steht die Länge der Daten in Bytes. Brauchst du nur lesen und auswerten >> bzw. im Programm berücksichtigen. Wenn du natürlich in deinen Programmen >> (Bootloader) davon ausgehst, dass das immer 16 Bytes wären, dann musst >> du eben mal ein wenig universeller und mit weniger Annahmen >> programmieren. > > > Ich versuche eigentlich universell zu programmieren - hier hat es mich > voll erwischt; habe ich ehrlich gesagt auch gar nicht dran gedacht an > sowas. > Weißt du denn, wie der BL auch mit unterschiedlich langen Lines klar > kommen kann, bzw wie er diese handhabt? ? Du schickst doch, wenn ich das richtig verstanden habe, die Zeile so wie sie ist zum Bootloader. Oder nicht. Der holt sich aus den ersten beiden Zeichen nach dem ':' die Anzahl der Datenbytes raus und weiß daher, was und wieviel nach der Datensatzkennung kommen muss. Wo ist da jetzt das große Problem?
Marius Dege schrieb: > wenn es einfacher ist) lösen kann, weil ich nicht so wirklich weiß, wie > dieses Programm die "Gewandelte.txt" erstellt hat (außer das die Daten > von der nächsten Line an die vorherige angehängt werden, und dann die > Checksum neu berechnet wird; Datenlänge wird natürlich auch angepasst). Man kann das natürlich so machen, wenn man davon ausgeht, dass die Datenbytes grundsätzlich aufsteigend im Speicher angeordnet sind. > Aber wie das tolle Programm da die Adressen berechnet - ?! Na komm. Das kannst du selbst auf Papier auch. Wenn du eine Startadresse von 10 hast, ich dir 7 Datenbytes gebe, danach 9 und dann nochmal 4, an welche Adresse kommt dann das nächste Byte? > bin ich dort mit der Adressenberechnung nicht durchgestiegen. Hast du > evtl. eine Ahnung wie das "Gewandelte.txt" entstanden ist?! Höchst wahrscheinlich (zumindest würde ich das so machen), genau so wie das beschrieben wurde: Datenrecord vom original lesen. Den dadurch codierten 'Befehl' (schreibe 8 Datenbytes beginnend ab Adresse xyz) in einem Array ausführen und wenn das File komplett gelesen wurde, dann schreib ich ein neues File basierend auf dem was ich an Daten im Array vorfinde. Das ist nicht wirklich schwer. Das sollte eigentlich jeder C-Programmierer in längstens 2 Stunden hinkriegen. Zumal das File-Format eines HEX-Files nicht sehr komplex ist.
:
Bearbeitet durch User
Hallo Marius, Marius Dege schrieb: > Mein Bootloader ist recht einfach aufgebaut: [...] > Die gesendete Line wird dann im BL zu HEX convertiert und es wird dort > Checksum, Data, Rekord, Adresse gebildet. Damit hat man erstmal alles um > via boot_fill_page eine Seite zu füllen. [...] > Ich kann euch gerne auch den Bootloader hochladen wenn gewünscht. Tu das mal. Ich versteh nämlich nicht mehr was du nicht verstehst :) LG, Sebastian PS: Ich bastele gerade an einem Internet-Bootloader (für mein Board mit Atmega1284P und W5500) und benutze dabei auch das hex-Format. Ich lade keine ganzen Zeilen sondern liefere alle einlaufenden Zeichen in einen hex-Zustandsautomaten, und von dort die Adressen und Datenbytes in einen Flash-Zustandsautomaten. Ich bin allerdings schon bei >4K UND es fehlt noch DHCP ... LG, Sebastian
Sebastian Wangnick schrieb: > Marius Dege schrieb: >> Mein Bootloader ist recht einfach aufgebaut: [...] >> Die gesendete Line wird dann im BL zu HEX convertiert und es wird dort >> Checksum, Data, Rekord, Adresse gebildet. Damit hat man erstmal alles um >> via boot_fill_page eine Seite zu füllen. [...] >> Ich kann euch gerne auch den Bootloader hochladen wenn gewünscht. > > Tu das mal. Ich versteh nämlich nicht mehr was du nicht verstehst :) Willst du mit mir eine Wette eingehen, was das EIGENTLICHE Problem ist :-)
Das Primitivste wäre wohl ein kleines Batchfile, das das Hexfile aufbereitet. hexbin %1.hex %1.bin binhex %1.bin %1.neu 0 Tunixe können das auch per Pipe zu einer Zeile zusammenfassen. Quältexte für hexbin und binhex gibt es auf Anfrage auch (einmal Turbopascal, einmal C).
Vielleicht hilft dir das:
1 | |
2 | if(nUdr == ':') //Neuer Hexstring |
3 | {
|
4 | nFrameInd = 0; |
5 | bNewFrame = true; |
6 | }
|
7 | //......
|
8 | |
9 | default: //Ascii-Daten (0..9, A..F, a..f) |
10 | nFrame[nFrameInd++] = nUdr; |
11 | nUdr = 0; |
12 | break; |
13 | |
14 | //....
|
15 | if(bNewFrame) |
16 | {
|
17 | //Länge ermitteln
|
18 | if(nFrameInd == 2) nData[0] = AsciiToByte(nFrame[0], nFrame[1]); |
19 | |
20 | if(nFrameInd == ((nData[0] * 2) + 10)) //Hexstring angekommen |
21 | {
|
22 | SendChar(XOFF); //Um Ruhe bitten |
23 | unsigned char nCsum = 0; |
24 | for (unsigned char nInd = 0; nInd < (nData[0] + 5); nInd++) |
25 | {
|
26 | //Datenbereich aus Hexstring umwandeln
|
27 | nData[nInd] = AsciiToByte(nFrame[nInd * 2], nFrame[(nInd * 2) +1]); |
28 | nCsum += nData[nInd]; |
29 | }
|
30 | if(!nCsum) |
31 | {
|
32 | //Adresse ermitteln und umwandeln auf Flashadresse
|
33 | UINT nAddress = (unsigned int)((nData[1] << 8) + nData[2]); |
34 | //....
|
Mit Längen- und Adressauswertung im Controller kannst du das Hexfile auch mit Hyperterminal oder sonstwas rüberschaufeln. Hauptsache der Knabe versteht XON/XOFF und müllt den Controller während er ins Flash brennt nicht zu. mfg.
:
Bearbeitet durch User
Hi, ich habe das für meinen ersten Bootloader (PIC24) alles am PC gemacht. Der PC wertet den Record aus, konvertiert das in Binärdaten und sendet das an den µC, mit den richtigen Adressen. Der Bootloader muss das nur ins Flash pinseln. Die Idee ist, dass der PC mit seinen schnellen Prozessor und großen Speicher die ganze Arbeit machen soll. Hat sich bewährt, weil man am PC besser debuggen kann und der Bootloader sehr dumm sein darf. Können muss er: - sicher kommunizieren (bei mir über Funk mit CRC) - Flash löschen - Flash schreiben / lesen - seine Version ausspucken - die Applikation starten Der Wikipedia-Artikel ist brauchbar: http://de.wikipedia.org/wiki/Intel_HEX Implementieren muss man nur die paar nrecord-typen die im Programmierfile vorkommen. Ich kann es wirklich empfehlen das selber zu machen, mir hats viel Spass gemacht. Anbei eine kleine Funktion zum decodieren. Ob es ohne Dokumentation hilft, weiß ich nicht. Sie dekodiert nur einen Record, nachfüttern (Pointer setzen) und Daten laden muss man selber.
> Na komm. > Das kannst du selbst auf Papier auch. > > Wenn du eine Startadresse von 10 hast, ich dir 7 Datenbytes gebe, danach > 9 und dann nochmal 4, an welche Adresse kommt dann das nächste Byte? > Das ist nicht wirklich schwer. Das sollte eigentlich jeder > C-Programmierer in längstens 2 Stunden hinkriegen. Zumal das File-Format > eines HEX-Files nicht sehr komplex ist. Warte mal: Ich starte bei Adresse 000, dann bekomme ich 8 Datenbytes ==> die nächste Adresse für die nächste Line ist dann 008? Das jetzt nicht dein ernst das das so einfach ist, oder? Wenn das so ist, war ich wohl irgendwie blind - dann ist das ja einfach mit der Adressmittelung.
Sebastian Wangnick schrieb: > PS: Ich bastele gerade an einem Internet-Bootloader (für mein Board mit > Atmega1284P und W5500) und benutze dabei auch das hex-Format. Ich lade > keine ganzen Zeilen sondern liefere alle einlaufenden Zeichen in einen > hex-Zustandsautomaten, und von dort die Adressen und Datenbytes in einen > Flash-Zustandsautomaten. Ich bin allerdings schon bei >4K UND es fehlt > noch DHCP ... > > LG, Sebastian Das hört sich krass an - leider ist keiner meiner Controller am Netz. Aber ich benötige noch einen Bootloader, der (sofern es nicht seine Firmware ist), die Daten via I²C an einen weiteren Controller schickt, welcher kein Bluetooth hat. Das wird auch noch interessant - aber ich kann dort auch nur bis 4k gehen (ATMega1284P). Dort wollte ich den alten erweitern.
Karl Heinz schrieb: > Sebastian Wangnick schrieb: > >> Marius Dege schrieb: >>> Mein Bootloader ist recht einfach aufgebaut: [...] >>> Die gesendete Line wird dann im BL zu HEX convertiert und es wird dort >>> Checksum, Data, Rekord, Adresse gebildet. Damit hat man erstmal alles um >>> via boot_fill_page eine Seite zu füllen. [...] >>> Ich kann euch gerne auch den Bootloader hochladen wenn gewünscht. >> >> Tu das mal. Ich versteh nämlich nicht mehr was du nicht verstehst :) > > Willst du mit mir eine Wette eingehen, was das EIGENTLICHE Problem ist > :-) Was ist denn das eigentliche Problem - Ich kann es euch aber gerne sagen: Ich habe den Adressaufbau beim .hex nicht wirklich verstanden. Aber jetzt ist es klar. Aktuelle Adresse + Datenbytes = Nächste Adresse. Danke für den Denkanstoß.
Marius Dege schrieb: > Warte mal: Ich starte bei Adresse 000, dann bekomme ich 8 Datenbytes ==> > die nächste Adresse für die nächste Line ist dann 008? Marius Dege schrieb: > Ich habe den Adressaufbau beim .hex nicht wirklich verstanden. Aber > jetzt ist es klar. Aktuelle Adresse + Datenbytes = Nächste Adresse. Nicht ganz. Die Adresse der nächsten Zeile steht immer in dem Header der Zeile. Nehmen wir mal eine Ausschnitt aus Normale.txt und streuen Leerzeichen und Zeilennummern ein: len addr typ data cksum Z1 : 10 00B0 00 E1F700C00000D9DF882389F3CE35D105 F0 Z2 : 10 00C0 00 31F4E0916000F09161000995E8CF83E8 98 Z3 : 0A 00D0 00 90E0D4DFE4CFF894FFCF F6 Z4 : 10 00DA 00 B004256900252E32660048616C6C6F2C CD Z5 : 10 00EA 00 20776965206765687420657320646972 82 typ ist bei allen reinen Datenzeilen 00. len gibt die Anzahl der Datenbytes in data. Oft ist len=0x10, also 16 Bytes an Daten. addr gibt die Adresse des ersten Datenbytes. data sind die Datenbytes. Das erste Datenbyte kommt an Adresse addr, das zweite and addr+1, das dritte an addr+2 und so weiter. Das letzte, also sozusagen das len'te, kommt an addr+len-1. Nur wenn ein grösserer zusammenhängender Datenbereich hex-kodiert ist (was aber fast immer der Fall ist), folgt in der nächsten Zeile dann addr(Z2) = addr(Z1)+len(Z1). In deinem Fall gilt dass auch für den Übergang von Z3 auf Z4. Z3 beginnt bei 0x00D0 und ist 0x0A lang. Z4 beginnt dann bei 0x00DA. Jetzt wird dir wohl auch klar, wie Gewandelte.txt entstanden ist. Die Datenbytes von 0xDA-0xDF aus Z4, also 0xB00425690025, wurden an die Datenbytes aus Z3 angehängt, um die Länge auf 16 zu erweitern. Die restlichen Datenbytes (0x2E32660048616C6C6F2C) beginnen eine neue Zeile mit Adresse 0x00E0, an die dann wieder Datenbytes aus Z5 angehängt werden um die Länge auf 16 zu bringen, und so weiter. Du fragst dich vielleicht: Warum aber ist in Normale.txt dieser blöde Bruch bei Z3. Das hat mit den Loader-Segmenten zu tun. Alles bis Z3 inklusive gehört zum .text-Segment, alles ab Z4 gehört (glaube ich) zum .bss-Segment (also zu den im Flash gespeicherten Daten die benötigt werden, vor dem Programmstart die Variablen im SRAM zu initialisieren). Wenn du das genau wissen willst, brauchst du die zur hex-Datei gehörende elf-Datei. Die kannst du mit avr-objdump -h -S dekodieren und dir die vom Loader generierten Segmente anschauen. Bei uC mit >64kB Flash gibt es dann noch, wie oben erwähnt, die typ 02 Zeilen. Dabei ist len 02, addr 0000, typ 02, und es gibt zwei Bytes data. Das unterste Nibble ist immer 0, siehe Wikipedia. data wird um ein Nibble linksgeshiftet und fortan noch zu addr dazugerechnet. Also, wenn die folgende Zeile erscheint,
1 | :020000021000EC |
dann wird data (0x1000) um ein Nibble linksgeshiftet (=0x10000), und danach immer zu addr hinzugerechnet. Also aus addr 0x0010 in irgend einer Folgezeile wird dann tatsächlich die Flash-Adresse 0x10010. LG, Sebastian
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.