Hallo Gemeinde,
ich habe einen Artikel (mein Erster!) über das Programmieren von
Bootloader für den AVR in C geschrieben. Eigentlich sollte es nur eine
Wissensammlung sein aber es ist jetzt mehr ein Tutorial geworden.
Es wäre schön, wenn die Gurus unter euch das mal drübergucken könnten
und Feedback über grobe Fehler oder Anmerkungen geben könnten. Es wäre
auch schön, wenn es jemand Ausprobieren würde. Idealerweise jemand der
noch nicht viel mit Bootloadern gearbeitet hat.
Hier der Link zum Artikel:
AVR Bootloader in C - eine einfache Anleitung
Der Artikel ist fast fertig (es fehlen noch ein paar Bilder).
Gruß
Mario
Mario Grafe schrieb:> @Turmel:>> es sollte nicht so stocksteif rüberkommen. Ich fands lustig so.
Dann frag halt nicht nach Kritik, wenn Du für Dich selbst schreibst.
Turmel schrieb:> Mario Grafe schrieb:>> @Turmel:>>>> es sollte nicht so stocksteif rüberkommen. Ich fands lustig so.>> Dann frag halt nicht nach Kritik, wenn Du für Dich selbst schreibst.
Ich schreibe nicht (nur) für mich. Ich hoffe das auch einige andere
etwas mit dem Artikel anfangen können. Die Kritik zum Schreibstil nehme
ich gerne an, der nächste Artikel wird förmlicher. Aber den
Bootloader-Artikel schreibe ich jetzt nicht nochmal komplett um
deswegen. Das ist mir zuviel Aufwand. Wer damit nicht leben kann der
soll ihn halt nicht lesen.
Es wäre gut wenn auch inhaltliche Kritik käme oder mal jemand den Code
ausprobiert...
Mario Grafe schrieb:> Turmel schrieb:>> Mario Grafe schrieb:>>> @Turmel:>>>>>> es sollte nicht so stocksteif rüberkommen. Ich fands lustig so.>>>> Dann frag halt nicht nach Kritik, wenn Du für Dich selbst schreibst.>> Ich schreibe nicht (nur) für mich. Ich hoffe das auch einige andere> etwas mit dem Artikel anfangen können. Die Kritik zum Schreibstil nehme> ich gerne an, der nächste Artikel wird förmlicher.
Das ist ein Irrtum. Es geht nicht um förmlich oder nicht förmlich. Ich
habe das auch garnicht geschrieben. Wie kommst Du darauf? Ist das eine
Verwechslung? Ich schrieb von schlechtem Deutsch. Man kann locker
schreiben und trotzdem grammatisch korrekt.
> Es wäre gut wenn auch inhaltliche Kritik käme oder mal jemand den Code> ausprobiert...
Ich lese das halt nicht wenn ich bei jedem dritten Wort stolpere. Tut
mir leid.
Ich will ja nicht wirklich insistieren.
Aber das mir jemand unterstellt ich würde seinen lockeren Stil meinen,
wenn ich von seinem Deutsch, also Grammatik und Diktion rede macht mir
nicht gerade Mut mit ihm eine Diskussion über eines der beiden Themen
"Stil" und "Grammatik" anzufangen.
Kleines Beispiel:
"Zu Beginn soll das notwendigste Wissen über den AVR-Bootloaderbereich
vermittelt werden, um eine Arbeitsgrundlage zu schaffen."
Wieso das "notwendigste"? Warum die Steigerung ins Absolute? Das
notwendige Wissen für eine Arbeitsgrundlage würde schon reichen.
Wozu diese Schwurbel-Substantiv "Bootloaderbereich"? Ist damit das Thema
gemeint oder der Speicherbereich?
Also lassen wir das lieber.
Es gibt soviele Artikel im Web über Bootloader das ich auf den
verzichten kann.
Turmel schrieb:> Ich lese das halt nicht wenn ich bei jedem dritten Wort stolpere. Tut> mir leid.
Rechts oberhalb eines jeden Abschnitts gibt es einen link "Bearbeiten".
Den darfst du gerne für den letzten sprachlichen Feinschliff nutzen.
Auch konkrete Verbesserungsvorschläge helfen sicherlich weiter.
Also: Besser machen, oder Schnauze halten.
Ich finde den Beitrag klasse.
Oliver
Also ich habe den Artikel nur mal grob überflogen. Mein erster Eindruck:
aufwendig gestaltet (@Turmel: ich weiss, nach der ndR aufwändig) und gut
lesbar.
Über die fachliche Solidität kann ich jetzt nichts sagen, aber ich würde
ihn zumindest mal dankbar lesen wenn ich mich in das Thema einarbeiten
wollte.
Von so einem Engagement lebt jedes Wiki.
Vieleicht sollte uns Turmel mal seine Artikel verlinken auf dass wir
noch was lernen können. :-)
Hast du pos./neg. Erfahrungen/Empfehlungen zur Verwendung eines
seriellen Bootloaders, wenn mit dem internen RC-Oszillator (statt
genauerem externen Taktgeber) gearbeitet wird?
Vielen Dank für die Blumen.
Stefan B. schrieb:> Hast du pos./neg. Erfahrungen/Empfehlungen zur Verwendung eines> seriellen Bootloaders, wenn mit dem internen RC-Oszillator (statt> genauerem externen Taktgeber) gearbeitet wird?
bei 9600 Baud mit ca. 0.2% Fehler geht es mit dem internen Takt von 8Mhz
wunderbar, mit 19200 Baud auch. Die Baudratentabelle im Datenblatt hilft
da weiter. Um ein STK500 zu simulieren, muss 115200 Baud unterstützt
werden. Dafür ist ein externer Quarz unverzichtbar.
Mario
Turmel schrieb:> Aber das mir jemand unterstellt ich würde seinen lockeren Stil meinen,
^^^ ^
dass ,
> wenn ich von seinem Deutsch, also Grammatik und Diktion rede macht mir
^
,
> nicht gerade Mut mit ihm eine Diskussion über eines der beiden Themen
^
,
> "Stil" und "Grammatik" anzufangen.
4 Fehler in einem Satz. Glashaus, Steine.
Mario Grafe schrieb:> Es wäre schön, wenn die Gurus unter euch das mal drübergucken könnten> und Feedback über grobe Fehler oder Anmerkungen geben könnten.Zum Layout
Hat Potential für Verbesserungen :-)
Beispiel:
#1
Verwende gescheite Einrückungen für die Quelle! Hier sieht man den
Grund, warum man keine TABs zm Einrücken nehmen sollte: Es sieht
überall anders aus. Ergo: Einrücktiefe zB 4, und zwar mit Leerzeichen
.
#2
Ganz offenbar stammt die Quelle von mehreren Autoren. Dennoch sollte
ein Stil durchgehalten werden.
#3
Viele Quell-Zeilen sind zu lange. Da diese nicht umgebrochen werden,
führt das dazu, daß die komplette HTML-Seite diese Breite bekommt und
breitenmässig nicht mehr auf einen Bildschirm passt (Display 1024 pix).
Zum Lesen muss beständig links-recht gescrollt werden. So macht das
Lesen keinen Spaß!
Zum C-Code
#4
Warum wird teilweise uint8_t verwendet, teilweise unsigned char? dito
16-Bit Typen?
#5
1
do
2
{
3
c=uart_getc();
4
5
if(c&UART_NO_DATA)
6
continue;
7
8
// 150 Zeilen Code
ist besser verständlich als
1
do
2
{
3
c=uart_getc();
4
if(!(c&UART_NO_DATA))
5
{
6
// 150 Zeilen Code
7
}
8
}
Zumal da bis zu 9(!) Einrückebenen folgen.
#6
Kommentare in der gleichen Zeile sind Geschmackssache (ich persönlich
mag's nicht), aber da die Zeilen teilweise erst bei Spalte > 70
beginnen, sollte das auf jeden Fall überdacht werden.
#7
Wozu wird an Adresse 0x0000 gesprungen? Sieht nach Hack aus...
#8
Vergleicht man die beiden Implementierungen
So fällt auf:
# die zweite Implementierung ist leichter verständlich, zumindest für
mich. Es gibt da keine magischen Zahlen und keine seltsame
Multiplikation über ein Konstanten-Array.
# Die zweite Version brauch ca. 80 Bytes, die erste rund 190 Bytes an
Code. An RAM braucht die zweite 2 Bytes für die Return-Adresse. Die
erste Version legt bei jedem(!) Aufruf mult als Array auf dem Stack an
und muss erst die Werte dort hinkopieren. Sie braucht 18 Bytes an Stack
(avr-gcc 4.3.3, -Os).
Ich weiß jetzt nicht wie großzügig man in einem Bootloader mit den
Resourcen haushalten kann...
#9
Für einige Aufgaben bieten sich Funktionen an, um den Spaghetti-Code
etwas zu entschärfen. ZB das Parser-Zeug. gcc wird das inlinen, und wenn
nicht, hat er gute Gründe dafür (inlining macht den Code auch bei einem
Aufruf nicht unbedingt kleiner). Variablen wie "flag" braucht's dann
nicht mehr, "c" lebt besser in dem Block, wo es verwendet wird...
Ok, hier mach ich mal Schluss, sonst find ich kein Ende... :-)
Und bitte nicht falsch verstehen. Ich schreib das nicht alles um
rumzumäkeln (das wär mit die Schreibarbeit nicht wert), sondern weil ich
Anregungen geben möchte. Text wird eben nicht nur über seine Buchstaben
wahrgenommen, sondern zum Großteil auch über sein Layout/seine
Typographie.
@Johann L.:
Danke, solche Anmerkungen und Anregungen habe ich gemeint. Wenn man
immer nur in seiner eigenen Suppe schwimmt, merkt man sowas nicht.
Sobald ich Zeit habe, werde ich mich über deine Vorschläge hermachen und
sie einarbeiten.
Die hex2num-Funktion von dir sieht tatsächlich viel besser aus, die
würde ich so übernehmen.Die Quellen stammen übrigens tatsächlich alle
von mir persönlich. Die falsche Einrückungen durch Tabs kommen durch das
Copy&Paste in den Wiki-Editor zustande, das habe ich übersehen. Da ich
einen ziemlich breiten Monitor habe sind mir einige "Breitenfehler"
nicht aufgefallen.
Hallo,
flash_cnt sollte vom Typ unsigned int sein, da SPM_PAGESIZE z.B. auf
einem Atmega644 256 ist und von flash_cnt somit nie erreicht werden
kann.
Grüße,
Olli
@ Johann L.:
ich habe jetzt schon einige Verbesserung des Layouts eingebaut (Tabs
entfernt, Kommentare in eigene Zeile). Es sieht tatsächlich besser aus
:)
Mein Funktion hex2num ist nicht besonders schön. Dein Vorschlag gefällt
mir besser, ich habe ihn so übernommen. Danke nochmal. Jetzt werde ich
mich noch mit dem "Hack" start() beschäftigen... er funktioniert zwar
aber ein vom WDT ausgelöster Reset ist besser denke ich.
Johann L. schrieb:> #7> Wozu wird an Adresse 0x0000 gesprungen? Sieht nach Hack aus...
Hallo Johann,
ich habe jetzt mal ausprobiert, den Bootloader mittels Watchdog reseten
zu lassen, aber dabei entsteht ein Henne-Ei-Problem. Der AVR springt ja
nach dem Reset immer wieder zuerst an Adresse 0x1800, dann wird nach 3
sec. wieder geresetet und er landet wieder bei 0x1800. Der Bootloader
springt also nie zur Anwendung weiter. Der "Hack" springt hart zur
Adresse 0x0000, eigentlich doch nicht so schlecht, was meinst du? Gibt
es noch eine andere Lösung die Anwendung loslaufen zu lassen?
Gruß
Mario
Mario Grafe schrieb:> Der "Hack" springt hart zur> Adresse 0x0000, eigentlich doch nicht so schlecht, was meinst du? Gibt> es noch eine andere Lösung die Anwendung loslaufen zu lassen?
Nein.
Der Resetvector ist ja auf den Bootloader verbogen und das läßt sich nur
per Fusebit ändern.
Du mußt nach 0x0000 springen, das ist die saubere Lösung (kein Hack).
Du kannst auch nach oben aus dem Bootloader rauslaufen (mit NOPs bis zum
Ende auffüllen), aber das würde ich als "dreckigen Hack" bezeichnen.
Peter
Mario Grafe schrieb:> Kennst du eine elegante Möglichkeit wie man die Fuses vom Bootloader aus> setzten kann?
Einen ATtiny25 an SPI + Reset anklemmen, und so programmieren, daß er
per ISP die Fuses ändert.
In der Regel sollte aber die Schaltung bekannt sein, in der der
Bootloader arbeitet, also sollte man die Fuses gleich richtig setzen
können.
Peter
Peter Dannegger schrieb:> Mario Grafe schrieb:>> Der "Hack" springt hart zur>> Adresse 0x0000, eigentlich doch nicht so schlecht, was meinst du? Gibt>> es noch eine andere Lösung die Anwendung loslaufen zu lassen?>> Nein.> Der Resetvector ist ja auf den Bootloader verbogen und das läßt sich nur> per Fusebit ändern.> Du mußt nach 0x0000 springen, das ist die saubere Lösung (kein Hack).
Das Problem mit "goto 0" ist, daß das kein Reset ist, sondern eben nur
ein "goto 0". Das initialisiert nicht die Hardware. Andererseits sind
viele Anwendungen so geschrieben, daß sie von einer initialisierten
Hardware ausgehen, zB Timer-Initialisierungen oder
UART-Initialisierungen etc. die |= verwenden beim Belegen von SFRs wo
sie eigentlich = meinen. Mit einer vor-initialisierten Hardware kann das
zu Problemen führen.
Ich sehe da 2 Lösungsansätze
A: Der Bootloader macht seine Initialisierungen rückgängig und schreibt
die entsprechenden Reset-Werte in die angefassten SFRs.
B: Man macht einen WDT-Reset und fragt nach dem Reset in Bootloader die
Reset-Ursache ab. War's ein WDT-Reset, folgt ein "goto 0". Nachteil: Die
Anwendung kann diesen Mechanismus nicht mehr verwenden, um nach einem
eigenen WDT-Reset neu aufzusetzten (zB wenn nach einem WDT nicht neu
initialisiert werden darf sondern an einem "Milestone" sicher aufgesetzt
werden muss)
Peter Dannegger schrieb:> Einen ATtiny25 an SPI + Reset anklemmen, und so programmieren, daß er> per ISP die Fuses ändert.>> In der Regel sollte aber die Schaltung bekannt sein, in der der> Bootloader arbeitet, also sollte man die Fuses gleich richtig setzen> können.
Gibt es keine Möglichkeit, die Fuses des eigenen AVR vom
Bootloaderbereich aus zu ändern? Hintergrund: Ich habe den Bootloader
daahingehend erweitert, das er sich wie ein STK500 verhält. Flashen usw.
klappt auch ganz wunderbar, nur die Fuses kann ich nicht ändern.
Dieser Bastler hier:
http://hubbard.engr.scu.edu/embedded/avr/bootloader/index.html
macht im Prinzip das gleiche, er muß es auch irgendwie gelöst haben,
leider gibt er die Quellen nicht raus. Ich dächte ich hätte so etwas
auch schon irgendwo mal gelesen, ich find es nur nicht mehr. Man muß
natürlich aufpassen, das man sich nicht aus dem Bootloader aussperrt,
aber das kann man ja abfangen. Nach dem Start hat man 3 Sekunden Zeit
sich über das AVRStudio mit dem AVR zu verbinden, dann springt er weiter
zum Programm, eigentlich ein schicke Sache. Wenn es fertig ist, werde
ich es mal posten.
Ich bin froh das du mal über meinen Code schaust, du hast ja selbst
schon einige Bootloader geschrieben und bist sehr aktiv und kompetent im
Forum unterwegs. Wie findest du den Artikel?
Mario Grafe schrieb:> Dieser Bastler hier:> http://hubbard.engr.scu.edu/embedded/avr/bootloader/index.html> macht im Prinzip das gleiche, er muß es auch irgendwie gelöst haben,> leider gibt er die Quellen nicht raus.
Ich denke das hast du misverstanden.
Der Bootloader selbst ändert keine Fuse Bits. Die muss man mit einem
richtigen Programmer umstellen, wenn man den Bootloader in den µC
brennt.
Karl heinz Buchegger schrieb:> Mario Grafe schrieb:>>> Dieser Bastler hier:>> http://hubbard.engr.scu.edu/embedded/avr/bootloade...>> macht im Prinzip das gleiche, er muß es auch irgendwie gelöst haben,>> leider gibt er die Quellen nicht raus.>> Ich denke das hast du misverstanden.> Der Bootloader selbst ändert keine Fuse Bits. Die muss man mit einem> richtigen Programmer umstellen, wenn man den Bootloader in den µC> brennt.
Aha, schade eigentlich. Sonst könnte man wenigstens noch die Taktquelle
ändern oder so. Kannst du bitte auch mal über den Artikel schauen ob
grobe Schnitzer drin sind, würde mich freuen. Schön wäre es auch wenn es
mal jemand ausprobiert :)
Hallo,
kleiner Tipp von mir, statt in jedem case Zweig Xoff und wieder Xon zu
schicken kannst du das auch vor und nach dem Switch machen. Danke für
den Artikel.
delay schrieb:> Hallo,> kleiner Tipp von mir, statt in jedem case Zweig Xoff und wieder Xon zu> schicken kannst du das auch vor und nach dem Switch machen. Danke für> den Artikel.
Da habe ich auch schon dran gedacht. Müßte man mal probieren. Könnte
sein das die Kommunikation dann langsamer wird da der AVR ständig den
Empfang stoppt.
Janein,
im Vergleich zu der jetzigen Implementierung kaum.
Besser wäre es die Flusssteuerung im der UART Module selbst zu machen.
Also wenn der Ringpuffer fast voll ist wird Xoff gesendet und erst wenn
wider ein Level unterschritten wird wird Xon. Aber dafür ist die
Implementierung von Peter Flury nicht ausgelegt.
Hallo Mario und vielen Dank erstmal für den guten Artikel!
Auf mich wirkte er tatsächlich sehr demystifizierend und hat mir erst
einmal ein grundsätzliches Verständnis für die Problematik gegeben.
Die Kommentare zur Rechtschreibung können wir mal getrost überlesen, die
zu Übersichtlichkeit des Quelltextes nicht ganz. Aber dazu wurden schon
genug Worte verloren.
Ich habe viel mehr eine konkrete Frage. Und zwar erschließt sich mir
bisher der Sinn der Verwendung des Intel-HEX-Formates nicht, wenn dieses
nur bewirkt, dass ich erst wieder einen Parser auf dem µC oder PC
brauche um es zu interpretieren. Warum lasse ich mir vom Makefile nicht
gleich mittels avr-objcopy eine Bin-Datei ausspucken und sende diese
dann via UART an den µC?
Daran schließt sich mir auch gleich noch eine zweite Frage an. Und zwar
bzgl. der Interpretation des Binärformates: Kann ich das so verstehen,
dass ich einfach stets 64 Bytes (1 Page) aus der Bin-Datei auslese und
diese nacheinander in die Speicherbereiche ab 0x0000 hochzählend
reinschreiben kann? Oder wie muss ich mir den Aufbau des Binärformates
vorstellen? Hab dazu nix richtig aussagekräftiges gefunden (zumindest
nichts was mir Klarheit verschafft hat ;-) ).
Danke schon mal für die Antwort(en).
Christoph P. schrieb:> brauche um es zu interpretieren. Warum lasse ich mir vom Makefile nicht> gleich mittels avr-objcopy eine Bin-Datei ausspucken und sende diese> dann via UART an den µC?
Dimit ginge zumindest kein XON/XOFF mehr, weil dann alle Hex-Werte
00..ff belegt wären. Zudem hat man so ne kleine Konsistenzpfüfung via
Prüfsumme.
Also ich finde die Lösung mit dem Hexfile auch ganz nett :)
Wenn man sich platz sparen möchte und keine Prüfung machen will kann man
ja auch den Parser abspecken.
z.B nach dem ":" einfach die ersten 8byte wegschmeißen und dann die
nächsten 32 Byte lesen, usw. Das das Hexfile mit 0 Anfängt usw nimmt man
einfach an. (naja den recodtype sollte man vielleicht noch auswerten um
das ende zu bestimmen)
Christoph P. schrieb:> Ich habe viel mehr eine konkrete Frage. Und zwar erschließt sich mir> bisher der Sinn der Verwendung des Intel-HEX-Formates nicht, wenn dieses> nur bewirkt, dass ich erst wieder einen Parser auf dem µC oder PC> brauche um es zu interpretieren. Warum lasse ich mir vom Makefile nicht> gleich mittels avr-objcopy eine Bin-Datei ausspucken und sende diese> dann via UART an den µC?> Daran schließt sich mir auch gleich noch eine zweite Frage an. Und zwar> bzgl. der Interpretation des Binärformates: Kann ich das so verstehen,> dass ich einfach stets 64 Bytes (1 Page) aus der Bin-Datei auslese und> diese nacheinander in die Speicherbereiche ab 0x0000 hochzählend> reinschreiben kann? Oder wie muss ich mir den Aufbau des Binärformates> vorstellen? Hab dazu nix richtig aussagekräftiges gefunden (zumindest> nichts was mir Klarheit verschafft hat ;-) )
wie schon Johann L. schrieb: Beim Binärformat werden die empfangenen
Daten als "echte" Binärzahlen interpretiert, d.h. wenn man eine binäre 5
(0x05) sendet, wird sie auch als 5 gewertet. Leider ist dann die
Flußsteuerung mit XON/XOFF nicht mehr möglich, da der gesamte Symbolraum
ausgenutzt wird. Natürlich könnte man auch auf "echte" Flußsteuerung á
la RTS/CTS umsteigen, aber das werden wohl die wenigsten implementiert
haben. Zum Aufbau der Binärdatei kann ich nicht viel sagen, daher habe
ich mich für den HEX-File-Parser entschieden, zumal keine avr-objcopy
o.ä. nötig ist. Der Artikel sollte so einfach und verständlich wie
möglich werden, so dass möglichst viele etwas damit anfangen können. Es
ist auch als Anregung zu verstehen die Sache weiterzuentwicklen oder
damit zu "spielen". Das schöne ist ja auch das durch die
Hardwareunabhängikeit durch C der Bootloader für jeden AVR (mit
Bootloadersupport) ohne Änderungen kompiliert werden kann.
Ich persönlich habe auch erst vor kurzem Angefangen mich speziell mit
Bootloadern zu beschäftigen. Ich habe letztens noch einen Bootloader
geschrieben, der sich wie ein STK500 verhält, dann wir das programmieren
noch einfacher. Er passt auch wunderbar in die 2k, werde ich bei
Gelegenheit mal posten.
delay schrieb:> z.B nach dem ":" einfach die ersten 8byte wegschmeißen und dann die> nächsten 32 Byte lesen, usw. Das das Hexfile mit 0 Anfängt usw nimmt man> einfach an. (naja den recodtype sollte man vielleicht noch auswerten um> das ende zu bestimmen)
Naja abspecken wird schwierig. Man kann den Header nicht
vernachlässigen. Die Daten stehen nicht so in der Hex-Datei wie sie
Binär im Speicher liegen. Da sind Sprünge drin, die müssen ausgewertet
werden. Es muß immer die Adresse ausgewertet. Eigentlich müßte der
Parser noch erweitert werden für RecordTyp 3 bis 5, um Adressoffsets
zuzulassen, bis jetzt sind nur 64kB addressierbar (RecordTyp 1 geht bis
0xFFFF).
Vielleicht hat ja jemand Lust das mal zu implementieren.
Mario Grafe schrieb:> Naja abspecken wird schwierig. Man kann den Header nicht> vernachlässigen. Die Daten stehen nicht so in der Hex-Datei wie sie> Binär im Speicher liegen. Da sind Sprünge drin, die müssen ausgewertet> werden. Es muß immer die Adresse ausgewertet. Eigentlich müßte der> Parser noch erweitert werden für RecordTyp 3 bis 5, um Adressoffsets> zuzulassen, bis jetzt sind nur 64kB addressierbar (RecordTyp 1 geht bis> 0xFFFF).> Vielleicht hat ja jemand Lust das mal zu implementieren.
stimmt, das würde nur mit kleinen Programmen gehen. Und man muss
annehmen das von 0-64k linear adressiert wird (was ja auch in der
jetzigen Implementierung zum Teil der Fall ist).
So, ich hab mich nun mal näher mit dem HEX-Format beschäftigt und muss
mich aufgrund der Verwendung eines ATmega1281 sowieso mit den
Datensatztypen 02 bis 05 beschäftigen. Dazu folgende Fragen:
1. Warum gibt es zwei verschiedene Modi/Record Types für die
Adressierung von Speicherplätzen über 64k? Zum einen den Extended
Segment Address Record (02) bei dem den folgenden Adressen ein Offset
aufaddiert wird und zum andern der Extended Linear Address Record (04)
bei dem den folgenden Adressen 4 höherwertige Bits vorrangestellt werden
und der Adressraum somit noch größer ist? Ist dies Compiler- oder
Architekturabhängig?
2. Der Record Type 03 (Start Segment Address Record) beinhaltet meines
Verständnis nach den Startpunkt (Zeiger) der Anwendung falls sie nicht
bei 0x0000 liegt (falls nicht, bitte korrigieren). Wozu dient dann noch
der Record Type 05 (Start Linear Address Record)?
Wenns Erfolge bei mir gibt bzgl. höherem Adressraum, kann ich den
entsprechenden Quelltext gern hier beisteuern. Und für Hinweise bzgl.
meiner Frage zum schreiben/flashen des BIN-Formats gibt, bin ich
weiterhin offen dafür ;)
Danke für den informative Artikel!
Ist es ein Versehen, dass statt dem üblichen CR+LF-Newline ("\r\n") ein
"\n\r" verwendet wird? Für mich ist es etwas irritierend.
Noch eine Kleinigkeit: Die Screenshots vom Terminal stimmen zum Teil
nicht mit den Ausgaben des Quellcodes überein. Stichwort: Gemischtes
Englisch - Deutsch.
Olli schrieb:> ich finde den Artikel zum Bootloader echt klasse. Kommt dann demnächst> noch die Erweiterung auf den STK500-kompatiblen Bootloader?
Danke für die Blumen. Sobald ich Zeit habe, poste ich den
STK500-kompatiblen Bootloader, er ist zu 90% fertig.
Jörg schrieb:> Ist es ein Versehen, dass statt dem üblichen CR+LF-Newline ("\r\n") ein> "\n\r" verwendet wird? Für mich ist es etwas irritierend.
Ja das ist ein Versehen, aber das Ergebnis ist das Gleiche. Könnte man
der Schönheit wegen noch ändern.
Jörg schrieb:> Noch eine Kleinigkeit: Die Screenshots vom Terminal stimmen zum Teil> nicht mit den Ausgaben des Quellcodes überein. Stichwort: Gemischtes> Englisch - Deutsch.
Richtig, das hat sich noch ein Screenshot einer Vorgängerversion
eingeschlichen (beim "Hallo Welt"-Bootloader). Muß ich noch berichtigen.
manni schrieb:> Hallo, geht das auch ohne AVR-Studio , nur mit Winavr und dann rüber?
Selbstverständlich! Letztenendes steckt ja auch nur WinAVR dahinter. Du
brauchst allerdings ein makefile, in dem du die Verschiebung der Sektion
.text als Option -Ttext=0xXXXX mitgeben kannst.
So, nachdem ich im AVRFreaks-Forum gelesen habe, dass der Record Type 03
(start segment address record) bei AVRs keine Bedeutung hat
(http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&p=650574
Beitrag 6) muss im Grunde für AVRs mit >64 KB nur noch der Record Type
02 (extended segment address record) ausgewertet werden. Alles kein
Problem, funktioniert bei mir schon ganz gut. Nur stellt sich mir dann
folgendes Problem: Wie kann ich - außer durch Eingabe eines festen
Wertes à la
1
void(*start_application)(void)=0x10000;
eine Adresse an den Funktionszeiger übergeben?
Ich stelle mir das ungefähr so vor:
Funktioniert (natürlich) beides nicht. In der Doku der avr-libc steht
unter 11.14 dazu folgendes:
> pointers are 16 bits (function pointers are word addresses, to allow> addressing up to 128K program memory space)
Wie kann ich dem Funktionszeiger nun eine Variable mit dem gewünschten
Adressinhalt übergeben?
Christoph P. schrieb:> Wie kann ich dem Funktionszeiger nun eine Variable mit dem gewünschten> Adressinhalt übergeben?
Die Applikation sollte doch an Adresse 0x0000 (0x00000000) starten.
Damit sollte es doch kein Problem geben, oder?
Ansonsten muß man inline Assembler nehmen, siehe "jmp", also etwa so:
1
asmvolatile("jmp 0x8000");
Die Adresse muß meines wissens als Word-Adresse angegeben werden, daher
0x10000/2=0x8000.
Kannst du deine Änderungen für den Segment Type 02 mal posten?
Mario Grafe schrieb:> Christoph P. schrieb:>> Wie kann ich dem Funktionszeiger nun eine Variable mit dem gewünschten>> Adressinhalt übergeben?>> Die Applikation sollte doch an Adresse 0x0000 (0x00000000) starten.> Damit sollte es doch kein Problem geben, oder?>> Ansonsten muß man inline Assembler nehmen, siehe "jmp", also etwa so:asm
volatile("jmp 0x8000");
> Die Adresse muß meines wissens als Word-Adresse angegeben werden, daher> 0x10000/2=0x8000.
So lange die neue Anwendung bei der Adresse 0x0000 beginnt ist das kein
Problem, richtig. Möchte ich aber zwei Anwendungen auf dem µC haben und
zwischen diesen Anwendungen mittels des Bootloaders wählen können, dann
muss ich bei (dementsprechend großen) Firmwares irgendwann auch mal in
den Speicherbereich >64 KB hineinspringen können. Dies würde ich gern so
"dynamisch" wie möglich machen, in dem die Startadressen der Anwendungen
aus den HEX-Dateien gelesen, gespeichert und bei Bedarf aufgerufen
werden.
In der avr-libc bin ich nun noch auf den uint_farptr_t gestoßen:
http://www.nongnu.org/avr-libc/user-manual/group__avr__inttypes.html#ga72b6692e3f3123903c1a0d9a960c59b1
1
typedefint32_tint_farptr_t
> signed integer type that can hold a pointer > 64 KB
Also an irgendeiner Stelle hab ich gerade einfach noch ein
Verständnisproblem - Byteaddresse, Wortadresse, Farpointer. Vielleicht
kann mir da noch jemand auf die Sprünge helfen, denn 0x10000/2 = 0x8000
=> jmp 0x8000 funktioniert auch nicht.
> Kannst du deine Änderungen für den Segment Type 02 mal posten?
Gern, nur der Record Type 03 ist (wie gesagt) völlig sinnfrei von mir
implementiert wurden. Hab den Parser nur mal in eine eigene Funktion
ausgelagert.
1
// boolean-defintion for software-flags
2
typedefenum
3
{
4
FALSE,
5
TRUE
6
}bool_t;
7
8
/**
9
* Parser for the received HEX-file content
10
*/
11
voidparse_hex_input(uint16_treceivedHexChar)
12
{
13
staticuint8_tparserState=PARSER_STATE_START,
14
hexSize=0,// length of the Intel-HEX data
15
hexRecType=0,// Intel-HEX record-type
16
hexChecksumEOL=0,// received HEX-file checksum
17
hexCounter=0,// writing position of the HEX-buffer
18
hexDataCounter=0;// counter of received HEX-data of one row
19
20
staticuint16_thexChecksum=0,// Intel-HEX checksum to proof received data
21
codeSgmntAddr=0,// code segment address for record-type == 03
22
instructionPtr=0;// instruction pointer for record-type == 03
23
24
staticbool_textSgmntAddrFlag=FALSE,// flag indicating record-type == 02
25
csRegisterFlag=FALSE,// flag indicating code segment address of record-type == 03
26
ipRegisterFlag=FALSE,// flag indicating instruction pointer of record-type == 03
27
flashPageFlag=TRUE,// flag indicating new flash-page
28
firstDataLineFlag=TRUE;// flag indicating that first line of HEX-file is read
29
30
#if (SPM_PAGESIZE > 255) // AVRs with 128k or more flash-memory
31
staticuint16_tflashCounter=0;// writing position of the flash-data buffer
32
staticuint32_thexAddrOffset=0,// address offset of the extended segment address record-type
33
hexAddress=0,// Intel-HEX target address
34
flashPage=0;// to be written flash-page
35
#else // AVRs with less than 128k flash-memory
36
staticuint8_tflashCounter=0;// writing position of the flash-data buffer
37
staticuint16_thexAddrOffset=0,// address offset of the extended segment address record-type
Christoph P. schrieb:> Ok, ich rudere zurück. Wortadressierung mittelsappStartAddress /= 2; und
anschließender Übergabestart_application = (void *) (uint16_t) appStartAddr;
funktioniert scheinbar doch 8-)
Das würde mich aber wundern, dann dürfte ja
1
void(*bootloader)(void)=0x1800;
nicht funktionieren...
Ein verzwickeltes Problem...
Nochmal nachgefragt:
Bist du sicher das du mehrere Anwendungen im Flash ablegen willst? Wie
hantierst du dann mit Interrupts (Stichwort: Sprungtabelle)? Was ist mit
dem Stack?
Mario Grafe schrieb:> Christoph P. schrieb:>> Ok, ich rudere zurück. Wortadressierung mittels appStartAddr /= 2; und>> anschließender Übergabe start_application = (void *) (uint16_t) appStartAddr;>> funktioniert scheinbar doch 8-)>> Das würde mich aber wundern, dann dürfte ja void (*bootloader)( void ) = 0x1800;> nicht funktionieren...>> Ein verzwickeltes Problem...
Ja, das habe ich auch erst gedacht. Aber kann es sein, dass der Compiler
bei der zweiten Version automatisch die Halbierung der Flashadresse
vornimmt, da Funktionszeiger ja stets Wortadressen sind? Nur eine vage
Vermutung.
Das mit den mehreren Anwendungen hat sicher noch so seine Tücken.
Speicherkonsistenz, Interrupt-Initialisierung/-Deinitialisierung usw.
Aber prinzipiell müsste es doch gehen, oder sehe ich das verkehrt? Was
du mit Stack meinst verstehe ich gerade nicht ganz. Aber beim PC
funktioniert's doch auch 8-)
Christoph P. schrieb:> Das mit den mehreren Anwendungen hat sicher noch so seine Tücken.> Speicherkonsistenz, Interrupt-Initialisierung/-Deinitialisierung usw.> Aber prinzipiell müsste es doch gehen, oder sehe ich das verkehrt? Was> du mit Stack meinst verstehe ich gerade nicht ganz. Aber beim PC> funktioniert's doch auch 8-)
Nein Christoph, einen PC kann man wirklich nicht mit einem AVR
vergleichen, da er keinen linearen Adressraum hat. Schau mal nach
"von-Neumann" und "Harvard"-Architektur bei wikipedia.
Eine Idee wäre allerdings möglich: Ein ausgefeilter Bootloader der eine
SD-Karte lesen kann (FAT) und ein Display und Steuertasten. Dann könnte
man via Bootloader eine Anwendung (hex oder bin-file) von der Karte
lesen und starten (=in den Flash kopieren). NAch dem Reset startet
wieder der Bootloader. Das fände ich durchaus praktikabel. Allerdings
würde das den Bootloader etwas aufblähen, bei großen Controllern aber
kein Problem.
Christoph P. schrieb:> Problem, richtig. Möchte ich aber zwei Anwendungen auf dem µC haben und> zwischen diesen Anwendungen mittels des Bootloaders wählen können, dann> muss ich bei (dementsprechend großen) Firmwares irgendwann auch mal in> den Speicherbereich >64 KB hineinspringen können. Dies würde ich gern so> "dynamisch" wie möglich machen, in dem die Startadressen der Anwendungen> aus den HEX-Dateien gelesen, gespeichert und bei Bedarf aufgerufen> werden.
Wenn du mal genauer darüber nachdenkst, dann macht es keinen Sinn, auf
einem AVR mehr als 1 Anwendung zu haben und per Bootloader umzuschalten.
1 AVR == 1 Anwendung
zb stimmen alle Interrupt Vektoren nicht. zb landet Applikation 2 in
Applikation 1, wenn es selber einen Sprung nach 0000 macht. Zb muss die
2.te Applikation für einen ganz anderen Speicherbereich gelinkt sein
etc. etc.
Die ganze Thematik kannst du getrost vergessen.
Wenn jemand wirklich 2 vorhandene Applikationen in eine verschmelzen
will, dann muss er das auf Code Ebene machen und sich selbst um die
ganze kleinen Feinheiten kümmern. Zum SChluss steht er dann wieder mit
nur 1 Applikation da, die vom Bootloader ins Flash gebrannt wird und bei
0x0000 startet.
> Wenn du mal genauer darüber nachdenkst, dann macht es keinen Sinn, auf> einem AVR mehr als 1 Anwendung zu haben und per Bootloader umzuschalten.>> 1 AVR == 1 Anwendung
Um genau zu sein, geht es mir auch mehr um die Möglichkeit eine Art
Firmware-Update durchführen zu können und weniger darum, zwei wirklich
verschiedene Anwendungsbereiche abzudecken. Also eher 1 AVR != 1
Firmware-Version
> zb stimmen alle Interrupt Vektoren nicht. zb landet Applikation 2 in> Applikation 1, wenn es selber einen Sprung nach 0000 macht. Zb muss die> 2.te Applikation für einen ganz anderen Speicherbereich gelinkt sein> etc. etc.
Vielleicht gehe ich an die Sache etwas zu blauäugig ran. Aber vielleicht
kannst du ja noch mal genauer auf die Punkte eingehen. Das Linken in den
gewünschten Speicherbereich ist ja kein Problem. Aber warum sollte
Anwendung 2 an die Stelle 0x0000 springen (außer Watchdog löst aus
o.ä.)? Das Auswählen zwischen den Anwendungen wird ja durch den
Bootloader übernommen. Am wenigsten Ahnung habe ich derzeit von den
angesprochenen Problemen mit den Interrupt-Vektoren.
Am Beispiel der Testanwendung aus dem Tutorial gesagt: Ich habe die
gleiche Anwendung in die Speicherbereiche ab 0x00000, ab 0x00100 und ab
0x10000 gelinkt und per Bootloader geflasht. Das heißt: Ich kann vom
Bootloader in alle drei Anwendungen springen und von denen wieder in den
Bootloader. Warum sollte das mit größeren Anwendungen nicht
funktionieren? Danke schon mal!
> Eine Idee wäre allerdings möglich: Ein ausgefeilter Bootloader der eine> SD-Karte lesen kann (FAT) und ein Display und Steuertasten. Dann könnte> man via Bootloader eine Anwendung (hex oder bin-file) von der Karte> lesen und starten (=in den Flash kopieren). NAch dem Reset startet> wieder der Bootloader. Das fände ich durchaus praktikabel. Allerdings> würde das den Bootloader etwas aufblähen, bei großen Controllern aber> kein Problem.
Die ganze Geschichte am Ende über einen externen Speicher (egal ob
SD-Karte oder was auch immer) zu lösen ist auch angedacht, aber für eine
schnelle Testlösung erstmal etwas zu viel.
Christoph P. schrieb:> Vielleicht gehe ich an die Sache etwas zu blauäugig ran. Aber vielleicht> kannst du ja noch mal genauer auf die Punkte eingehen. Das Linken in den> gewünschten Speicherbereich ist ja kein Problem. Aber warum sollte> Anwendung 2 an die Stelle 0x0000 springen
Weil du als Bootloader Programmierer keine Kontrolle darüber hast,
welche Schweinereien dein Anwendungsprogrammierer macht, die du nicht
verhindern kannst.
wer will mich daran hindern zu schreiben
1
intmain()
2
{
3
void(*func)();
4
func=0;
5
6
func();
7
}
Dein Bootloader ganz sicher nicht :-)
> Bootloader übernommen. Am wenigsten Ahnung habe ich derzeit von den> angesprochenen Problemen mit den Interrupt-Vektoren.
Das kannst du auch so einfach nicht lösen. Denn die Position der
Interrupt Vektoren ist dir von der Hardware vorgegeben.
> Am Beispiel der Testanwendung aus dem Tutorial gesagt: Ich habe die> gleiche Anwendung in die Speicherbereiche ab 0x00000, ab 0x00100 und ab> 0x10000 gelinkt und per Bootloader geflasht.
Na dann mach mal in deine Anwendung eine ISR rein und sieh nach welche
angesprungen wird, wenn App3 läuft und der Interrupt auftritt
So, ich hab mir die ganze Sache mit den Interrupt-Vektoren nochmal durch
den Kopf gehen lassen. Zunächst mal habt ihr natürlich recht, dass die
ISR-Vektoren immer am Anfang des Speicherbereichs stehen. Wenn der
auszuführende Inhalt der ISRs bei allen geflashten Anwendungen gleich
ist, dürfte die Ausführung ja kein Ding sein, oder?
Allerdings ist mir nicht ganz klar, warum der Rücksprung in die
eigentliche Anwendung aus einer ISR ein Problem darstellt. Ist die
Rücksprungadresse denn nicht im Programmzähler gespeichert bzw. von
diesem abhängig? Woher weiß denn die ISR (bzw. der µC) nach der
Codeabhandlung an welche Stelle im Flash gesprungen wird?
Also konkret: Was genau hindert mich daran, bei gleichen ISR-Inhalten,
mehrere Anwendungen auf einem µC laufen zu lassen (mal abgesehen von
Funktionszeigern auf bestimmte Speicheradressen und sonstigen
programmiererspezifischen Unwegbarkeiten)?
Wie gesagt, externer Zwischenspeicher ist defintiv angedacht, aber es
soll ja fix gehen ;)
Schade, dass mir noch keiner eine Antwort auf obige Frage geben konnte.
Derweil hier mal noch fix eine Funktion die eine BIN-Datei in den
Flashspeicher schreibt. Dabei wird vorher noch (wenn auch sinnfrei der
Diskussion zu folge) die Startadresse abgefragt und anschließend die
Größe der BIN-Datei eingegeben. Danach einfach nur noch die Daten
zwischenspeichern und ab in den Speicher. Vielleicht interessierts ja
jemanden.
1
/**
2
* Parser for the received BIN-file content
3
*/
4
voidparse_bin_input(uint16_treceivedHexChar)
5
{
6
#ifdef BIN_MODE
7
staticuint8_thexCounter=0;// writing position of the HEX-buffer
8
9
staticbool_tbinStartAddrFlag=FALSE,// flag indicating whether application start address is known or not
10
binSizeFlag=FALSE;// flag indicating whether application size is known or not
11
12
#if (SPM_PAGESIZE > 255) // AVRs with 128k or more flash-memory
13
staticuint16_tflashCounter=0;// writing position of the flash-data buffer
14
staticuint32_tbinStartAddr=0,// start flash-address of the application
15
binSize,// size of the application in byte
16
flashPage=0;// to be written flash-page
17
#else // AVRs with less than 128k flash-memory
18
staticuint8_tflashCounter=0;// writing position of the flash-data buffer
19
staticuint16_tbinStartAddr=0,// start flash-address of the application
Interressant wäre vielleicht auch ein XModem-Übertragungsprotokoll.
http://de.wikipedia.org/wiki/XModem
Bietet zumindest ein klein wenig Übertragunssicherheit, und so ziemlich
jedes Terminal-Programm bietet einen XModem Up-/Download an.
mit "sx" gäbs unter Linux ein einfaches Kommandline-tool zum Upload.
Die XModem-Blockgröße von 128Byte passt auch gut zur SPM_PAGESIZE vieler
AVRs, nur bei den kleinen tinys könnte es vom Ram knapp werden.
Hallo zusammen,
Die Sache mit den Interruptvektoren und mehreren Firmwares auf einem
Chip hat mich nun doch noch nicht in Ruhe gelassen.
Angenommen ich reserviere pro forma ab Adresse 0x0000 einen
Speicherbereich in der Größe aller theoretisch möglichen
Interruptvektoren. Ein vollständiges Image (inkl. Interruptvektoren)
beider Firmwares befindet sich im Flash (im Speicherbereich entsprechend
platziert mit den Linker-Flags im Makefile). In den reservierten
Speicherbereich kopiere ich dann die Interrupttabelle der Anwendung, die
ich gerade nutzen möchte. Da die Sprungziele m.M.n. absolute Adressen
sind, müsste das doch funktionieren, oder? So kann man mittels
Bootloader verschiedene Firmwares im Speicher platzieren und auch
auswählen.
Ein unerwarteter Sprung zu 0x0000 würde somit auch wieder in der vorher
verwendeten Anwendung enden.
Hoffe meine Gedankengänge sind nicht allzu wirr ;)
Frage an die Bootloader Gemeinde:
Ich möchte für ein Projekt einen Bootloader verwenden, um
Softwareupdates zu ermöglichen.
Jedoch sind die bisher verwendeten Möglichkeiten um den Bootloader in
den Updatemodus zu versetzen bei mir nicht möglich. Ich kann also nicht
den Taster oder die typischen 2 Warte sekunden bei mir einbauen.
momentan habe ich folgendes umgesetzt:
Nach dem Start checkt der Bootloader wie er gestartet wurde, in dem er
das Reset Register ausliest.
Wurde der Controller normal gestartet, so wird das bisherige Programm
aus dem EEProm geladen.
Wurde der Controller durch einen Hardwarereset neu gestartet, so
bedeutet es, dass eine neue Firmware als update kommt. Der Hardwarereset
wird durch die aktuelle Firmware ausgelöst, meist über einen Befehl von
der RS232 Schnittstelle.
Funktioniert so auch richtig gut.
Jedoch kann ich so keinen Watchdog benutzen (da der Bootloader sonst
jedesmal eine neue Firmware erwarten würde) was mir auch nicht recht
ist, da ich den Controller in einer relativ kritischen Anwendung nutze.
Ist folgendes möglich?
Kann ich zum speichern der Updateinformation auch ein Byte im EEprom des
Controllers nutzen? Es muss dabei garantiert sein, dass der Bootloader
und die Firmware auf die selbe SPeicherzelle zugreifen.
ist dsa möglich?
schon mal Vielen Dank
Martin J. schrieb:> Kann ich zum speichern der Updateinformation auch ein Byte im EEprom des> Controllers nutzen? Es muss dabei garantiert sein, dass der Bootloader> und die Firmware auf die selbe SPeicherzelle zugreifen.> ist dsa möglich?
Natürlich, wieso auch nicht?
Wie, steht bspw. hier:
http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#EEPROM
Hallo,
ich bin dem Tutorial gefolgt und habe versucht den Bootloader zum laufen
zu bekommen.
Das Problem ist, dass die Hex-Datei nicht 1796 Byte sondern 2520 Byte
groß ist. Hier einem mal die Ausgabe von Win-AVR beim kompletten
Rebuild:
Hallo Felix,
nein das ist mir schleierhaft. Die Beispiele wurden mit einem Atmega88
getestet. Da der Atmega128 aber einen genügend großen Bootloaderbereich
hat, sollte es trotzdem gehen (nach richtiger Fuse-Konfiguration).
Hast du es mal ausprobiert?
Mir ist doch noch was eingefallen:
Evtl. bindet die UART library (uart.c und uart.h) etwas mehr Code ein.
Im der Library von Peter Fleury wird der Prozessortyp ermittelt und
entsprechend angepasste Funktionen eingebunden. Da der Atmega128 ja
meherer UARTs hat, wird wohl mehr Code bzw. zusätzliche eingebunden
werden.
Ich denke das ist des Rätsels Lösung.
Stell doch im Kompiler mal Spaßenshalber den Atmega88 ein und kompiliere
es, mal sehen wir groß der Code da wird....
Hallo!
Ich habe versucht, den Bootloader auf einem DVK90CAN1 umzusetzen. Da der
uC AT90CAN128 von Peter Fleurys UART nicht unterstützt wird, habe ich
die UART mit FIFO von Peter Dannegger genommen. Das Projekt wird mit dem
AVR Studio erstellt und erfolgreich kompiliert. Die Verbindung zu einem
Terminalprogramm klappt ebenfalls vorzüglich (Danke, Peter!).
Nun aber zu meinem Problem: Wenn ich das Programm nach Anweisung in den
Bootloaderbereich verschiebe durch Setzen der Linker-Option
(hier -Ttext=0x1E000) und "Verbiegen" der Interrupts, passiert nichts.
Mit dem Autor des Artikels habe ich schon konferiert, aber er ist
ratlos.
Welcher Schalter muß noch umgelegt werden?
Helene
Also:
Ein Programm, das compiliert, geflasht und ausgeführt wird, läuft
erwartungsgemäß (keine Interrupts, nur "pollen").
Das Verschieben auf eine andere Anfangsadresse im Bootloaderbereich oder
auch nur um ein paar words (na klar, compiliert, etc...) läuft nicht.
Kann mir wirklich keiner einen Tip geben?????
Helene
Hallo Helene,
wahrscheinlich hast Du das gleiche Problem wie ich:
Der Compiler erzeugt eine falsche Interrupt-Sprungtabelle:
0001f000 <__vectors>:
1f000: 0c 94 72 f8 jmp 0x1f0e4 ; 0x1f0e4 <__ctors_end>
1f004: 0c 94 91 f8 jmp 0x1f122 ; 0x1f122 <__bad_interrupt>
1f008: 0c 94 91 f8 jmp 0x1f122 ; 0x1f122 <__bad_interrupt>
1f00c: 0c 94 91 f8 jmp 0x1f122 ; 0x1f122 <__bad_interrupt>
1f010: 0c 94 91 f8 jmp 0x1f122 ; 0x1f122 <__bad_interrupt>
...
Die jmp's sind alle 4, und nicht nicht, wie notwendig, 2 Byte.
Ich habe bis jetzt noch keine Möglichkeit gefunden, dass die
Vektortabelle korrekt erzeugt wird (WinAVR 20100110: Optimize for size
(-Os), -fno-jump-tables oder auch -mshort-calls --> keine Auswirkung).
Vielleicht weiß jemand eine Möglichkeit....
Gruß,
Gunter
Gunter Heuckeroth schrieb:> Die jmp's sind alle 4, und nicht nicht, wie notwendig, 2 Byte.
Dann hast du wohl beim Linken den falschen Controller angegeben.
Hallo Stefan,
also, dann benutzt AvrStudio + Eclipse, wenn beim Linken
"-Ttext=0x1F000" angegeben ist, einen anderen Controller als wenn diese
Option nicht angegeben ist....
Hast Du es selbst mal probiert?
Gunter
Gunter Heuckeroth schrieb:> "-Ttext=0x1F000"
Du benutzt also einen Controller mit 128k Flash. Wie kommst du darauf,
dass die Vektoren 2 Bytes lang sein müssen? Die sind bei deinem
Controller mit 100%iger Sicherheit 4 Bytes (2 Words) groß.
Hallo Stefan,
danke für die Anregung...
Du hast recht!
Ich bin auf die unterschiedliche Adressdarstellung hereingefallen
(Datenblatt -> Wort-Adressen; GCC-Listing -> Byte-Adressen).
(Geistesblitz....)
Das heißt, für einen ATMEGA2560 muß ich dem Linker als Adresse 0x3E000
angeben (Byteadresse!) und nicht 1F000 (Wortadresse!)...
Arrghhh...
Dann klappt's vielleicht jetzt auch mit den Interrupts...
Nochmals danke, werde ich jetzt gleich ausprobieren....
Gunter
Kann ich das Tutorial auch für den ATmega8515 umschreiben?
Momentan hab ich das Problem, dass ich im MCUCR register vom 8515 die
IVCE und IVSEL bits nicht finde. Haben die beim 8515 ne andere
Bezeichnung oder gibts die gar net?
Hallo Unwissender ;-)
Nach einem kurzen Überfliegen des Datenblattes des 8515:
Es gibt kein "Boot"-Flash-Bereich, in dem ein Bootloader stehen könnte.
Das Teil kann nur per "parallelem" Programming oder "seriell" geflasht
werden.
Gruß,
Gunter
Freut mich das es die gefällt. Ich habs ans Ende des Artikels angefügt.
Ich wollte eigentlich mal wieder ein bischen dran weiterarbeiten wenn
ich Zeit habe, vor allem die Ergänzung für die XMEGAs...mal gucken wann
das wird.
Guten Rutsch
Mario
Hallo auch,
habe mich mal an diesem Bootloader versucht und bin auch weit gekommen
:-D
Jetzt habe ich aber ein kleines Problem und hoffe mir kann da jemand
helfen.
Ich Drücke also die Taste "p" um den Bottloader in den Zustand zu
bringen, dass er die Daten des HEX-File empfängt. Der Bootloader lauscht
auch brav danach.
Wenn ich nun das HEX-File in Putty kopiere, fängt der mit der
Übertragung an aber leider nur eine Zeile lang, danach kommen merhere
Zeilen - Rautesymbole - und dann bleibt alles stehen:
.....................................................p
###############################################################
###############################################################
###############################################################
####################
Ich habe schon versucht die Bautrate zu reduzieren aber hilft alles
nichts.
Woran könnte das liegen?
Gruß und vielen Dank
Snatch
In den Error-State (Raute-Symbole) springt der Bootloader nur, wenn die
Checksumme der Zeile nicht stimmt. Es sieht also ganz so aus als ob er
die (erste) Zeile nicht richtig empfängt. Das kann an der Baudrate oder
auch an der Genauigkeit der Baudrate liegen (Baudratenfehler).
Gib mal ein paar mehr Daten:
Welcher AVR?
Taktfrequenz?
Baudrate?
Hast du etwas am Bootloader verändert?
Hallo,
ein sehr schöner Artikel. Ich war grad dabei das nachzuvollziehen, habe
aber das aktuelle AVR Studio 5. Wo finde ich denn dort die
Projekteinstellungen? Klar Rechtsklick auf das Projekt und Properties
macht ja einen schönen Dialog auf (Visual Studio läßt grüßen), aber wo
kann man denn schonmal die Frequenz einstellen? Ich such mir seit ca.
zwei Stunden schon nen Wolf. Kann mich mal bitte jemand erleuchten.
Ich hab bisher mit programmers notepad gearbeitet und dort kann man den
Parameter ganz einfach im makefile eingeben. Aber das AVR Studio hat
wohl auch so einige Vorteile. Deswegen möchte ich mich gern mal
einarbeiten.
Vielen Dank,
der ChekR
Hallo Mario,
ich hab bestimmt was noch nicht verstanden: was ich im Code nicht sehe
ist folgendes: wenn eine geparste Adresse aus der momentan aktuellen
Flash-Page herausführt (also ein Adresssprung im hex-File, was ja
möglich ist), müsste dann nicht erst die (gegebenenfalls nur teilweise
ausgefüllte) "alte" flash page geschrieben werden und dann eine neue
flash-page Adresse erzeugt werden? Oder einfach gefragt: funktioniert
der Code auch wirklich bei einem nicht linear durchgehend beschriebenen
Flash-Speicher? Im code sehe ich nur, dass der Flash bei vollem Puffer
oder bei hexRecType = 1 (Ende des Files) geschrieben wird.
Konkret sehe ich das Problem, wenn ich ans Ende des Flashspeichers
direkt vor dem Bootcode z.B. noch eine Versionsnummer eintragen will,
wie das in den SD-card- Bootloadern, die mit Binärdateien arbeiten, oft
üblich ist. Das kann ich ja mit -section-start = xxxxxxx als
linker-flag erreichen.
Ich will das für einen Xmega128 machen und muss dazu natürlich auch in
den extended segment address-Bereich (währen mein restlicher code in den
64K-Bereich passt). Die letzen vier Zeilen des hex-files sehen dann so
aus:
:10092C0067000000000200000000650300000000EA //letzte Zeile aus
64K-space
:020000021000EC //extended address
:08FFF8007856341255AA0000EE //code ab addr. 0x1FFF8
:00000001FF //file ende, hexRecType 1
Bei der Arbeit mit Binärfile alles kein Problem, da wird ja brav der
gesamte flash durchgehend bis zur obersten verwendeten Adresse
abgespeichert.
Über eine Aufklärung würde ich mich freuen.
Grüße,
Karl
@CheKr: Properties, Toolchain, AVR/GNU C Compiler, Symbols. Unter -D
defined symbols mit dem grünen "+" Symbol F_CPU= xxxxxxUL eintragen
und wenn man dann nur so einen kleinen "Brocken" in den Flash schreibt,
sollte man vielleicht vorher lieber die originale flash page erst mal in
den Puffer laden, damit man nichts verändert, was man gar nicht
verändern will, wenn man die page wieder zurückschreibt. So macht's der
kavr zum Beispiel.
Karl
und hier wäre dann mein Vorschlag, die oben beschriebenen Probleme zu
beheben, als Erweiterung von Marios Code, mit Kommentaren. Der Code ist
aber ungetestet, ich weiß gar nicht, ob so was hier erlaubt ist... Er
sollte jetzt auch hex-Files schlucken, in dem die Adressen kreuz und
quer gehen.
Grüße,
Karl
Hallo Karl,
du hast richtig gelesen. Adresssprünge und Code >64K wurden bisher nicht
berücksichtigt. Dies ist auch am Ende des Tutorials vermerkt.
Mario
wen es interessiert: im Paralleluniversum
http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&p=953604#953604
habe ich den dort ursprünglich veröffentlichten code für einen Xmega
Bootloader, der einen hex-file von einer SD-Karte einliest, so
umgearbeitet, dass er tatsächlich auch für flash code im Bereich >64k
arbeitet und eine Versionskontrolle erlaubt. Getestet mit XMega128A1 und
FAT16.
Karl
Die downloads sind nur sichtbar, wenn man bei avrfreaks angemeldet ist,
was aber ja keine Hürde sein sollte. Ich fand es dem Autor bei
avrfreaks, dessen Programm ich erweitert habe, unfair gegenüber, den
code auch hier anzuhängen. Ich lasse mich vom Moderator aber gerne eines
besseren belehren bzw. meinen Post hier löschen.
Karl
Karl Jacobs schrieb:> Die downloads sind nur sichtbar, wenn man bei avrfreaks angemeldet ist,> was aber ja keine Hürde sein sollte.
Sign Up? -> Fehlanzeige...
no member of AVRFreaks.net schrieb:> Sign Up? -> Fehlanzeige...
Lieber Gast, ich verstehe diese Meldung zwar nicht, aber wenn Du hier
angemeldet wärest, könntest Du mir eine Nachricht schicken und bekämst
den code direkt von mir. Ich möchte allerdings nicht das Forum hier
vollmüllen, das ist daher mein letzter post zu diesem Thema.
Gunter Heuckeroth schrieb:> (Geistesblitz....)> Das heißt, für einen ATMEGA2560 muß ich dem Linker als Adresse 0x3E000> angeben (Byteadresse!) und nicht 1F000 (Wortadresse!)...
Danke an Stefan und an Gunter, genau das war auch mein Problem. Hatte
beim ATmega324pa anstatt der Byte-adresse 0x7800 die Wort-adresse 0x3c00
dem Linker mitgegeben. Mit 0x7800 klappts auf Anhieb.
Hallo Leute,
ich hoffe der Thread ist nicht zu alt und ich bekomme ich hier noch eine
Antowrt, das wäre super.
Erstmal danke an den Autor, eine Super Arbeit!!
Ich bin dabei, den Bootloader für meinen AT90CAN auszulegen. Allerdings
habe ich ein Problem mit der hex_checksum. Nach der ersten Zeile Code
bekomme ich nur noch Fehler, die zb so aussehen:
.............#######################################
also beginnt der Bootloader nichtmal eine Page zu beschreiben. Hat
Jemand eine Idee wodran es liegen könnte und ob es eine einfache Lösung
des Problems gibt auf die ich nicht komme?
Als kommunikation benutze ich eine eigene UART lib mit flowcontrol, die
aber einwandfrei funktioniert.
grüße
Ollo
Mario schrieb:> Ich wollte eigentlich mal wieder ein bischen dran weiterarbeiten wenn> ich Zeit habe, vor allem die Ergänzung für die XMEGAs...mal gucken wann> das wird.
Guten Morgen Mario,
hast Du bereits etwas für die xmegas optimiert?
Habe gestern Deine Anleitung gelesen und heute wollte ich sie testen,
allerdings spuckt AtmelStudio 6 erstmal einen Berg Fehlermeldungen und
Warnings aus. (Selbst beim Hallo-Welt-'Bootloader')
Angefangen bei der boot.h "# error AVR processor does not provide
bootloader support!" gibts eigentlich nur Probleme.
Habe nun von Atmel den xmega-Bootloader drin, aber der ist eben nicht so
einfach gehalten und so gut anpassbar.
Gruß Tobi
Hallo Tobi,
Tobias Gläser schrieb:> hast Du bereits etwas für die xmegas optimiert?
Nein ich hatte noch keine Zeit dazu.
Tobias Gläser schrieb:> Habe gestern Deine Anleitung gelesen und heute wollte ich sie testen,> allerdings spuckt AtmelStudio 6 erstmal einen Berg Fehlermeldungen und> Warnings aus. (Selbst beim Hallo-Welt-'Bootloader')
Das wundert mich, es sollte auch mit dem AtmelStudio und Xmegas
prinzipiell funktionieren, vorrausgesetzt man passt die Einstellungen
für den Atxmega an. Welchen hast du denn?
Tobias Gläser schrieb:> Angefangen bei der boot.h "# error AVR processor does not provide> bootloader support!" gibts eigentlich nur Probleme.
Das klingt eher nach falschen Controller-Settings.
Gruß
Mario
Hallo Mario,
Vielen Dank für den Beitrag.
eins ist mir noch nicht klar:
"...an Word-Adresse 0xC00, also Byteadresse 0xC00 * 2 = 0x1800"
um die Adresse eines Words zu bekommen, muss man die Adresse von dem
Byte mit 2 multiplizieren??
warum?
Umgekehrt. Man möchte die Byteadresse aus der Wordadresse ermitteln.
Beim Word ist das Datenwort 16 Bit, beim Byte nur 8 Bit. Demzufolge
entspricht die Byteadresse = 2 * Wordadresse.
Man kann es auch Bitweise ausrechnen: 8 * 0xC000 = 16 * 0x1800
Hallo,
toller Artikel! Trotzdem habe ich noch eine Anmerkung:
Bei einigen Typen - zumindest beim ATmega32 - sind die IVSEL und IVCE
bits nicht im MCUCR, sondern im GICR.
Gruß,
Peter
Hallo Mario,
mithilfe deines Artikels ist es auch mir als "nicht Profi" gelungen, den
Bootloader auf dem Atmega 644 zum laufen zu bringen. Ein Update des uC
aus meiner Labiew Applikation ist so problemlos möglich.
Nun muss ich aber auf den 1284 umsteigen. Ich dachte schon der
Bootloader läuft auch hier, aber da hatte ich den Hinweis auf die
fehlende Unterstützung >64K Flash leider überlesen.
Da ich wie gesagt eher der Anwendungsprogrammierer bin, tue ich mich mit
der Integration der erweiterten Adressräume (HEX-Zeilentyp 2 bis 5)
etwas schwer, bzw. weiss nicht so richtig wo ich da ansetzen muss.
Hat evtl. schon jemand diese Erweiterung gemacht oder kannst Du mir
einen Tipp geben wie ich das am besten angehe?
Gruß
Jan
Hallo Jan, der richtige weg ist die state-machine zu erweitern. Ich
wollte das sowieso mal noch machen. Ich bin die Woche leider unterwegs.
Ich melde mich Ende der Woche nochmal.
Nein tut mir leid. Ich hab zur Zeit zu viel zu tun.
Letztenendes muss in diesem Abschnitt:
1
...
2
case PARSER_STATE_TYPE:
3
hex_buffer[hex_cnt++] = (uint8_t)c;
4
if(hex_cnt == 2)
5
{
6
uart_putc(XOFF);
7
hex_cnt = 0;
8
hex_data_cnt = 0;
9
hex_type = (uint8_t)hex2num(hex_buffer, 2);
10
hex_check += hex_type;
11
switch(hex_type)
12
{
13
case 0: parser_state = PARSER_STATE_DATA; break;
14
case 1: parser_state = PARSER_STATE_CHECKSUM; break;
15
default: parser_state = PARSER_STATE_DATA; break;
16
}
17
uart_putc(XON);
18
}
19
break;
noch der "case" 2 eingebaut werden (Extended Segment Address Record) und
dann der Adresszeiger entsprechend manipuliert werden. Das einfachste
ist man fügt eine Offsetvariable hinzu welche bei der Berechnung der
"flash_page" hinzuaddiert wird. Achtung: vor dem Berechnen der neuen
Adresse sollten die alte Page auf jeden Fall noch geschrieben werden (
auch wenn sie noch nicht voll ist).
Ich schau mal ob ich das eingebaut bekomme. Ich werde es aber leider
nicht so fix testen können...
So ich habe mal im Tutorial ein neues Kapitel für Programme >64k
angefangen und die Auswertung des Record-Typ 2 in den Bootloader
eingebaut, hauptsächlich wurde die Variable "hex_addr" auf 32 Bit
erweitert und ein Offset (auch 32 Bit) eingeführt. Wenn der Record-Typ 2
kommt wird im Zustand "PARSER_STATE_DATA" entsprechend die
Segmentoffset-Adresse (hex_addr_offset) geparst und gesetzt. Alle
folgenden Schreiboperationen beziehen den Offset dann ein. Vor dem
Ändern des Offsets wird noch die Angefangene Page geschrieben.
@Jan Müller: bitte testen..
Hallo Mario,
beim compilieren bekomme ich folgende Warnung:
/* Berechnen der Offsetadresse */
hex_addr_offset = (uint32_t)(hex2num(hex_buffer, 4) << 16);
../bootloader.c:313: warning: left shift count >= width of type
Habe das Programm dann mal geladen:
Eine 60K Hex Datei wird geladen und das Programm läuft dann auch.
Eine 104K Hex Datei wird geladen und aber das Programm läuft dann nicht.
Gruß
Jan
Jan Müller schrieb:> Hallo Mario,>> beim compilieren bekomme ich folgende Warnung:>> /* Berechnen der Offsetadresse */> hex_addr_offset = (uint32_t)(hex2num(hex_buffer, 4) << 16);
Der Cast ist an der falschen Stelle. Das muss lauten
Karl Heinz schrieb:> Der Cast ist an der falschen Stelle. Das muss lauten> hex_addr_offset = ((uint32_t)hex2num(hex_buffer, 4)) << 16;
...geändert. Danke.
Hallo Mario,
ich habe das heute noch mal ausprobiert:
Eine 60K Hex Datei wird geladen und das Programm läuft dann auch.
Eine 104K Hex Datei wird geladen und aber das Programm läuft dann nicht,
der Controller macht permanent Reset.
Gruß
jan
Hallo Jan,
ich habe den Quellcode für den Bootloader nochmal komplett überarbeitet.
Es waren noch einige Bugys drin. Ich habe mal das alte Atmega88-Vehikel
zum Testen reaktiviert. Mit diesem habe ich auch getestet, das
funktioniert erstmal soweit...
Ich musste noch einiges straffen damit es in die 2048 Byte reinpasst.
Bitte teste jetzt mal mit Hex-Daten > 64k...
Im Anhang mal das Quellfile der "main.c", dann sparst du dir das
Copy&Paste :)
Gruß
Mario
im Quellcode bitte sehr:
- alle Einrückungen ohne Tabs
- alle Einrückungen gleichmässig (4 blanks ist ein gute Zahl)
- ä, ö, ü etc vermeiden
Muss man das begründen?
Ist mir so auf die Schnelle aufgefallen, vielleicht gibt es
noch mehr ....
isidor schrieb:> im Quellcode bitte sehr:>> - alle Einrückungen ohne Tabs> - alle Einrückungen gleichmässig (4 blanks ist ein gute Zahl)> - ä, ö, ü etc vermeiden>> Muss man das begründen?>> Ist mir so auf die Schnelle aufgefallen, vielleicht gibt es> noch mehr ....
Danke für den Hinweis, natürlich weiß ich das. Ich habe es mir aber für
morgen aufgehoben den Quelltext "aufzuhübschen". Jan sollte erstmal
weiterkommen und meine Zeit am Code zu arbeiten ist derzeit sehr
begrenzt...
Hallo Mario,
beim Compilieren habe ich Probleme mit der Funktion
"memcpy_PF"
Warnung:
../bootloader.c:257: warning: implicit declaration of function
'memcpy_PF'
Error:
R:\BP700\SW\01_Controller\12_bootloader1284P\work_2\default/../bootloade
r.c:257: undefined reference to `memcpy_PF'
Ich verwende "WinAVR-20100110", in der pgmspace.h gibt es nur eine
Funktion 'memcpy_P'.
Habe dann im Internet eine neuere pgmspace.h mit der Funktion
"memcpy_PF" gefunden und die Datei "pgmspace.h" ausgetauscht.
Dann war die Warnung weg, aber der Error steht weiterhin an.
Gruß
jan
Hallo Jan,
die "memcpy_PF"-Funktion ist in der Tat teil der avr-libc:
http://www.nongnu.org/avr-libc/user-manual/group__avr__pgmspace.html
das "..F" bedeutet "far" für Kopieraktionen in Speicherbereichen >64k.
Du kannst die auch eine Routine mit "pgm_read_byte(...)" schreiben.
Dein WinAVR ist in ziemlich alt. Ich habe für das kompilieren das
AVRStudio 6.2 mit der gcc.Verision: gcc version 4.8.1
(AVR_8_bit_GNU_Toolchain_3.4.4_1162) benutzt. Evtl. wäre es eine gute
Idee zumindest den gcc mit der gnu toolchain zu updaten...
mein avr-libc ist vermutlich 1.8 (muss ich noch checken)...
Schlimmstenfalls kannst du erstmal die "memcpy-PF" auskommentieren und
probieren. Das ist eigentlich nur wichtig wenn es Adress-Sprünge
innerhalb des Hex-Files gibt...
so, habe die "memcpy-PF" mal auskommentiert, das Ergebnis ist leider wie
bisher auch:
Eine 60K Hex Datei wird geladen und das Programm läuft dann auch.
Eine 104K Hex Datei wird geladen und aber das Programm läuft dann nicht,
der Controller macht permanent Reset.
(ohne Bootloader, direkt in den Controller geladen, funktioniert die
104K Hex Datei einwandfrei).
Werde dann mal das AVR Studio updaten.
Irgendwie finde ich keinen neueren WinAVR Installer als meinen
WinAVR-20100110-install.exe
Gruß
jan
Hmm, ich muß mal schauen ob ich irgendwie ein Testvehikel auftreibe.
Benutzt du Putty als serielle Konsole?
Kommt irgendwann mal die Ausschrift "J"?
Vermutlich gibt es noch ein Problem in der Addressberechnung...
Jan Müller schrieb:>> Ich verwende "WinAVR-20100110", in der pgmspace.h gibt es nur eine> Funktion 'memcpy_P'.>> Habe dann im Internet eine neuere pgmspace.h mit der Funktion> "memcpy_PF" gefunden und die Datei "pgmspace.h" ausgetauscht.> Dann war die Warnung weg, aber der Error steht weiterhin an.>> Gruß> jan
Da fehlt tatsächlich etwas in der lib. Aber es reicht nicht das
Header File zu ersetzen.
Es gibt eine neuere Version, die hier: avr-libc-1.8.1
hier herunter zu laden:
http://download.savannah.gnu.org/releases/avr-libc/
Dort ist memcpy_PF enthalten. Hoffentlich der zugehörige Code
ebenfalls. Ich habe mich aber nicht getraut meine existierene
WinAVR-20100110 Installation zu patchen.
Ich glaube ich habe den Fehler (zumindest einen Fehler) gefunden:
Die Berechnung der Offset-Adresse für Record Typ 2 ist definitiv falsch,
sie muss etwa so aussehen:
1
...
2
case 2: hex_addr_offset = ((uint32_t)(hex2num(hex_buffer, 4)) << 4; break;
3
...
da beim Record Typ 2 stellt die Offset-Adresse den oberen Teil (Bit
4-19) einer 20 Bit-Adresse dar, daher die Verschiebung um 4 Bit nach
links. Ich habe es im Wiki geändert. Im Anhang die aktuelle "main.c"
@Jan: Bitte testen...
Sorry, aber das funktioniert leider immer noch nicht.
Eine 60K Hex Datei wird geladen und das Programm läuft dann auch.
Eine 67K Hex Datei wird geladen und aber das Programm läuft dann nicht,
der Controller macht allerdings nun nur noch einen Reset (nach dem Ende
des Ladens), aber das Programm läuft dann nicht.
Gruß
jan
Mario Grafe schrieb:> Hab grad festegestellt, das ich meinen eigenen Code nicht mehr verstehe.> Kann mir jemand (Karl Heinz?) die Berechnung der Flash-Adresse> erläutern:>>
>> Irgendwie steh ich grad auf dem Schlauch...so ist das wenn man sich> lange nicht mehr damit beschäftigt hat.... :)
Wenn du die Zahl 834 hast und SPM_PAGESIZE 100 ist, was ergibt dann der
Ausdruck
1
834 - 834 % 100
das ergibt eine glatte 800.
D.h. die Berechnung beantwortet wohl die Fragestellung: Wenn ich eine
beliebige Adresse x habe und eine beliebige Page-Size, welches ist dann
die erste Adresse in der Page, in der die Adresse x liegt.
Am Beispiel: Bei einer Pagesize von 100 liegt die Adresse 834 in
derjenigen Page, die bei der Adresse 800 startet.
Karl Heinz schrieb:> Wenn du die Zahl 834 hast und SPM_PAGESIZE 100 ist, was ergibt dann der> Ausdruck 834 - 834 % 100> das ergibt eine glatte 800.>> D.h. die Berechnung beantwortet wohl die Fragestellung: Wenn ich eine> beliebige Adresse x habe und eine beliebige Page-Size, welches ist dann> die erste Adresse in der Page, in der die Adresse x liegt.>> Am Beispiel: Bei einer Pagesize von 100 liegt die Adresse 834 in> derjenigen Page, die bei der Adresse 800 startet.
Danke, zwischenzeitlich ist es mir auch wieder wie Schuppen aus den
Haaren gefallen :)
Ich hatte vergessen, das die Page-Write-Funktion nicht die Nummer der
Page sondern die Startadresse der Page übernimmt..
Jan Müller schrieb:> Sorry, aber das funktioniert leider immer noch nicht.>> Eine 60K Hex Datei wird geladen und das Programm läuft dann auch.>> Eine 67K Hex Datei wird geladen und aber das Programm läuft dann nicht,> der Controller macht allerdings nun nur noch einen Reset (nach dem Ende> des Ladens), aber das Programm läuft dann nicht.
Ohne debuggen wird das nix. Die Adressberechnung sollte eigentlich jetzt
stimmen. Ich habe noch ein ATmega2560-Geschoß rumliegen, ich werde mal
versuchen das zu reaktivieren...
Ich bekomme den Bootloader auf dem ATmega2560 im Augenblick nicht zu
laufen. Es scheint ein Problem mit UART und dem AVR zu geben. Ich
verwende die USART-Lib von Peter Fleury. Das UART-Senden funktioniert.
Einzelne Zeichen empfangen geht auch. Sobald ich das HEX-File rüber
schiebe resetet sich der ATmega2560...
Der Code ist der gleich wie beim ATmega88...sehr seltsam...
Hallo,
vorweg ein großes Dankeschön für das tolle Tutorial. Leider bekomme ich
den Bootloader auf dem Atmega32 nicht zum laufen.
Die Ausgabe sieht so aus: ...............############### usw.
Ich habe das MCUCR zu GICR angepasst und als Adresse 0x7800 (Bootsz
1024) gewählt, die Baudrate liegt bei 9k6 aber auch bei niedrigeren
Baudraten kommt es zum Checksum Fehler. Als Oszillator nutze ich einen
externen 8 MHz Quarz.
Hat jemand den Bootloader schon auf einem Mega32 zum laufen gebracht und
kann mir sagen was alles angepasst werden muss?
Xon/Xoff waren eingeschaltet, hat aber scheinbar nicht funktioniert.
Ich habe die Softwareflusssteuerung jetzt auskommentiert, die
_delay_ms(100) beim schreiben einer Page gestrichen und in C# ein
Terminalprogramm geschrieben, welches nach jeder übertragener Line kurz
wartet. Jetzt funktioniert alles. Das Problem lag wohl daran, dass
Xon/off nicht immer funktioniert hat und somit der RX-Buffer
übergelaufen ist.
Ich werde heute mal versuchen den Parser im Terminalprogramm zu
implementieren.
Nochmal zu der Flusssteuerung:
Ich habe ja die UART-Library von Peter Fleury benutzt. Diese hat einen
Empfangs- und Sendpuffer, d.h. die "uart_putc" schreibt nur in den
Puffer, wann das Byte gesendet wird steht auf einem anderen Blatt. Wenn
der Empfangsinterrupt permanent aktiv ist bleibt vermutlich zu wenig
Rechenzeit zum Senden übrig. Mit einer "echten" Flusssteuerung (RTS/CTS)
würde es natürlich klappen.
Eine andere Möglichkeit ist natürlich nach einer bestimmten Anzahl von
Bytes zu warten. Das müsste aber dann das Terminal machen.
Falls jemand eine gute Idee hat wie man es besser machen könnte nur raus
damit :)
Evtl. hilft auch eine höhere Taktfrequenz damit mehr Rechenzeit (neben
dem Abarbeiten des Empfangsinterrupts) übrig bleibt. Eine
IR-Priorisierung wäre auch nicht schlecht, geht aber beim ATmega nicht.
Ich habe den Parser jetzt aus dem Bootloader genommen und lasse das
Terminalprogramm das Hex-File "übersetzen". Jetzt geht das flashen
doppelt so schnell, da nur noch halb so viele Bytes übertragen werden
müssen.
Nach jeder Line wartet das Terminal eine kurze Zeit (20-50ms), damit hat
der Controller mehr als genug Zeit um die Page zu schreiben.
Danke für die super Anleitung und deine Hilfe!
Sorry noch nicht. Ich habe versucht rauszufinden warum mein ATmega2560
nicht funktioniert. Dafür habe ich alles möglich auskommentiert. Er
startet jedoch nach dem Empfang von ein paar Zeichen ohne Grund immer
neu. Ich habe fast das Gefühl es liegt am ATmega2560...
Das ISR-umschalten funktioniert. Der Bootloader läuft auch los.
Irgendwie scheint die Lib von Peter Fleury nicht zu funktionieren...
Wenn Zeit ist muß ich nochnmal weiter suchen...
Hallo freunde,
Erstmal herzlichen dank Mario für dein bootloader.
Mit Atmega88 funktioniert es, aber mit Atmega8 leider nicht.
Laut Datenblatt BootStart adresse ist 0xC00 (WORD) also 0x1800 (Byte)
Ich hab die Fuse so eingestellt BOOTRST = 0 (programmed) und Bootloader
size = 00 (1024)(word) und 8 Mhz eingestellt.
Kann mir bitte jemand tips geben was ich eventuell falsch gemacht habe.
Danke euch
MFG
Eddy
Hallo Mario,
Vielen Dank für dein super Tutorial, mir hat es sehr sehr geholfen.
... und was Turmel geschrieben hat ist voll nicht verständlich, für mich
hat der Typ kein Ahnung. Wenn ich was durch arbeite, achte nicht auf
Rechtschreibung, achte auf den Inhalt was ich auch mit erfolg durch
gearbeitet habe.
Mach dir nichts draus es gibt immer Idiotien die schnell mit negativen
Feedback sich beteiligen.
MFG
Eddy
Eddy C. schrieb:> Hallo Mario,> Vielen Dank für dein super Tutorial, mir hat es sehr sehr geholfen.>> ... und was Turmel geschrieben hat ist voll nicht verständlich, für mich> hat der Typ kein Ahnung. Wenn ich was durch arbeite, achte nicht auf> Rechtschreibung, achte auf den Inhalt was ich auch mit erfolg durch> gearbeitet habe.>> Mach dir nichts draus es gibt immer Idiotien die schnell mit negativen> Feedback sich beteiligen.
Danke für die Blumen :)
Ich habe das Tutorial geschrieben weil ich mich selbst tief in das Thema
einarbeiten mußte und nur wenig brauchbare Hilfe gefunden habe. Das
erarbeitete Know-How wollte ich nun weitergeben. Ich finde es gut wenn
es auch anderen nützt.
Guten Rutsch
Mario
hallo Andy,
ich versuche das Bootloader-Programm auf Atmega8 zu übertragen, leider
ohne Erfolg.
Meine Einstellungen für den Fuse sind: LOW:0x44 HIGH:0x41. Sind sie
richtig?
Hast das Programm geändert(ausser die Zeilen:
temp = GICR;
GICR = temp | (1<<IVCE);
GICR = temp | (1<<IVSEL);
)
Danke im Voraus
hallo zusammen,
ich habe folgendes gemacht:
1. Die Bootrst wurde unprogrammiert. Das Bootloader programm geflasht
und dann die Anwendung eingefügt (wie es in die Anleitung beschrieben).
Nach einem Reset, wird die Anwendung ausgeführt. Nach der Eingabe eine
'b', wird das Programm zum Bootloader-Bereich gesprungen und bleibt
hängen.
Hallo hier ist der echte Bootloader
Programmiere den Flash!
Kopiere die Hex-Datei und f▒ge sie hier ein (rechte Maustaste)
................................................................P
................................................................P
................................................................P
................................................................P
................................................................P
................................................................P
................................................................P
................................................................P
................................................................P
............................................................P
Reset AVR!
Hier ist das Anwendungsprogramm...
Du hast folgendes Zeichen gesendet:
Du hast folgendes Zeichen gesendet:
Du hast folgendes Zeichen gesendet:
Du hast folgendes Zeichen gesendet:
Du hast folgendes Zeichen gesendet:
Du hast folgendes Zeichen gesendet: d
Du hast folgendes Zeichen gesendet: d
Du hast folgendes Zeichen gesendet: d
Du hast folgendes Zeichen gesendet: d
Springe zum Bootloader...
Hallo hier ist der echte Bootloader
Reset AVR!
2. Wenn ich das Bootrst-bit programmiere, bleibt das Programm hängen.
Hallo hier ist der echte Bootloader
Programmiere den Flash!
Kopiere die Hex-Datei und f▒ge sie hier ein (rechte Maustaste)
................................................................P
................................................................P
................................................................P
................................................................P
................................................................P
................................................................P
................................................................P
................................................................P
................................................................P
............................................................P
Reset AVR!
Ich benutze
- AVR Studio 4.18
- WinAVR-20100110
- Extrem Burner
-Putty (Einstellung 9600,8,Kein,XON/XOFF)
- Atmega8 mit ext. Quarz 16MHz. Fuse: LOW: FF HIGH : D1
Kann jemand mir weiter helfen??
halloMario,
Schön,das Du da bist.
ich habe den ersten Test auf Atmega32, hat wunderbar geklappt. Nun jetzt
teste ich den Atmega16 und macht Ärger.
Ich habe die gleichen Programme wie für Atmega32 genommen und auf
Atmega16 übertragen. Die Adresse des Bootloaders auf (word: ox1C00,
Byte:0x3800) geändert. Nach dem Flashen des Bootloaders habe ich
versucht, die kleine Anwendung (auch schon angepasst auf Atmega16)
kopiert (ich meine hex-File) und angefügt, leider klappt nicht die
Übertragung, es wird immer unterbrochen.
Hast du eine Idee?
Danke im Voraus
Die Fuse: Low FF, High:D0 (Extern Quarz 16MHz)
Leandro Leandro schrieb:> Ich habe die gleichen Programme wie für Atmega32 genommen und auf> Atmega16 übertragen. Die Adresse des Bootloaders auf (word: ox1C00,> Byte:0x3800) geändert. Nach dem Flashen des Bootloaders habe ich> versucht, die kleine Anwendung (auch schon angepasst auf Atmega16)> kopiert (ich meine hex-File) und angefügt, leider klappt nicht die> Übertragung, es wird immer unterbrochen.
Kannst du mal einen Screenshot der Ausgabe im Terminal machen?
Welche Baudrate verwendest du?
Das Hauptproblem bei der Übertragung ist die Flußkontrolle. Meistens
hängen die Problem damit zusammen. Die Software-Flußkontrolle (XON/XOFF)
funktioniert nur so leidlich. Wenn der Controller mit Daten zugeballert
wird kann er u.U. das XOFF nicht mehr senden, besser wäre die
Implementation einer Hardware-Flußkontrolle (DTS/RTS).
ich habe die folgenden Baudrate: 9600, 19200 und 115200 versucht, leider
wurde das Problem nicht behoben.
anbei ein Screenshot:
Hallo hier ist der echte Bootloader
Reset AVR!
Hallo hier ist der echte Bootloader
Reset AVR!
Hallo hier ist der echte Bootloader
Reset AVR!
Hallo hier ist der echte Bootloader
Reset AVR!
Hallo hier ist der echte Bootloader
Programmiere den Flash!
Kopiere die Hex-Datei und f▒ge sie hier ein (rechte Maustaste)
........................................................................
........................................................P
........................................................................
........................................................P
und dann bleibt hängen.
Sieht komisch aus, al ob die Flashgröße (SPM_PAGESIZE) nicht stimmt oder
der Parser nicht funktioniert. Scheinbar schreibt er ja 2 Pages, danach
bleibt er in einem State hängen.
Du mußt die mal ein paar mehr Debugausgaben machen, z.B. in welchem
State sich das Programm grade befindet. Ich empfehle einzelne Zeichen
(z.B. "S" für State State), da sonst die Übertragung zu sehr gestört
wird.
Welches Terminalprogramm nimmst du?
Die Programm was du runterlädst ist definitiv für den Atmega16?
1. ich benutzte putty.
2. Die Programme sind für Atmega16.
ich benutze jetzt Baudrate 19200 und habe die delays vom 100 auf 10
gesetzt.
es hat nur einmal geklappt und dann niemehr
Leandro Leandro schrieb:> ich benutze jetzt Baudrate 19200 und habe die delays vom 100 auf 10> gesetzt.>> es hat nur einmal geklappt und dann niemehr
Versuch mal den bootloader neu zu flashen. Geht es dann beim ersten mal?
habe ich gerade gemacht und es wurde wieder unterbrochen. nachdem ich
nochmal geflasht habe, könnte ich keine eingabe machen bzw. hat er nicht
auf meine Eingaben reagiert:
Reset AVR!
Hallo hier ist der echte Bootloader
Reset AVR!
Hallo hier ist der echte Bootloader
Reset AVR!
Hallo hier ist der echte Bootloader
Reset AVR!
Hallo hier ist der echte Bootloader
Hallo,
bei mir funktionierts leider nicht mit einem Mega32. Kann man bei putty
irgendwie ein delay einstellen? Bzw. mit welchem Terminlprogramm (linux)
kann man eine Verzögerung hinbekommen? Mit GtkTerm scheints nicht zu
gehen. Trotzdem guter Artikel. Schade dass es nicht läuft.
Viele Grüße
Hallo,
bei mir funktionierts jetzt auch. Hab die Flusssteuerung raus genommen,
die Puffer erhöht und die Baudrate (auf 300) runter gesetzt. So ist das
jetzt zwar erst mal eine Zumutung bei der Nutzung aber es läuft
grundsätzlich. Jetzt muss das halt noch etwas optimiert werden.
Danke für den Artikel und viele Grüße!
Hallo Zusammen,
ich habe mehrere Schaltungen mit ATMega 328 und 644 mit diesem
Bootloader im Einsatz.
Nach einem Jahr ist jetzt bei einem 644 folgendes passiert:
Eine Schaltung lief mehrmals wöchentlich bei jedem Neustart immer sauber
an, doch nun nach ca. 12 Monaten passiert nichts mehr.
Also die Schaltung ausgebaut (war natürlich nicht so einfach) und in die
Werkstatt gebracht.
Nach dem Netz Ein meldet sich der Bootloader wie gewohnt einmal, aber
das Anwenderprogramm wird nicht gestartet. Seit einem Jahr war an der
seriellen Schnittstelle aber nichts mehr angeschlossen.
Da ich die LockBits so eingestellt habe, das man den Controller nicht
mehr auslesen kann (Further programming and verification disabled) kann
ich auch nicht nachsehen, was da nun falsch ist.
Was kann wohl die Ursache dafür sein?
# Controller defekt?
# Spannungsschwankungen? ich schalte die 5V Versorgung bei <4.2V ab
# Fehler im Anwenderprogramm?
# ???
Hat sonst jemand ähnliche Erfahrungen gemacht?
Gruß
Jan
Ich finde den Artikel sehr gelungen. Die Grammatik ist nicht so schlimm,
du hast was auf die Beine gestellt, allein das zählt.
Nun zu meiner Frage:
Da ich kein AvrStudio habe(ich benutze Linux) möchte ich wissen wie man
den Bootloader mit avr-gcc kompiliert.
Hoffe Du kannst mir da n bissl helfen.
Gruss TechChristoph
AVRMember schrieb:> Super Artikel :-) thumbsup> Wirklich schön geschrieben, und sehr informativ.
Danke für die Blumen :)
TechChristoph schrieb:> Da ich kein AvrStudio habe(ich benutze Linux) möchte ich wissen wie man> den Bootloader mit avr-gcc kompiliert.>> Hoffe Du kannst mir da n bissl helfen.
Unter dem AVRStudio werkt ja auch bloß das avr-gcc mit der Toolchain.
Insovern müsste nur das Makefile angepasst werden. Ein Linkerparameter
für die Verschiebung das Linken des Kompilats in den Bootloaderbereich
muß hinzugefügt werden: -Ttext=0x????
???? ist die Startadresse des Bootloeaderbereichs (s. Artikel)
Unter Linux wirst du sicher schon mit Makefiles arbeiten, da kannst du
den Parameter mit eintragen...
Hallo,
danke an Mario G. für den tollen Bootloader Artikel.
Ich bin auf ein kleines Problem gestoßen, sobald ein Programm mit Timer
über den Bootloader geladen wird hängt sich der Bootloader auf.
Vermutlich weil der Timer vom Programm noch aktiv ist.
Programme ohne Timer funktionieren problemlos.
Johann L. schrieb:> Das Problem mit "goto 0" ist, daß das kein Reset ist, sondern eben nur> ein "goto 0". Das initialisiert nicht die Hardware. Andererseits sind> viele Anwendungen so geschrieben, daß sie von einer initialisierten> Hardware ausgehen, zB Timer-Initialisierungen oder> UART-Initialisierungen etc. die |= verwenden beim Belegen von SFRs wo> sie eigentlich = meinen. Mit einer vor-initialisierten Hardware kann das> zu Problemen führen.
Gibt es dafür eine einfache Lösung?
Roman schrieb:> > Das Problem mit "goto 0" ist, daß das kein Reset ist> Gibt es dafür eine einfache Lösung?
Reset per Watchdog?
(cli(), Watchdog auf eine kurze Zeit einstellen, Endlosschleife)
Sebastian schrieb:> Roman schrieb:>> > Das Problem mit "goto 0" ist, daß das kein Reset ist>> Gibt es dafür eine einfache Lösung?>> Reset per Watchdog?> (cli(), Watchdog auf eine kurze Zeit einstellen, Endlosschleife)
Dann hast du das 'Problem', dass du nach einem Reset wieder im
Bootloader landest. Und das soll ja auch so sein. Selbst wenn in der
eigentlichen App nichts mehr geht, soll man mittels eines Reset immer
wieder zumindest in den Bootloader kommen können um eine neue
Programmversion einspielen zu können.
Zum genannten Problem fällt mir eigentlich nur ein:
Dann muss eben der Bootloader alle von ihm benutzten
Konfigurationsregister vor dem Sprung in die Applikation wieder auf ihre
Ausgangswerte zurücksetzen.
So viel benutzt ein Bootloader ja üblicherweise nicht, so dass das
durchaus handhabbar sein sollte.
Roman schrieb:> Ich bin auf ein kleines Problem gestoßen, sobald ein Programm mit Timer> über den Bootloader geladen wird hängt sich der Bootloader auf.> Vermutlich weil der Timer vom Programm noch aktiv ist.>> Programme ohne Timer funktionieren problemlos.
Vor dem Sprung in den Bootloader sollten man dafür sorgen dass keine
Timer mehr aktiv sind.
Am Anfang des Bootloaders werden ja auch die Adressen der
Interrupt-Vektoren in den Bootloader Bereich verschoben:
1
...
2
/* Interrupt Vektoren verbiegen */
3
temp=MCUCR;
4
MCUCR=temp|(1<<IVCE);
5
MCUCR=temp|(1<<IVSEL);
6
...
und kurz vor dem Sprung zurück ins Programm wieder an die richtige
Adresse zurück gestellt:
1
...
2
/* Interrupt Vektoren wieder gerade biegen */
3
temp=MCUCR;
4
MCUCR=temp|(1<<IVCE);
5
MCUCR=temp&~(1<<IVSEL);
6
...
In welchem Zustand die interruptfähigen Hardware-Elemente des
Controllers sind, muß der Nutzer selbst festlegen.
Ich könnte mir vorstellen, das ein Verschieben der Interrupt-Vektoren
mit aktivem Timer Probleme macht..
Ist es dieses Problem was du meinst?
Hallo Zusammen,
erstmal Vielen Dank, dass du dir die Mühe mit dem Tutorial gemacht hast!
Ich finde es echt sehr gut gelungen. :)
Bei mir scheint es allerdings leider nicht vollständig zu funktionieren.
Ich nutze den Bootloader auf einem ATmega2560 und habe ihn dafür etwas
angepasst, den Hex-Parser habe ich allerdings 1 zu 1 übernommen.
Mir ist nun aufgefallen, dass per Bootloader geflashte Programme nicht
richtig zu funktionieren scheinen. Es tritt immer wieder unerklärliches
Verhalten, wie zum Beispiel komische Zeichen im UART auf. Flashe ich
dasselbe Programm dann direkt, funktioniert alles wie gewollt.
Zum Testen habe ich deshalb ein Programm einmal per Bootloader und
einmal direkt per JTAG geflasht und beide Male anschließend den Inhalt
des Flashspeichers ausgelesen. Mir ist dabei aufgefallen, dass drei
Zeilen der ausgelesenen Hex-Dateien nicht übereinstimmen (den
Bootloaderteil am Ende des Flash ausgenommen). Es scheint also, dass der
Bootloader die Hex-Datei nicht richtig flasht bzw. einige Teile nicht
richtig übernimmt. Aus diesem Grund funktioniert logischerweise das
geflashte Programm nicht richtig.
Ich weiß nicht, ob es notwendig ist den Code hier zu posten, da
zumindest der Parser-Teil 1 zu 1 aus dem Tutorial übernommen ist. Falls
doch kann ich das gerne nachholen.
Ich bin noch ein Anfänger und würde mich über jedwede Tipps oder
Ratschläge freuen!
Schonmal Danke im Vorraus.
Dominik schrieb:> des Flashspeichers ausgelesen. Mir ist dabei aufgefallen, dass drei> Zeilen der ausgelesenen Hex-Dateien nicht übereinstimmen (den> Bootloaderteil am Ende des Flash ausgenommen).
Dann stell fest welche das sind bzw. worin sie sich unterscheiden und
such nach Mustern in den Fehlern. Das können zb auch spezielle Adressen
sein an denen das zu Flashende steht (zb Page-Grenzen oder dergleichen).
> Ich bin noch ein Anfänger und würde mich über jedwede Tipps oder> Ratschläge freuen!
Ist kein Argument.
Wer einen Bootloader schreibt muss auch damit rechnen selbst debuggen zu
müssen. Irgendwann muss man schliesslich ja auch mal die Technik des
Fehlersuchens lernen. Ein Bootloader ist da jetzt nicht unbedingt ein
ideales Objekt dafür, aber ... den hast du dir ausgesucht.
Hallo allerseits,
ich bin gerade dabei, den Bootloader für den 16er ATMEGA umzusetzen. Zum
Thema "Interrupt Vektoren" verbiegen ist es vielleicht auch wichtig zu
erwähnen, dass man mit dem Debuglevel aufpassen muss. Sonst wird das
nichts mit den 4 Taktzyklen.
Ich hoffe, ich habe die Information nicht im Tutorial oder hier im
Thread übersehen. Falls doch, bitte ich um Nachsicht.
lg Torsten
hallo,
ich sitze gerade am bootloader-tutorial und komme leider beim letzten
schritt nicht weiter (die anwendung per bootloader laden).
aber weil ich mir unsicher bin, ob ich bis hierhin alles richtig gemacht
habe, hier mein bisheriger weg:
ich benutze den im tutorial verwendeten atmega88 mit dem stk500 als
programmer und als "test-hardware" mit der zweiten seriellen
schnittstelle, mache das alles unter linux mit avrdude und putty.
nun zu den drei einzelnen etappen:
1. "hallo welt": hier hatte ich zunächst vier probleme/fragen:
a) warum lässt sich die extended fuse nicht auf 0xf8 setzen?
ich habe leider lange dafür gebraucht, aber jetzt bin ich mir recht
sicher: weil es das beim atmega88 nicht gibt und die fuse auf 0x00 genau
richtig ist. falls ich da richtig liege, kann man das ja im tutorial
verbessern, das verwirrt anfänger wie mich etwas).
b) wo trage ich das "-Ttext=0x1800" ins makefile ein?
ich verwende dieses makefile:
https://www.mikrocontroller.net/wikifiles/b/b6/Makefile
und da gibt es folgenden absatz:
# Linker flags.
# -Wl,...: tell GCC to pass this to linker.
# -Map: create map file
# --cref: add cross reference to map file
LDFLAGS = -Wl,-Map=$(TARGET).map,--cref
LDFLAGS += $(EXTMEMOPTS)
LDFLAGS += $(PRINTF_LIB) $(SCANF_LIB) $(MATH_LIB)
und den habe ich so erweitert:
# Linker flags.
# -Wl,...: tell GCC to pass this to linker.
# -Map: create map file
# --cref: add cross reference to map file
LDFLAGS = -Wl,-Map=$(TARGET).map,--cref
LDFLAGS += $(EXTMEMOPTS)
LDFLAGS += $(PRINTF_LIB) $(SCANF_LIB) $(MATH_LIB)
LDFLAGS += -Ttext=0x1800
c) uart-library einbinden:
ich habe die library runtergeladen, im gleiche verzeichnis, wie die
main.c entpackt, es funktionierte aber erst, nachdem ich noch folgendes
ins main.c geschrieben habe:
#include "uart.c"
d) freq.
der uart hat "was" gemacht, aber immer nur "sonderzeichen". dann habe
ich folgendes in die main.c geschrieben und dann ging es:
#define F_CPU 8000000
waren diese bisherigen schritte so ok von mir?
2. die test-anwendung:
ich habe auch hier wieder die schritte 1.a)+c)+d) gemacht und dann ging
es.
3. der echte bootloader:
hier habe ich wieder die schritte 1.a)-d) komplett durchgeführt und der
bootloader verhält sich, wie beschrieben - bis ich das hex-file eingebe.
bei linux mache ich das nicht mit der rechten, sondern der mittleren
maustaste, aber sonst, wie im tutorial mit der dort angegebenen datei.
der bootloader erkennt, dass es eine hex-datei ist die ersten "punkte"
erscheinen. nach etwa 10-20 "punkten" stoppt der bootloader und es
kommen etwa ebenso viele sonderzeichen.
dann wurde mir klar, dass das hex für die anwendung ja nicht meinen
änderungen an der main.c bneinhaltet (siehe oben 1. c)+d). also bin ich
in den ordner, den ich erfolgreich für die test-anwendung verwendet habe
und habe und habe die dort liegende main.hex geöffnet und es mit diesem
hex-text versucht.
die anzahl der punkte und sonderzeichen waren abweichend aber in der
selben grössenordnung und sonst war alles gleich.
ich habe dann ewig rumgesucht und nur den hinweis gefunden, es mal mit
niedrigeren baudraten zu versuchen. das habe ich gemacht und die
übertragung ist auch merkbar langsamer, aber das ergebnis bleibt das
gleiche.
ich habe jetzt keine ahnung mehr, wo ich weiter nach einem ansatz suchen
soll und freue mich über jeden hinweis (auch bestätigung meiner
bisherigen schritte wären hilfreich, dann weiss ich schnomal, wo ich
nicht weiter suchen muss).
vielen dank und beste grüsse
a.
Hallo,
es war von mir sicherlich nicht richtig, dass ich die Gross- und
Kleinschreibung missachtet habe, ich finde die Antwort stilistisch dann
aber ehrlich gesagt auch etwas dürftig (Netiquette sagt meines Erachtens
u.A.: „Vergiss niemals, dass auf der anderen Seite ein Mensch sitzt!“).
Aber egal - hier also nochmal:
Ich sitze gerade am Bootloader-Tutorial und komme leider beim letzten
Schritt nicht weiter (die Anwendung per Bootloader laden).
Aber weil ich mir unsicher bin, ob ich bis hierhin Alles richtig gemacht
habe, hier mein bisheriger Weg:
Ich benutze den im Tutorial verwendeten Atmega88 mit dem Stk500 als
Programmer und als "Test-Hardware" mit der zweiten seriellen
Schnittstelle, mache das alles unter Linux mit avrdude und putty.
Nun zu den drei einzelnen Etappen:
1. "Hallo Welt": Hier hatte ich zunächst vier Probleme/Fragen:
a) Warum lässt sich die Extended Fuse nicht auf 0xf8 setzen?
Ich habe leider lange dafür gebraucht, aber jetzt bin ich mir recht
sicher: Weil es das beim Atmega88 nicht gibt und die Fuse auf 0x00 genau
richtig ist. Falls ich da richtig liege, kann man das ja im Tutorial
verbessern, das verwirrt Anfänger wie mich etwas).
b) Wo trage ich das "-Ttext=0x1800" ins Makefile ein?
Ich verwende dieses makefile:
https://www.mikrocontroller.net/wikifiles/b/b6/Makefile
Und da gibt es folgenden Absatz:
# Linker flags.
# -Wl,...: tell GCC to pass this to linker.
# -Map: create map file
# --cref: add cross reference to map file
LDFLAGS = -Wl,-Map=$(TARGET).map,--cref
LDFLAGS += $(EXTMEMOPTS)
LDFLAGS += $(PRINTF_LIB) $(SCANF_LIB) $(MATH_LIB)
Und den habe ich so erweitert:
# Linker flags.
# -Wl,...: tell GCC to pass this to linker.
# -Map: create map file
# --cref: add cross reference to map file
LDFLAGS = -Wl,-Map=$(TARGET).map,--cref
LDFLAGS += $(EXTMEMOPTS)
LDFLAGS += $(PRINTF_LIB) $(SCANF_LIB) $(MATH_LIB)
LDFLAGS += -Ttext=0x1800
c) Uart-Library einbinden:
Ich habe die Library runtergeladen, im gleichen Verzeichnis, wie die
main.c entpackt, es funktionierte aber erst, nachdem ich noch folgendes
ins main.c geschrieben habe:
#include "uart.c"
d) Freq.
Der Uart hat "was" gemacht, aber immer nur "sonderzeichen". Dann habe
ich folgendes in die main.c geschrieben und dann ging es:
#define F_CPU 8000000
Waren diese bisherigen Schritte so ok von mir?
2. Die Test-Anwendung:
Ich habe auch hier wieder die Schritte 1.a)+c)+d) gemacht und dann ging
es.
3. Der echte Bootloader:
Hier habe ich wieder die Schritte 1.a)-d) komplett durchgeführt und der
Bootloader verhält sich, wie beschrieben - bis ich das Hex-File eingebe.
Bei Linux mache ich das nicht mit der rechten, sondern der mittleren
Maustaste, aber sonst, wie im Tutorial mit der dort angegebenen Datei.
Der Bootloader erkennt, dass es eine Hex-Datei ist, die ersten "Punkte"
erscheinen. Nach etwa 10-20 "Punkten" stoppt der Bootloader und es
kommen etwa ebenso viele Sonderzeichen.
Dann wurde mir klar, dass das Hex-file für die Anwendung ja nicht meine
Änderungen an der main.c beinhaltet (siehe oben 1. c)+d). Also bin ich
in den Ordner, den ich erfolgreich für die Test-Anwendung verwendet habe
und habe die dort liegende main.hex geöffnet und es mit diesem
Hex-Text versucht.
Die Anzahl der Punkte und Sonderzeichen waren abweichend aber in der
selben Grössenordnung und sonst war alles gleich.
Ich habe dann ewig rumgesucht und nur den Hinweis gefunden, es mal mit
niedrigeren Baudraten zu versuchen. Das habe ich gemacht und die
Übertragung ist auch merkbar langsamer, aber das Ergebnis bleibt das
gleiche.
Ich habe jetzt keine Ahnung mehr, wo ich weiter nach einem Ansatz suchen
soll und freue mich über jeden Hinweis (auch Bestätigung meiner
bisherigen Schritte wären hilfreich, dann weiss ich schonmal, wo ich
nicht weiter suchen muss).
Vielen Dank und beste Grüsse
A.
a) Es gibt sehr wohl eine "Extended Fuse" im Atmega88 --> siehe
Datenblatt http://www.atmel.com/Images/doc2545.pdf --> Seite 286, diese
Fuse legt die Größe der "bootloader section" fest
b) Dieser Angabe der Position der Section ".text" gehört natürlich zu
den Linkerflags, ist also bei LDFLAGS gut aufgehoben
c) Du musst das Makefile entsprechend anpassen und ein Target für uart.c
hinzufügen, siehe z.B. hier
http://www.cs.colby.edu/maxwell/courses/tutorials/maketutor/
d) das define von F_CPU habe ich nicht explizit erwähnt, aber
vorausgesetzt. Die uart-Bibliothek benötigt für die Berechnung der
Baudraten-Timerwerte die Prozessorfrequenz
Generell:
Testanwendung und Bootloader sind zwei verschiendene Programme. Für die
Testanwendung brauchst du ein eigenes Makefile, welches die Verschiebung
von ".text" nicht enthält.
Hallo,
super - vielen Dank für die Antwort.
zu a):
Da habe ich mich dann missverständlich ausgedrückt. Natürlich gibt es
eine Extended Fuse. Allerdings kann die nicht den Wert 0xF8 annehmen, da
sie nicht so viele Bits nutzt. Wenn ich mich richtig erinnere, waren es
nur die unteren drei und da sind 0xF8 und 0x00 gleich. Somit funtioniert
es auch, wenn ich die Fuses auf 0xF8 setze, weil die Fuses, die gesetzt
werden können ja richtig sind. Avrdude gibt mir aber eine Fehlermeldung
aus, weil er versucht alle Bits auszulesen und das geforderte 0xF8
findet er nicht vor. Also im Ergebnis alles kein Problem, aber es gibt
eine unnötige Fehlermeldung, wenn man avrdude verwendet.
Ich hoffe, ich habe das jetzt alles richtig und verständlich
wiedergegeben.
zu c):
Vielen Dank für den Link, das werde ich mir in Ruhe anschauen. Aber
jetzt schon eine Frage: Mein Weg (Eintragen in die main.c) hat ja
funktioniert - ist das falsch oder unsauber oder ist das auch OK?
Zum Generellen:
Das mit den zwei unabhängigen Anwendungen habe ich verstanden und sowohl
der Hallo-welt-Bootlaoder, als auch die Einfach-Anwendung laufen ja
jetzt problemlos und auch der Echte-Bootloader scheint ja erstmal zu
machen, was er soll.
Ich stehe jetzt leider an dem Punkt, dass entweder der Bootloader einen
Fehler macht, wenn er das Hex-File verarbeiten soll oder das Hex-File
einen Fehler hat und deshalb nicht verarbeitet werden kann. Aber wer der
beiden jetzt der "Schuldige" ist und wie ich den Fehler dann finden
kann, da bin ich momentan etwas ratlos und hoffe weiterhin auf Hilfe.
Beste Grüsse
A.
Hallo Zusammen,
ich habe mehrere Schaltungen mit ATMega 328 und 644 mit diesem
Bootloader im Einsatz.
Hat bisher problemlos funktioniert.
Nun habe ich das Anwendungsprogramm für den ATMeaga 328 etwas erweitert.
Wenn ich das Programm direkt in den Controller schreibe funktioniert es
wie gewollt.
Lade ich es jedoch via Bootloader, dann macht der Controller permanet
einen Reset.
Benutze ich für das geänderte Programm eine andere Optimierungs
Einstellung des Compilers, funtioniert das Programm auch wieder mit dem
Bootloader.
Ursprungsprogramm: 14282 Byte mit Compiler Optimierung -Os läuft
geändertes Programm: 14732 Byte mit Compiler Optimierung -Os läuft
nicht
geändertes Programm: 16188 Byte mit Compiler Optimierung -O1 läuft
Ich bin da ziemlich ratlos,
kann mir vieleicht jemand weiterhelfen?
Gruß
jan
Funktioniert das neue Programm wenn du es direkt auf den Controller
"flashst", also ohne Bootloader?
Die Bedeutung der Compileroptimierungen kann man hier nachlesen:
AVR-GCC-Codeoptimierung
In beiden Fällen (-Os und -O1) wird die Größe optimiert. Gibt es ein
Überlauf- oder Stackproblem, was evtl. in einer Variante wegoptimiert
wird?
Hallo Mario,
ja, ohne Bootloader läuft das Programm.
Ich habe in der Zwischenzeit herausgefunden, das der Fehler auftritt,
wenn ich 922 Telegramme zum Boatloader schicke.
Wenn mein Programm etwas verkleinere oder vergrößere, dann ist alles
gut.
Bei 921 und 923 funktioniert alles, bei 922 Telegrammen tritt der Fehler
auf.
Wie kann ich ein Überlauf - oder Stackproblem erkennen ?
Gruß
Jan
Überlauf und Stackprobleme sind üblicherweise schwer zu erkennen, da sie
in undeterministischen Verhalten münden, d.h. es passieren jedes Mal
andere Fehler. Da der Bootloader eigentlich relativ einfach gestrickt
ist könnte ich mir vorstellen das auch ein deterministisches Verhalten
auftreten könnte. Es passiert ja immer das gleiche. Hast du dir mal das
922 Telegramm angeschaut? Du meinst mit "Telegramm" doch sicher eine
Hex-Zeile, oder?
Häng doch mal dein Hex-File dran...
Hier mal die beiden Hex-Files.
Beide mit den gleichen Einstellungen compiliert.
Nur einen Delay Befehl hinzugefügt, um auf 923 telegramme zu kommen.
Und dann funktioniert es auch via Bootloader.
Direkt auf den Controller programmiert laufen beide.
Gruß
Jan
Es ist etwas seltsam, das die Länge "0x0E" vorkommt...aber sonst ok.
Es wäre noch interessant, ob irgendwelche Sprünge (Type 02, 05)
vorkommen. Das wird bislang nicht abgefangen.
Hi Mario,
das Tutorial gefällt mir sehr gut - danke für die Arbeit!
Eine Anmerkung und eine Frage:
- Vielleicht nimmst du diesen Thread in die Links mit auf
- Im "Hallo Welt Bootloader"-Teil steht folgende Anmerkung, die etwas
verwirrend ist:
"Achtung! Bug im Quellcode! Serielle Schnittstelle funktioniert nicht
mehr wenn es als Bootloder (mit Addr 0x0180 geflasht wird), bei 0x0000
funktioniert die UART aber es ist natürlich keine Bootloader Funktion
gegeben (Atmega8)"
Wie ist das jetzt gemeint? Müsste da 0x1800 stehen wahrscheinlich? Ich
habe obigen Hallo-Welt BL ausprobiert und an 0x1800 (bzw. beim 328p dann
0x7800) funktioniert UART so halb: Der Bootloader macht kein TX, also
gibts keine Info auf dem Terminal. Zeichen empfangen kann er aber
anscheinend schon (habe mit Blinksequenzen an einer Debug LED gesehen:
3x blinken bei Bootloader Start (also auch nach "q" Eingabe und Togglen
sonst). Sollte UART insgesamt tatsächlich nicht funktionieren, wäre er
ja an sich offensichtlich obsolet - also: wie ist das gemeint?
UART Ausgabe wäre ja schon noch schön - ist der von dir erwähnte Bug
denn bekannt? --> Oder geh ich einfach erstmal weiter im Tutorial
Richtung "echtem" Bootloader und da gibts dann keine Probleme?
Viele Grüße
Christian
Oh, Asche auf mein Haupt - TX des Atemgas war am falschen Pin des FTDI
verbunden. Jetzt klappt alles. Bleibt nach wie vor (und jetzt erst
recht) die Frage, wie die Anmerkung mit dem Bug zu verstehen ist.
Hallo Dominik,
das Problem das du beschreibst habe ich aktuell auch, es tritt bei mir
immer nach dem Schreiben einer Page auf. Es werden die Daten in der
nächsten Zeile nach dem Schreiben der Page nicht geschrieben, bzw.
teilweise wird quasi die übernächste Zeile geschrieben.
Beim ATMega2560 sollte eine Page auch 256 Byte lang sein, dort scheint
der Fehler aufzutreten.
Die Daten werden korrekt empfangen aber aktuell suche ich noch den
Fehler, wenn ich ihn finde poste ich ihn.
Gruß,
Martin
UART-Bug im Hallo Welt BL schrieb:> - Im "Hallo Welt Bootloader"-Teil steht folgende Anmerkung, die etwas> verwirrend ist:>> "Achtung! Bug im Quellcode! Serielle Schnittstelle funktioniert nicht> mehr wenn es als Bootloder (mit Addr 0x0180 geflasht wird), bei 0x0000> funktioniert die UART aber es ist natürlich keine Bootloader Funktion> gegeben (Atmega8)"
Ich weiß nicht wer das ins Wiki eingetragen hat, ich nicht. Ich habe es
mit dem Hinweis auf das Umschalten der Interruptvektoren wieder
entfernt. Man muß unbedingt darauf achten dass das richtige SFR für das
Umschalten verwendet wird, dann klappt es auch mit UART & Co...