Forum: Mikrocontroller und Digitale Elektronik Aus Programm heraus in den Bootloader springen


von Andreas (Gast)


Lesenswert?

Hallo,

ist es möglich aus dem laufenden Programm heraus in die
Bootloader-Sektion zu springen? Die Idee ist, dass ich über die
serielle Schnittstelle ein commando schicke, der ATMega in seinen
Bootloader springt und ich dann einfach den flash neu beschreiben
kann.

Im Moment ist es so, dass in der Bootloader-Sektion eine Taste
überprüft wird. Ist diese gedrückt, wird der Bootloader aktiv. Selbst
wenn ich in den Bootloader-Sektion spring, dann wird immernoch
überprüft, ob die Taste gedrückt ist. Das soll aber dann in diesem Fall
übersprungen werden.

Im Prinzip ist das ja dann sowas wie ein Reset. Habe mir auch überlegt,
z.B. im EEPROM ein flag zu setzen und dann einen Reset auszulösen. Wenn
bei einem Neustart das flag gesetzt ist, startet der Bootloader
ansonsten das Hauptprogramm.

Hat jemand eine Idee, wie man sowas realisieren könnte?

von JojoS (Gast)


Lesenswert?

das müsste gehen, hast du denn den Bootloader Code? Da braucht man dann
die Einsprungadresse die die Tastenabfrage umgeht. Wenn es C oder
Assembler ist kann man ein Label setzen und sieht die Adresse dann in
der Map die vom Linker generiert wird.

von Jens (Gast)


Lesenswert?

Per EEProm wird einfacher sein.
In den Bootloader Sprinngen sollte je nach dem kein Thema sein (Problem
ist nur die Adresse zu adressieren, es kann sein, dass du mehrmals
Sprinngen musst)

Das einzige, was ich nur nicht weiss ist, ob du den Flash Programmieren
kannst, ohne einen Reset zu geben.

von inoffizieller WM-Rahul (Gast)


Lesenswert?

Du kannst auch "einfach" den Controller in den watchdog schicken und
im Bootloader dann die letzte Reset-Quelle feststellen.

von TravelRec. (Gast)


Lesenswert?

Meines Erachtens ist es sicherer, den Bootloader nach dem Prozessorreset
immer per default aufzurufen und wenn eine gewisse Zeit nichts passiert
auf der Programmierschnittstelle, dann in´s Hauptprogramm zu springen.
Ansonsten hast Du ein schwerwiegendes Problem, wenn Dein Hauptprogramm
neu geflasht wird, irgendetwas dabei schiefgeht, der Bootloader das
Hauptprogramm startet und dieses dann nicht läuft und somit nie wieder
den Bootloader aufrufen kann. Also Bootloader als Quasi-Hauptprogramm
nach jedem Reset starten, dann, wenn keine Daten kommen, weiter in´s
Hauptprogramm. Das kostet kaum Zeit und ist extrem sicher, wenn der
Bootloader kugelsicher programmiert wurde. Der ATMega bietet für diese
Anwendung extra bestimmte Fuses und LockBits an.

von Andreas (Gast)


Lesenswert?

Nach dem Prozessorreset wird der Bootloader immer aufgerufen. Wenn dann
eine Taste gedrückt ist, kann man den µC flashen.

Nun will ich zusätzlich die Möglichkeit schaffen, direkt aus einem
Windowsprogramm zu flashen. Dazu will ich einen Befehl per RS232 an den
µC schicken, damit er in den Bootloader springt. Dann darf natürlich
nicht die Taste abefragt werden. Also muss entweder der Bootloader
wissen warum (Reset oder commando) er gestartet wurde, ober ich muss,
wie schon erwähnt, die Tastenabfrage überspringen.

Habe dazu, wie von JojoS vorgeschlagen, ein Label an die entsprechende
Stelle gesetzt. Wie bekomme ich aber nun die Adresse von dem Label? Ich
habe mit die .lss datei angesehen, da war die Adresse 1f888. Kommt das
hin?

