Ich habe für meinen ATmega128 einen Bootloader geschrieben. Dabei wird Zeichen für Zeichen das Image übertragen. Die Bestätigung erfolgt durch zurücksenden des selbigen Zeichens. Die Geschwindigkeit ist okay, klnnte aber sicher besser sein. Folgende Ideen zur Optimierung habe ich und würde gern wissen, welche Möglichkeiten sinnvoll sind: - in Blöcken senden, also 8, 16 oder ähnlich und Checksumme errechnen und nur die Checksumme vom Slave zurücksenden, anstatt die Zeichen zu "echo'en" - in Blöcken senden, also 8, 16 oder ähnlich und diese auch in einem Stück zurücksenden Machen die Änderungen überhaupt Sinn oder sollte ich es lassen, wie ich es habe? Bei der ersten Möglichkeit müsste ich auch noch eine Adresse mitsenden, da sonst kein Eingriff im Fehlerfall möglich wäre.
Ein Blockübertragung wirst Du Dir spätestens wünschen sobald Du mit USB -> RS232 Umsetzern arbeiten musst. Das wird bei einzelnen Bytes extrem langsam. Zur Blockgröße: Warum nicht gleich die flash-pagesize verwenden?
Naja auf 256 Bytes wird die Checksumme dann nicht mehr so real sein, denke ich. Es sei denn ich erhöhe sie auf 16 Bit. Ist die Flashpagesize immer gleich oder differiert die zwischen den einzelnen AVRs? Spätestens da wird es interessant, wo man den Bootloader anpassen muss. Aber ich denke ich werde das wirklich mit der Blocksache so realisieren.
Hallo Ronny, die Größe der Pages differiert. Das ist auch der Grund, warum Atmel sich in der AppNote 109 "Self programming" ein wenig verbiegt. Wenn Du Deinen Bootloader optimieren willst, dann schau die mal die beiden Appnotes 109 und 911 von Atmel an. Die beschreiben eine Kombination aus Bootloader und PC-Software zum Programmieren. Der Vorteil des (auch von mir eingesetzten) Modells liegt in der leichten Anpassbarkeit an andere Mikrocontroller aus der AVR-Familie. MfG, Daniel. P.S.: Der Bootloader wurde übrigens von mir nach WinAVR portiert.
Ronny, was Du implementiert hast, ist ein so genanntes "Stop and Go Protocol". D.h. der Sender überträgt ein Datenpaket (kann auch nur ein Byte sein) und wartet bis der Empfänger eine Antwort schickt und überträgt dann das nächste Paket etc. Dieses Verfahren ist immer langsam, weil Du nur maximal die Bandbreite in einer Richtung nutzen kannst. In Deinem speziellen Fall, der Byteweisen-Übertragung, nutzt Du nur maximal die halbe Bandbreite der seriellen Verbindung. Denn der Sender sendet in einer Zeiteinheit ein Byte. Nun muss er aber eine Zeiteinheit warten in der der Empfänger ein Byte sendet. D.h. die hälfte der Zeiteinheiten in der der Sender senden könnte, wartet er und sendet eben nicht. Und noch deutlich langsamer wird es, wenn Sender und Empfänger noch Latenzzeiten haben in der Größenordnung der Übetragungszeiteinheiten. D.h. wenn sie nicht sofort antworten, sondern erst etwas ausrechnen müssen und deshalb noch mehr Zeit vergeht und dann antworten. Die einfachste Lösung des Problems ist schon mal, die Senderpakete größer machen, und die Paket die vom Empfänger zurück geschickt werden möglichst klein zu halten. Aber selbst dann erreichst Du nie 100% Bandbreite. Die einzige Möglichkeit besteht darin, eine Art "Fenster" zu verwenden. D.h. der Sender sendet unentwegt die Daten, und sendet z.B. bis zu 5 unbestätigte Datenpakete an den Empfänger. Der Empfänger wiederum bestägt jedes Datenpaket sofort, wenn er es komplett erhalten hat. Im Idealfall sieht das dann so aus. 1.) Sender sendet erstes Paket komplett, erhält keine Bestätigung. 2.) Sender sendet sofort danach das zweite Paket an den Empfänger. 3.) Während der Sender das zweite Paket sendet, empfängt er die Bestätigung für das erste Paket. 4.) Sender sendet unverzüglich nach dem zweiten Paket das Dritte. 5.) Währed der Sender das dritte Paket sender, erhält er die Bestätigung für das zweite Paket. 6.) ... 7.) Der Sender sendet das letzte Paket und erhält währed dessen die Bestätigung für das vorletzte Paket. 8.) Der Sender hat aufgehört zu senden und muss nun auf die Bestätigung des letzten Pakets warten. So in etwa funktionieren Netzwerkprotokolle im Internet. Nur so ist eine schnelle Datenübertragung möglich. Was die Sache eben etwas komplizierter macht, ist wenn Pakete frisch gesendet werden sollen, oder der Empfänger zu langsam ist etc. Gute Literatur, ein Klassiker, zu diesem Thema ist: "Computer Networks" von Andrew S. Tanenbaum http://www.amazon.de/exec/obidos/ASIN/0130384887/
Ich bedanke mich für die vielen Ratschläge. Allerdings so riesig Unterlagen wälzen wollte ich jetzt nicht. Deshalb habe ich meinen Code jetzt weitgehend fertiggestellt. Ist zwar noch nicht gestestet, aber so solls laufen: Bootloaderprogramm wird auf PC gestartet und wartet bis sich der Slave meldet. Dann passiert folgendes: - Übertragung der Blockgröße vom Slave (PGM_PAGESIZE) - Übertragung der Blocknummer vom Master - Übertragung der Dtaen im Block vom Master (wichtig bei Dateiende, sonst PGM_PAGESIZE) - Übertragung der Daten vom Master - Übertragung der Checksumme der Daten vom Slave Stimmt die Checksumme nicht, wird der gleiche Block erneut übertragen. Ich denke so kann die Lösung aussehen udn wird sicher auch schneller sein. Was meint ihr?
Also Punkt 3 meine ich: - Übertragung der Datenpaketgröße .. wichtig bei Dateiende, sonst immer PGM_PAGESIZE hatte mich da etwas verwirrt ausgedrückt.
Interessant. Müßte ausreichend sein. Werde das Schema mal auf meinen Bootloader anwenden. Zur Zeit ist er halt noch im "Versuchsstadium". Er überträgt und flashed perfekt. Habe aber noch keine Fehlererkennung à la Checksumme integriert. Wie berechnest Du deine? Einfach alle Bytes aufaddieren in eine 16-bit Variable? Wäre das Einfachste. Ich bin auch begeistert von dem Bootloader, da er so schön schnell ist und ich meine Controller jetzt über RS232 und mit Wandler über USB flashen kann. Mega16 ist in ca. 3sek beschrieben(Flash-Sektion ohne Bootloader-Sektion =15kB - leider noch ohne Checksummen-Prüfung), nicht wie bei PonyProg, das immer ne Ewigkeit braucht und ich immer noch Zusatzkabel ranklemmen muß. MfG Barti
Also ich hatte jetzt noch einen Fehler in der Checksummenprüfung, der jetzt behoben ist. Die Übertragung funktioniert super und auch schnell. Und ja ich addiere einfach die Datenbytes in 16 Bit. Der Flashvorgang scheint aber noch nicht zu funktionieren. Die Byte-für-Byte-Version ging. Warum das jetzt nicht geht, weiß ich auch noch nicht. Sollte eigentlich funktionieren. Der Flash bleibt aber leer. Das werde ich mir bei Zeiten mal ansehen. Ich habe mal den Quellcode des bootloaders rangehangen. Wen es interessiert... aber wie gesagt der Flashvorgang geht noch nicht so recht.
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.