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.
Du deklarierst die Funktionen in Deinem Programm wie üblich:
1 | int externeFunktion(char *s, int i); |
damit der Compiler weiß, wie sie anzusprechen ist. Der Linker-Kommandozeile fügst Du dann zu:
1 | avr-ld ... --defsym externeFunktion=0xfa2 ... |
oder, wenn der Linker vom Compiler aufgerufen wird (was der übliche Fall ist):
1 | avr-gcc ... -Wl,--defsym,externeFunktion=0xfa2 ... |
So sollte es gehen. (Als Compiler habe ich den [avr-]gcc vorausgesetzt.)
Hc Zimmerer schrieb: > Der Linker-Kommandozeile fügst Du dann zu: >
1 | > avr-ld ... --defsym externeFunktion=0xfa2 ... |
2 | > |
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.
Wäre es nicht einfacher, Deine geheimen Funktionen zu ner Lib zu compilieren? Im Bootloader sind sie ja auch nicht gegen Auslesen geschützt. Peter
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.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.