Nun wollte ich einfach per Funktion im meinem Hauptprogramm zu dieser
Adresse springen. Ist doch ok so, oder?

von TravelRec. (Gast)


Lesenswert?

Nee, das mach mal nicht. Setze in Deinem laufenden Programm ein Flag an
eine genau spezifizierte Adresse im SRAM oder in einem Register und
löse einen Watchdog-Reset aus. Nur dann kannst Du sicher sein, daß Dein
Bootloader auch ganz bestimmt anläuft. Dieser kontrolliert dann das Flag
und gibt für die W....s-Software das Flashing frei.

von Sven (Gast)


Lesenswert?

>>spezifizierte Adresse im SRAM oder in einem Register

Bleibt der Zustand des Flags während eines Software-Reset sicher
erhalten? Ich würde sagen ja, aber weiss das jemand?

Wenn der Zustand des Flags nach einem Hardware-Reset (Brown-Out,
Einschalten) nicht definiert ist, kann das aber schiefgehen.

Sven

von TravelRec. (Gast)


Lesenswert?

Bei einem Software-Reset bleiben die Flags erhalten. Bei einem Hardware
Reset nach dem Einschalten sind sie undefiniert. Der Watchdog hingegen
verändert das SRAM nicht, wenn der Controller einmal läuft. Du kannst
ja mehrere Bytes mit definiertem Bitmuster füllen, um ganz sicher zu
gehen...

von JojoS (Gast)


Lesenswert?

die Adresse müsste man durch 2 Teilen, der Speicher wird doch Wortweise
addressiert, war das nicht so? Dann kommt man auf 0xFC44, das passt nur
wenn das ein Mega128 ist. Jetzt fehlt nur noch der Sprung zu dieser
absoluten Adresse.

von TravelRec. (Gast)


Lesenswert?

Direktes Springen in den Bootloader halte ich für - sorry - grob
fahrlässig, da keines der I/O Register dann initialisiert ist und man
von keinen definierten Zuständen ausgehen kann. Es sei denn, der
Bootloader kontrolliert das alles und fängt es entsprechend ab. Auf
jeden Fall sollte in der ersten Zeile des Bootloaders ein "cli"
stehen, damit nicht ein gerade auflaufender Interrupt der Bootloader
gleich wieder abschießt.

von JojoS (Gast)


Lesenswert?

warum und was ist nicht initialisiert? Der Bootloader macht doch nichts
besonderes und es ist alles initialisiert weil das Hauptprogramm schon
lief. Das die Interrupts gesperrt werden müssen ist richtig. Nur nach
dem Flashen würde ich einen Reset anspringen damit bei einem C-Programm
z.B. der Stack wieder sauber ist und der return nicht in unbekanntem
Code (weil ja neu geladen) landet.

von TravelRec. (Gast)


Lesenswert?

Nehmen wir mal an, der Controller startet, dann läuft er zuerst in den
Bootloader. Alles paßt. Alle I/O Register (auch die vom USART z.B)
haben die erwarteten Werte. Das Hauptprogramm wird angesprungen. Dort
wird alles Mögliche abgearbeitet und auch Register verändert. Nun wird
auf Befehl hin wieder in den Bootloader gesprungen. Dieser findet jetzt
aber plötzlich alles anders vor. Klar, man kann nun eine komplette Init
im Bootloader machen, und ebenso eine im Hauptprogramm, aber ist das
nicht doppelter Aufwand? Was ist an einem gezielten Reset, der den
Bootloader startet, so verkehrt?

von Peter D. (peda)


Lesenswert?

"warum und was ist nicht initialisiert? Der Bootloader macht doch
nichts besonderes und es ist alles initialisiert weil das Hauptprogramm
schon lief."


Juhu, ich nehme also die Init-Routinen von Word und rufe dann die
Funktonsroutinen von Excel auf !!!

Der PC wird mir aber was husten und bestenfalls nen Bluescreen machen.


Programme sind nur in sich funktionsfähig. Ich kann nicht 2 halbe
Hex-Files zusammwursteln und erwarten, daß dann überhaupt noch
irgendwas funktioniert.

