www.mikrocontroller.net

Forum: Compiler & IDEs Bootloader Section


Autor: Marcel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich versuche gerade meinen Bootloader Code ans das Ende vom Flash zu
schieben. Folgende Code habe ich als Grundlage genommen:
#include <avr/io.h>
#include <avr/boot.h>

volatile char i=0;
void btl_run( void ) BOOTLOADER_SECTION;

int main( void )
{
    while(1)
        btl_run();    

    return 0;    
}

void btl_run( void )
{
    i++;
}

Im Makefile habe ich ebenfalls die Section verschoben und dem Linker
bekannt gegeben:

[SNIP]
LDFLAGS = -Wl, --section-start=.bootloader=0x1E000,
-Map=$(TARGET).map,--cref
LDFLAGS += $(EXTMEMOPTS)
LDFLAGS += $(PRINTF_LIB) $(SCANF_LIB) $(MATH_LIB)
[/SNIP]

Wie kann ich jetzt heraus finden ob er wirklich den Code ans Ende
gelegt hat?
AVR-Studio sagt, dass es nicht so ist :-(.

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
AVR Studio kann auch nicht mit sections außer .text, .data und
.bss umgehen.

Was sagt denn das .sym-File?

Ganz davon abgesehen, wenn du einen Bootloader als solches
schreibst, kannst du auf die section .bootloader auch verzichten.
Schreib alles ganz normal und verschiebe die .text-section dann
auf 0x1E000.

Autor: Marcel (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Im Anhang ist die Sym Datei und genau da steht nix von der .bootloader
section.

>Ganz davon abgesehen, wenn du einen Bootloader als solches
>schreibst, kannst du auf die section .bootloader auch verzichten.
>Schreib alles ganz normal und verschiebe die .text-section dann
>auf 0x1E000.

Ok. Werds mal testen. Dann sollte ich wenigstens debuggen können.

Autor: Marcel (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
passiert das genau das selbe wenn ich die text section verlege.
Avr Studio sagt immer noch, dass es am Anfang liegt.

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Irgendwas tut da mit deinem Makefile wohl nicht richtig...

Wenn du "make" aufrufst, siehst du denn die entsprechende -Ttext
Option in der Kommandozeile des GCC, der da zum Linken aufgerufen
wird?

Autor: Marcel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Jetzt geht es.

LDFLAGS = -Wl,--section-start=.text=0x1E000,-Map=$(TARGET).map,--cref
LDFLAGS += $(EXTMEMOPTS)
LDFLAGS += $(PRINTF_LIB) $(SCANF_LIB) $(MATH_LIB)

Irgendein Tool war ziemlich sensibel. Ich hatte im Makefile
zwischen "," und "-MAP" ein Leerzeichen. Das war zuviel.

Jetzt stellt sich mir gerade eine weitere Frage.

Da ich die Textsection nun verschoben habe, was passiert mit globalen
Variablen die ich eventuell im Bootloader verwende? Die werden so viel
ich weiss im Startupcode initialisiert. Hab ich jetzt ebenfalls einen
startup code im bootloader? Das wäre ja nicht sinn und zweck der sache.
Oder wird der Starupcode nur durch die Main funktion generiert? ich bin
verwirrt.

Autor: Werner B. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Der gesamte Code inclusive startup-code (crt1) wird auf 0x1E000
reloziert.

Autor: Marcel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
genau das möchte ich nicht. Was soll startupcode im Bootloader?
Bootloader soll schliesslich bootloader bleiben.

der bootloader soll aus der main heraus gestartet werden.

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Irgendein Tool war ziemlich sensibel. Ich hatte im Makefile
> zwischen "," und "-MAP" ein Leerzeichen. Das war zuviel.

Logisch.  Das alles gehört lückenlos hinter die -Wl-Option des
Compilers, denn diese Option besagt: ,,Schiebe den Rest der Option
durch zum Linker.''  Wenn du da ein Leerzeichen hast, beendet das
die
-Wl-Option, und der Compiler sucht nach weiteren Optionen auf seiner
Kommandozeile.  Du hättest natürlich nach dem Leerzeichen ein neues
-Wl starten können.

> der bootloader soll aus der main heraus gestartet werden.

Das ist nicht die normale Arbeitsweise eines Bootloaders.

Ein Bootloader ist normalerweise eine eigene Mini-Applikation, die mit
irgendjemandem in der Außenwelt in Kontakt tritt (RS-232, SPI, I²C,
Ethernet, ...) und von ihm eine neue Hauptapplikation entgegennimmt,
die es dann in den Applikationsbereich des Flashs programmiert.  Als
solches ist sie komplett eigenständig, einschließlich eigenem main()
(wenn man den Loader in C schreibt), ggf. eigenen Variablen, einer
eigenen Stack-Initialisierung -- kurzum, einem eigenen startup-Code.

Mir dünkt, du willst was komplett anderes tun und nennst das nur
Bootloader.  Aber dann solltest du dich genauer ausdrücken, meine
Kristallkugel muss ich erst wieder aus dem Keller holen...

Autor: Marcel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Aber dann solltest du dich genauer ausdrücken, meine
>Kristallkugel muss ich erst wieder aus dem Keller holen

lass die mal im Keller :).

ich habe selber noch nie mit einem bootloader gearbeitet, was ich aber
möchte, ist wie du schon sagtest meine haupt-applikation über den usart
updaten.

dazu habe ich mir gedacht, dass meine hauptapplikation ganz normal
arbeiten z.b Daten über den usart sendet und empfängt bis eine
bestimmte sequenz empfangen wird worauf die main-app den bootloader
startet und dieser beginnt die main-app zu löschen bzw. zu neu zu
schreiben. Vielleicht gibts es einen besseren weg dieses zu lösen. So
hatte ich mir das zumindest vorgestellt.

Autor: Daniel Braun (khani)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo

mal zu dem was Jörg wahrscheinlich mit Bootloader oder nicht-Bootloader
meinte :

Ein BOOTLOADER ist nach einem Reset bzw. nach dem einschalten (was oft
so gut wie ein Reset ist) aktiv und zwar bei jedem Neustart des
Systems. Der Bootloader liegt in einer bestimmten Region des
Programmspeichers (bei den AVRs muss er in der Bootloader-Section
liegen, damit man ihn sinnvoll einsetzen kann). Der Bootloader ist also
ein kleines Programm, welches nur wenige Aufgaben erfüllen kann. Der
Bootloader überprüft nun meist eine Bedingung, ob er aktiv werden soll.
Meist wird überprüft, ob ein bestimmter Pin auf einem bestimmten
Logikpegel gezogen wird oder Ähnliches. Ist dies nicht der Fall, wird
der Bootloader durch Anspringen des Hauptprogramms (meist ab Anfang des
Programmspeichers) beendet.
Läuft der Bootloader weiter kommuniziert er meist über eine
Schnittstelle direkt oder indirekt mit einem Programmiergerät, welches
dem Bootloader ein neues Anwendungsprogramm überträgt. Der Bootloader
haut das Programm dann in den Programmspeicher des Mikrocontrollers.
Manche Bootloader beenden danach automatisch den Vorgang indem sie das
Hauptprogramm anspringen, andere Bootoloader können nur durch einen
erneuten Hardware-Reset beendet werden.

Programme mit AUTOUPDATE-Fähigkeit (hier ist "auto" als "selbst",
nicht als Abkürzung von "automatisch" gemeint) sind eine andere
Baustelle. Solche Programme besitzen meist ein normales Hauptprogramm,
sowie einige Funktionen zum Laden eines neuen Hauptprogramms. Die
Funktionen, welche das neue Programm dann in den Programmspeicher
schreiben, bzw. die Kommunikation mit einem PC/Programmiergerät
abwickeln, sollten bei den AVRs wiederum in einem bestimmten Bereich
(Bootloader-Section) liegen, damit ein unvorhersagbares Verhalten des
Mikrocontrollers ausgeschlossen werden kann.

Vielleicht trägt das ja dazu bei, sich etwas genauer unterhalten zu
können.

MfG, Daniel.

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die main­-App (so es überhaupt gerade eine gibt zu diesem Zeitpunkt)
macht einfach einen Sprung an den Anfang des Bootloaders.  Damit
gibt sie die Steuerung komplett ab, der Bootloader agiert als
eigenständige Applikation (wenn nämlich die main-App nur aus 0xffff
besteht, gibt's z.B. noch keinen initialisierten Stackpointer) ab
diesem Moment.  Wenn er fertig ist, macht er einen Sprung nach 0,
und die main app übernimmt die Steuerung wieder.

Autor: Marcel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vielen Dank erstmal, das macht die Sache für schon mal etwas klarer.

Gehen wir also mal davon aus dass die main-app und der bootloader zwei
komplett voneinander getrennte systeme sind und nach dem Startup der
Bootloader am Ende des Flashes gestartet wird. Dann stellt sich mir die
Frage wie ich dem Compiler klar mache den Bootloader anzuspringen und
nicht die main-app?

Kann ich somit also zwei getrennte main routinen schreiben?
Einmal für die main-app und den bootloader?

Wenn ich nach dem updaten der main-app vom bootloader aus die
main-app starte und zu adresse 0x0000 springe werden dann alle
variablen der main-app initalisiert? Mir ist bisher bekannt, dass dem
nicht so ist.

Wenn ich Interrupts im Bootloader benutzen möchte muss ich ja die
INT-Vektor Tabelle mit in den Bootloader übernehmen. Gehts das
ebenfalls mit dem Compiler?

viele Fragen :-)

Autor: Werner B. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>...wie ich dem Compiler klar mache den Bootloader anzuspringen und
>nicht die main-app?

Das machst Du nicht mit dem Compiler, sonder über die FUSES BOOTSZ0..1
und BOOT??? (fällt mir jetzt nicht ein wie das andere FUSEBIT heisst).

>Kann ich somit also zwei getrennte main routinen schreiben?
>Einmal für die main-app und den bootloader?

Du kannst nicht, Du MUSST

>...werden dann alle
>variablen der main-app initalisiert?

Die 0000-Main app hat ja wieder seinen eigenen Startup-Code der alle
initialisierungen durchführt.

>Wenn ich Interrupts im Bootloader benutzen möchte...
Davon rate ich für_die_ersten_Versuche DRINGENST ab.
Sobald Du etwas besser vertaut mit dem erstellen eines Bootloader bist
kann man sich auf dieses etwas komplexe Thema stürzen.

Autor: Marcel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ok. werde mich dann jetzt mal an das thema ran wagen.

Zwei fragen hab ich aber noch:

1. Bekomme ich vom Compiler eine Warnung wenn der Speicherbereich in
den Bootloader Breich eintritt? Wenn z.B zu wenig Speicher vorhanden
ist.

2. Wie lade ich am besten Bootloader und main-app in den controller?
Getrennt nacheinander oder die Hex files miteinander verrödeln?

Autor: Μαtthias W. (matthias) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

zu 1.
Nö. Gibt keine Warnung. Warum auch? Der Bootloaderbereich läßt sich ja
ganz normal nutzen solange kein Bootloader verwendet wird. Zusätzlich
ist die Größe dieses Bereichs ja noch variabel (mittels Fusebits)

zu 2.
Zwei Möglichkeiten: Bootloader rein und dann mittels Bootloader die
Applikation oder Applikation und Bootloader zusammenfriemeln. Das
zusammenbauen erledigt bei mir ein kleines perl-Script. Kann ich auf
Wunsch liefern.

Matthias

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Aus dem Bootloader in die Applikation kann man übrigens über einen
Sprung nach 0 machen (so macht's Atmel's Appnote AVR109), aber ich
finde persönlich einen Watchdog-Reset etwas besser geeignet, da es ein
echter Reset ist, also auch alle IO-Register auf den Voreinstellungen
landen.

Allerdings hatte ich gestern ein etwas böses Erwachen mit dem
Wachhund: nach dem ersten Watchdog-Reset in einem ATmega644 wurden
danach sämtliche Ausschriften nach ca. 15 ms abgewürgt, und der
Controller ging wieder in den Reset.  Sieht so aus, dass bei allen
neueren Controllern (ab ATmega88) der Watchdog nach einem
Hardware-Reset (außer power-on) weiterläuft und dann mit der
kürzestmöglichen Zeitkonstante aktiviert ist.

Das Datenblatt empfiehlt daher, schnellstmöglich nach dem Reset das
WDRF in MCUSR zu löschen und den Watchdog auszuschalten.  Ich habe
folgende Empfehlung in die avr-libc-Doku aufgenommen:
#include <stdint.h>
#include <avr/wdt.h>

uint8_t mcusr_mirror;

void get_mcusr(void) \
  __attribute__((naked)) \
  __attribute__((section(".init3")));
void get_mcusr(void)
{
  mcusr_mirror = MCUSR;
  MCUSR = 0;
  wdt_disable();
}

mcusr_mirror braucht man natürlich nur, wenn man die Reset-Quelle
nachträglich noch auswerten will.

Autor: Marcel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ich habe heute in einem schnell durchgang einen kleinen Bootloader
implementiert (Fehlt noch einiges).

Jetzt möchte ich natürlich von meiner PC app den Loader updaten.
Dazu muss ich allerdings das Intel-Hex format verstehen. Gibts dafür
irgendwo eine beschreibung zu? bisher hab ich vergeblich gesucht.

Autor: Μαtthias W. (matthias) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

das glaub ich nicht das du länger als 10s gesucht hast:
http://www.google.de/search?hl=de&q=intel+hex+file...

Matthias

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
U. U. ist es auch sinnvoller, gleich von da aus ein
avrdude zu starten (so man einen Bootloader hat, der ein
Standardformat versteht).  So machen wir's derzeit in
der Firma.

Autor: Kai Klenovsek (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Jörg
Verstehe ich das jetzt richtig, dass in Avrdude eine Bootloader
Unterstützung drin ist? Ist mir bisher in der 4.3.0 nicht aufgefallen.
Zumal ich keinen Unterpunkt "Bootloader" in der Doc finde.

Ciao,
Kai

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das AVRDUDE muss ja auch nicht wissen, dass das ein Bootloader
ist. ;-)  In 4.x ist ja schon "butterfly" drin -- und das ist
letztlich genau das: ein Bootloader.  Leider ist der starr auf
19200 Bd festgelegt.  In 5-Beta habe ich das repariert, ich habe
ein paar kleine Inkompatibilitäten mit AVR109 beseitigt und die
Baudrate einstellbar gemacht, damit ist es jetzt komplett AVR109-
kompatibel.

Außerdem hat Matthias Weißer's USBisp natürlich schon lange gezeigt,
dass man eine Bootloader auch mit einem abgespeckten STK500-
Protokoll fahren kann...

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.