Ich habe eine Frage an euch.
Ist es möglich, bei einem AVR vom eignetlichen Programm heraus auf
Funktionen im Bootloader zuzugreifen?
Ich möchte eine Art Ablaufsteuerung verwirklichen, bei der sich die
eignetlichen Funktionen im Bootloader befinden und nur die
Hauptprogrammschleife und zusätzliche Funktionen nachgeladen werden.
Ist soetwas möglich?
Sepp O. schrieb:> Ich habe eine Frage an euch.>> Ist es möglich, bei einem AVR vom eignetlichen Programm heraus auf> Funktionen im Bootloader zuzugreifen?
Ja ist es Mario Grafe hat gerade dazu eine Anleitung in die Artikel
Sammlung gestellt. und diese Anleitung hier auch Diskutiert
siehe mal unter
AVR Bootloader in C - eine einfache Anleitung: Die Test-Anwendung
Sepp O. schrieb:> Ist es möglich, bei einem AVR vom eignetlichen Programm heraus auf> Funktionen im Bootloader zuzugreifen?
Generell erstmal nein und prinzipiell jain.
In Assembler sind alle Schweinereien erlaubt. Obs aber auch praktikabel
ist, steht auf einem anderen Blatt.
In C oder Basic mußt Du mal Dein entsprechendes Manual befragen, ob
sowas unterstützt wird. Ich vermute mal, nein.
Es müßte quasi eine Art OS mit nem API implementiert werden.
Und der Compiler müßte entsprechende Schnittstellen und
Speicherverwaltung bereitstellen, damit sich die 2 Programme überhaupt
erstmal verstehen und auch nicht gegenseitig ihre Daten und den Stack
zerstören.
Peter
@Peter
Deinen Einwand verstehe ich nicht. Wenn man aus dem Hauptprogramm
lediglich eine Funktion des Bootloaders aufrufen will, so findet dies ja
im selben Kontext statt. Das einzige Problem ist doch, dass ich die
Adresse der Funktion wissen muss?
Gibt es eventuell eine Lösung die ähnlich ist wie bei der
PC-Programmierung bei DLL's, Plug in's,...?
Da gibt es ja auch dass Problem, dass man dem Programm mitteilen muss an
welcher Adresse sich die Funktion befindet.
StinkyWinky schrieb:> Das einzige Problem ist doch, dass ich die> Adresse der Funktion wissen muss?
Nicht nur das.
Du weißt nicht, wo sie steht.
Du weißt nicht, welche Argumente sie wo und wie haben will.
Du weißt nicht, wo und wieviel RAM sie belegt.
Du weißt nicht, welche Ressourcen (Ports, Interrupts) sie belegt.
Und was noch viel schlimmer ist, der Linker weiß es ja auch nicht.
Peter
Da ich den Boot-Loader schreiben werde dürften die Punkte mit mehr oder
nochmehr Aufwand zu lösen sein.
Was mir von Anfang an Kopfzerbrechen macht, ist wie ich das Ganze dem
Linker beibringe.
Gibt es da keine Möglichkeit etwas über Schnittstellen / Headerdateien
zu trixen?
Sepp O. schrieb:> Gibt es da keine Möglichkeit etwas über Schnittstellen / Headerdateien> zu trixen?
Du erzeugtst den Bootloader als normale Library. Mittels change-section
usw. an die richtige Stelle verschieben.
Lib linken mit minimalprogram, dessen main mit "weak"-attribut versehen,
damit der Linker nicht meckert.
Lässt sich dann so brennen, als reiner Bootloader.
Jetzt die Applikation ebenfalls gegen exakt diese library linken.
Bootloader-Funktionen sind dann ganz normal verfügbar.
Das daraus resultierende HEX-File enthält jetzt aber bootload UND
Applikation. Den Bootloader-Teil vorm Upload rausschneiden, der
Bootloader kann sich nicht selbst updaten. Alternativ kann der
bootloader einfach ungültige Adressen in seiner Eingabe ignorieren.
Sepp O. schrieb:> Da ich den Boot-Loader schreiben werde dürften die Punkte mit mehr oder> nochmehr Aufwand zu lösen sein.>> Was mir von Anfang an Kopfzerbrechen macht, ist wie ich das Ganze dem> Linker beibringe.
Gar nicht.
> Gibt es da keine Möglichkeit etwas über Schnittstellen / Headerdateien> zu trixen?
Natrülich. Du musst in deinem Anwenderprogramm deine Funktion so
verpacken, dass sie als konstanter Funktionspointer bekannt ist.
Zusammen mit dem richtigen Protoypen kannst du dann den Aufruf machen.
Die Schwierigkeit: Die Adressen der Funktionen feststellen.
Bei CP/M hat das zb so funktioniert:
An einer bekannten Stelle im Speicher gibt es ein Array mit
Funktionspointern (oder waren dort schon die Calls. Ich bin mir nicht
sicher, aber ich glaube dort waren schon die Calls), welche zu den
eigentlichen Funktionen führen. Das BDOS hat dieses Array aufgebaut und
seine eigenen Funktionsstartadressen dort eingetragen. Will ein
Anwenderprogramm eine BDOS Funktion aufrufen zb Konsolen-Ausgabe, dann
geht es über dieses Array, deren Lage im Speicher es kennt und deren
Reihenfolge der Funktionen fix ist.
Im Grunde/Prinzip nichts anderes als das was bei den Interrupt Vektoren
auch gemacht wird.
Ich zieh mein
[Zitat]
>> Was mir von Anfang an Kopfzerbrechen macht, ist wie ich das Ganze dem>> Linker beibringe.>> Gar nicht.
[/Zitat]
hiermit zurück :-)
Ich gehe davon aus, dass ich den Bootloader selber geschrieben habe,
also weiss ich:
- welche Argumente sie wo und wie haben will.
- wo und wieviel RAM sie belegt.
- welche Ressourcen (Ports, Interrupts) sie belegt.
Ferner weiss ich, an welcher Adresse mein Bootloader und mein
Hauptprogramm liegen. Als Bastel-Lösung kann ich die Adresse meiner
gewünschten BL-Funktion aus dem Map-File lesen und in meiner Applikation
verwenden.
Sollte ich aber den Bootloader ändern, muss ich natürlich die Adresse
der BL-Funktion im Hauptprogramm anpassen.
StinkyWinky schrieb:> Ich gehe davon aus, dass ich den Bootloader selber geschrieben habe,> also weiss ich:> - welche Argumente sie wo und wie haben will.> - wo und wieviel RAM sie belegt.> - welche Ressourcen (Ports, Interrupts) sie belegt.
Ich werden den Bootloader nicht vollkommen selbst schreiben, sondern nur
an meine Bedürfnisse anpassen.
Ich will ja das Rad nicht umbedingt komplet neu erfinden.
StinkyWinky schrieb:> Sollte ich aber den Bootloader ändern, muss ich natürlich die Adresse> der BL-Funktion im Hauptprogramm anpassen.
Dass ist aber im PC-Bereich beim Verwenden von Schnittstellen / Plugins
auch nicht anders.
@Hc Zimmerer
Dass ist ja genau das was ich suche.
Weist du wo ich detailierte Informationen darüber finde?
Hc Zimmerer schrieb:> (Als Compiler habe ich den [avr-]gcc vorausgesetzt.)
Ja, ich verwende AVR gcc. Genauer gesagt das aktuelle Win-AVR Paket.
Sepp O. schrieb:> @Hc Zimmerer> Dass ist ja genau das was ich suche.
Das dachte ich mir :).
> Weist du wo ich detailierte Informationen darüber finde?
In den Gnu Info Pages zu gcc und ld (->binutils), zu finden in der
Paketverwaltung jedes Linux-Systems oder online unter
http://www.gnu.org/manual/manual.html, Abschnitt „Software Development“.
StinkyWinky schrieb:> Ferner weiss ich, an welcher Adresse mein Bootloader und mein> Hauptprogramm liegen. Als Bastel-Lösung kann ich die Adresse meiner> gewünschten BL-Funktion aus dem Map-File lesen und in meiner Applikation> verwenden.
Wieso definierst du nicht eine schöne kleine Sprungtabelle im
Bootloader-Bereich? Damit hast du weniger Abhängigkeiten zwischen BL und
dem "normalen" Programm. Musst dich bloss einmal drauf einigen, wo die
Sprungtabelle im BL-Bereich liegt. Würd ich wohl ganz am Anfang machen.
Der erste Befehl als Jump in die BL main, dann weitere Jumps in die
exportierten functions. Kommt mal eine function hinzu, wird die Tabelle
einfach n bisschen grösser und der Code dahinter verschiebt sich um
einige Bytes.
Man kann es auch wie früher beim DOS-Interrupt machen.
Du hast eine Einsprungadresse, z.B. Flashend und in einem Register wird
die Funktionsnummer übergeben.
Interessant ist auch, ob der Bootloader Interrupts behandelt oder ob
auch die Applikation Interrupts enthalten darf.
Peter
ich hab so etwas für ein Projekt gemacht. Man benötigt natürlich
Funktionen die nur am Stack arbeiten, also nichts globales angreifen.
Bei mir waren das alles Verschlüsselungs- und Hashfunktionen, was es
noch einfacher macht, weil auch keine Hardwareabhängigkeiten bestanden.
Ich hab im Bootloader ein Array mit den Adressen der gewünschten
Funktionen an eine Bekannten Stelle abgelegt, damit ich sich mögliche
Änderungen im BL nicht auf die App durschlagen, angelegt. Und in der
Applikation verwenden ich dann diese Sprungtabelle für meine
Funktionsaufrufe. Funktioniert alles problemlos und man muss nicht mit
Linker herumtricksen.
Dass hört sich vielversprechend an.
Kann ich (und eventuell auch andere) ein Beispiel bekommen?
Denn dieses Thema dürfte sicher auch für andere Interessant sein.
Falls du mich meinst.
Bei mir hat es nichts mit Geheim zu tun.
Ich will nur so viele Funktionen wie möglich in den Prozessor
verfracchten, damit nur mehr das Steuerungsprogramm selbst nachgeladen
werden muss.
Sepp O. schrieb:> Ich will nur so viele Funktionen wie möglich in den Prozessor> verfracchten, damit nur mehr das Steuerungsprogramm selbst nachgeladen> werden muss.
Dann wird das aber mit dem Bootsektor nichts, der ist ja nur sehr klein.
Peter
stimmt die Bootloader Section im AVR ist ja auch nicht so groß, bei mir
war das ganze auf ARM7 bzw M3 Cortex.
Eine Frage hätte ich noch, warum willst du gewisse Teile deines
Programmes fix nicht updatebar machen, wenn du sie im Bootloader nicht
verwendest, damit kannst du mögliche Fehler mit Firmware Updates ja
nicht mehr beheben? Oder ist die oberste Prämisse die neue Firmware
möglichst klein zu halten?
Also nochmal mein Senf dazu, weiß jetzt leider nicht auswendig, ob das
alles im AVR so geht:
Bootloader mit allen anderen fixen, nicht updatebaren Funktionen an den
Beginn vom Flash -> das ganze Zeug muss natürlich auch gelinkt werden
und im ELF bzw HEX file da sein für später. Hier muss der Bootloader
natürlich jedes mal selbst in die Hauptapplikation springen.
1) Quick and dirty Variante um zu sehen ob es so funktioniert:
Hauptapplikation ist ein separates Projekt und bindet die Header Dateien
von den gewünschten Funktionen ein, aber die dazugehörigen Files werden
nicht kompiliert. Beim Linken sagst du dem Linker mit:
--just-symbols=filename
dass er sich die Symbole für die Adressen der Bootloader Funktionen aus
dem ELF File vom Bootloader holen soll. Somit kannst du deine App
kompilieren und Linken.
Nachteil: Änderungen am Bootloader schlagen sich direkt auf die APP
durch
2) BL und APP unabhängiger gestalten:
dazu im Bootloader entweder gleich zu Beginn oder am Ende seiner Section
ein Array mit den Adressen der Funktionen anlegen. In der Applikation
musst du dann aber jeden Funktionsaufruf, oder die Funktion selbst,
umschreiben und mit Funktionspointern arbeiten. Damit braucht die APP
nur mehr den Beginn des Arrays und die Reihenfolge der Funktionen
wissen.
Ich glaube, ich werde es erst einmal mit einer Lib versuchen.
Aber um zu sehen ob und wie es funktioniert, werde ich die Boot-Loader
Geschichte einmal ausprobieren.