Bootloader und Hauptprogramm, sind 2 völlig verschiedene Programme, die
nichts voneinander wissen.


Peter

von JojoS (Gast)


Lesenswert?

vielleicht ist das so wenn der Bootloader sehr komplex ist. Aber ich
habe einen einfachen seriellen Bootloader und der initialisiert sich
beim Start selber. Die 'lästige' Technik mit zusätzlichem Bootloader
Button habe ich auch, deshalb die gleiche Idee wie sie hier
vorgeschlagen wurde. Aber prinzipiell meinen wir ja schon das gleiche,
es ist doch nur die Frage wie man in den Bootloader kommt. Natürlich an
die Stelle vor der nötigen Initialisierung, und warum soll man da nicht
einfach hinspringen?

von JojoS (Gast)


Lesenswert?

Der Bootloader steht fest an einer Stelle im Speicher, dafür ist es ja
der Bootloader. Den betrachte ich also mal als eine Firmware die aus
dem Hauptprogramm nutzen kann. Erste Bedingung war ja das man den Code
kennen sollte damit man den Einsprung richtig setzen kann.
'Gefährlich' ist nur dafür ein Konstante zu nehmen wenn man den
Bootloader doch mal ändert. Dann wäre ein Export der Adresse und ein
Import im Linker des Hauptprograms sicherer. Mit irgendeinem
unbekannten Bootloader würde ich das auch nicht machen.

von Peter D. (peda)


Lesenswert?

Bootloader und Hauptprogramm benutzen Variablen und diese verteilt der
Linker irgendwo rein zufällig im SRAM.


Ruft das Hauptprogramm den Bootloader auf, sind die Variablen völlig
falsch initialisiert.
Der Bootloader muß also den SRAM völlig neu initialisieren, daran fürt
kein Weg vorbei.


Und der Bootloader darf nicht mehr zum Hauptprotgramm zurückkehren, da
er ja dessen Variablen zerstört hat. In der Regel hat er ja auch das
Hauptprogramm selber zerstört.
Er darf also nur an den Eintrittspunkt des Hauptprogramms (0x0000)
springen, damit dieses sich wieder neu initialisieren kann.


Eine völlig andere Sache sind API-Calls, die das Hauptprogramm benutzen
kann und die wieder zurückkehren.
Diese API-Calls müssen in Assembler geschrieben sein, damit sie keinen
SRAM benutzen, sondern nur den Stack und zerstörbare Register
(Scratchpadregister).
API-Calls macht man vorzugsweise auf die letzte Adresse des Flash, da
diese ja für jedes Derivat fest steht.


Peter

von Andreas (Gast)


Lesenswert?

Also,
nach dem flashen soll natürlich eine Reset ausgelöst werden. Aber
trotzdem scheint ja diese Methode nicht optimal zu sein. Wie könnte man
es denn besser lösen?

Mit dem Watchdog eine Reset auslösen und dann einfach im Bootloader die
Resetquelle abfragen habe ich mir auch schon überlegt. Im Moment habe
ich noch keine Watchdog im Programm. Das Feature werde ich aber
vielleicht hinzufügen und dann habe ich ein Problem.

Und wie sieht es mit dem Flag im EEPROM aus? Kann man im Prinzip mit
zwei Programmen die gleiche Stelle im EEPROM adressieren?

von Peter D. (peda)


Lesenswert?

Ich würds einfach so machen, wie in meinem Bootloader:

Nach jedem Reset wird zuerst in den Bootloader gesprungen und der
wartet 200ms, ob das richtige Paßwort reinkommt. Wenn nicht, dann
springt er zur Anwendung.

Um nun aus der Anwendung den Bootloader zu starten, kriegt die ein
Kommando, mit dem der Watchdogreset ausgelöst wird. Danach sendet der
PC sofort das Paßwort in einer Schleife, bis er eine Antwort bekommt.


Peter

von Andreas (Gast)


Lesenswert?

@Peter
Stimmt eigentlich. Das wird die beste Lösung sein. Jetzt fehlt mir ja
nur noch der richtige bootloader :-)

Benutzte zu Testzwecken gerade den von mthomas. Leider bekomme ich den
nur mit AVRProg zum laufen, aber nicht mit avrdude und avrosp. Deine
Bootloader habe ich mir auch schonmal angeschaut. Aber damals war
gelaube ich das Problem, dass er mit dem ATMega128 nicht richtig
funktioniert hat. Kann das sein? Wie sieht es denn da mittlerweile aus?

von Peter D. (peda)


Lesenswert?

Der Mega128 überschreitet die 64kB-Grenze und braucht daher
3Byte-Adressen.

Da ich aber auch nicht annähernd so extrem viel Flash brauche, habe ich
mich nicht näher mit dem Mega128 beschäftigt.

Mir ist rätselhaft, was man mit nem Mega128 bloß anfangen kann.

Für Entwicklungszwecke habe ich mir mal einen großen Mega32 gegönnt,
benutze aber eigentlich nur den Mega8.


Peter

von Andreas (Gast)


Lesenswert?

Naja,
ich bin bei mir knapp an der 64kB-Grenze. Gut, wenn ich beim
Kompilieren Optimierungen einschalte wird es auch weniger.

Respekt, wenn du in der Regel mit nem AtMega8 auskommst. Wieviele
Zeilen C-code haben dann deine Programme so?

Wäre es denn arg schwer, den bootloader so umzuschreiben, dass man auch
den kompletten AtMega128 flashen kann?

von Martin Thomas (Gast)


Lesenswert?

"Benutzte zu Testzwecken gerade den von mthomas. Leider bekomme ich den
nur mit AVRProg zum laufen, aber nicht mit avrdude und avrosp."

Ist nicht nur von mir, auch wenn man den Urspung im
Butterfly-Bootloader kaum mehr sieht. Inzwischen sind auch von anderen
viele Verbesserungen und Ereiterungen eingeflossen - siehe
readme-Datei.

avrosp habe ich nie ausprobiert. Aber mit avrdude funktioniert "mein"
AVRprog compatible-Bootloader. Man muss den Bootloader nur den ISP
Device-Type senden lassen und nicht dem BOOT Device-Type. AVRprog
unterscheidet diese, avrdude in der Version 5.1 aus WinAVR 4/06 scheint
noch auf Angabe des ISP-Typen zu bestehen. Flash/EEprom read/write
funktioneren bei AVRprog auch mit der ISP Angabe.

Im Bootloader-Quellcode gibt es dafuer eine Konfigurationsmoeglichkeit,
vgl. readme-Datei / main.c #define DEVTYPE.

(Fehler ist moeglicherweise inzwischen behoben, nicht mehr auf
aktuellem Stand, habe mich aus der Mithilfe bei der avrdude-Entwicklung
vor einiger Zeit zurueckgezogen)

Meine "test-batch":
1
@echo off
2
rem Use avrdude as programming-software with the AVRProg compatible
3
bootloader
4
rem Martin Thomas, 2006
5
6
rem Verfiy that the bootloader is configured with #define DEVTYPE
7
DEVTYPE_ISP
8
rem since it seems that avrdude does not work with "Boot"
9
device-types and needs
10
rem ISP device-types (at least in version 5.1 as in WinAVR 4/06)
11
12
set HEXFILE=cansniffer.hex
13
set PROGRAMMER=avr109
14
set PORT=com2
15
set BAUD=19200
16
set PART=atmega32
17
18
rem * disable safemode - bootloader can not "restore" fuses anyway
19
set DIS_SAVE=-u
20
21
avrdude %DIS_SAVE% -p %PART% -P %PORT% -c %PROGRAMMER% -b %BAUD% -v -U
22
flash:w:%HEXFILE% 
23
24
rem pause

Martin Thomas

von Peter D. (peda)


Lesenswert?

@Andreas,

"Respekt, wenn du in der Regel mit nem AtMega8 auskommst. Wieviele
Zeilen C-code haben dann deine Programme so?"


Naja, ich benutze noch Textdisplays (VFD), und da kann man alle
Ausgaben in ASCII machen, d.h. man braucht keinen großen Flash für
irgendwelche Bildchen und Animationen.


Mein größtes Projekt ist etwa 10.000 Zeilen und 30 c-Files groß,
inclusive aller defines in den h-Files.
Ich bin der dritte, der daran arbeitet, ist also nicht besonders
optimal geschrieben.

Es hat mich auch zum c-Fan gemacht, da ich Sachen ändern und hinzufügen
konnte ohne das ganze Programm zu kennen.

Der erste Entwickler hat da sowas wie ein OS entwickelt, d.h. es wird
zuerst erkannt, welche Module drinstecken, dann wird in einer Liste
gesucht, ob diese Konfiguration gültig ist und dann werden die
gerätespezifischen Module im SRAM installiert. Es ist daher relativ
viel SRAM nötig (8kB) und inzwischen 10 verschiedene Konfigurationen
möglich, die als Daten im Flash stehen.
Insgesamt werden also etwa 40kB benötigt.

Es ist ein 8051-Projekt, größere Projekte mache ich immer auf dem 8051,
da er 4 Interruptprioritäten hat.

Ich mag es, wenn man die einzelnen Module möglichst unabhängig und mit
wenigen Nebenwirkungen programmieren kann.
Und da sind Prioritäten äußerst bequem, da langsame Interrupts
keinerlei Rücksicht auf schnelle Interrupts nehmen müssen.


Mit den AVRs mache ich nur kleinere Sachen wegen der nur einen
Priorität. Obwohl einmal habe ich ne 2. Priorität mit nem freien Timer
einbauen müssen, wegen ner Software-PCM.


Peter

von JojoS (Gast)


Lesenswert?

ich habe den Ansatz mit dem Sprung in den Bootloader weiterverfolgt und
dabei einen Thread im gcc Forum gefunden:
http://www.mikrocontroller.net/forum/read-2-416971.html
da ich das auch mit gcc mache und Ergebnisse nicht allgemeingültig sind
poste ich meine Lösung in den gcc Thread.

von Andreas (Gast)


Lesenswert?

@Martin
Ich werde das ganze nochmal genau testen. Falls das Problem auch
weiterhin noch besteht, werde ich mal einen extra thread aufmachen

@Peter
Hätte mich auch gewundet, wenn 10.000 codezeilen in eine AtMega8
passend würden :-)

Besteht denn die Möglichkeit, Deinen bootloader auf den AtMega128 zu
trimmen?

@JojoS
Ich werden mit das ganze nochmal genauer anschauen. Wobei mir der
Vorschlag von Peter auch sehr gefällt.

von Peter D. (peda)


Lesenswert?

@Martin,


"Hätte mich auch gewundet, wenn 10.000 codezeilen in eine AtMega8
passend würden :-)"


Hat ja auch niemand behauptet.
40kB ist aber noch meilenweit von 128kB entfernt.


Peter

von Andreas (Gast)


Lesenswert?

@Peter
Ich wollte damit nur sagen, dass ich mir schon gedacht habe, dass du
auch programme schreibst, die nicht in einen Atmega8 passen.

Will ja nicht nerven, aber ist es möglich mit wenig aufwand deinen
bootloader für den atmeaga128 umzuschreiben?

von Martin Thomas (Gast)


Lesenswert?

Autor: Peter Dannegger (PeDa) Datum: 25.09.2006 10:11
"@Martin ..."

Ich habe das schon richtig verstanden. Andreas war der
"Verwunderte".

-

Ich kenne den PBOOT-code nicht wirklich, aber die erforderlichen
Erweiterung fuer groessere Flash-Speicher kann man sich wahrscheinlich
relativ einfach aus "meinem" Bootloader abschauen - es sind nur ein
paar Zeilen.
http://www.siwawi.arubi.uni-kl.de/avr_projects/#avrprog_boot

Martin Thomas

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.