Hallo an alle, ich habe mal eine Frage an die Fortgeschrittenen C-Programmierer unter euch. Ich hab schon seit längerem eine Idee und würde diese gerne mal test-mässig umsetzen. Ich möchte ein Mechanismus programmieren, mit dem ich in den freien Flash-Speicher meines Mikrocontrollers Programme nachladen / "nachflashen" kann. Ich denke mir das folgendermassen : Ich habe ein Grundstock an Systemfunktionen in einem Speicherbereich A liegen. Variablen (RAM) liegen ebenfalls in einem fest definierten Speicherbereich. Nun möchte ich in einem Speicherbereich B Programm-Code ablegen und von meinem Grundsystem aus starten. Speichermässig würde das ganze so aussehen (RAM wie Flash) : |---------------- .. ------ .. ----------------- .. ---------| | A | .. | AX | .. | B | .. | BX | |---------------- .. ------ .. ----------------- .. ---------| AX bzw. BX sollen Bereiche sein, die für den Austausch von Daten/Adressem von Funktionen zuständig sind. RAM mässig müsste es genauso aussehen (also 4 Bereiche). Nun müsste man einiges an restriktionen machen (z.b. Feste Startadresse der Bereiche (RAM/Flash), damit das Programm B immer auf gültige Daten zugreift, vor allem für A müssen diese Bereiche immer fest sein). Wenn der RAM Bereich für beide Programm-Teile getrennt definiert ist, müsste es eigentlich doch auch keine probleme mit dem Stack geben (da ja beide programme, wegen getrennter speicherbereiche, einen eigenen Stack haben). Ich hab mir das ganze so vorgestellt das ich mit einem Grundsystem mehrere Applikationen (von mir aus von SD/MMC) "laden" und ausführen kann. Meine Frage ist nun : Würde das so funktionieren ? Wie würde ich ein Interface schreiben mit dem ich im Programm B ernittele WO meine Funktionen von A liegen, welche ich nutzen möchte ? Was muß ich bei der Initialisierung beachten (außer das ich mir den Reset-Vektor nicht plattbügel ...) ? Kann ich den Startup-Code von B so einfach aufrufen ? Ich habe bewusst keinen Prozessor-Typ genannt (ich verwende einen MSP430), da ich das ganze universell definieren möchte, da man dieses Prinzip (wenn es denn so funktioniert) auf alle Controller anwenden könnte welche in der Lage sind ihren eigenen Programm-Speicher zu flashen. Bin mal gespannt auf eure Kommentare und Vorschläge ... Gruß Rene
Du suchst nach einem 'Bootloader' Viele AVR-Typen unterstützen so was. Siehe zb. http://www.mikrocontroller.net/articles/Bootloader http://www.mikrocontroller.net/forum/read-4-53146.html
in dem sinne ist "bootloader" richtig, aber eben nicht nur auf den boot vorgang beschriänkt, sondern während des laufenenden betriebs sagen kann : lade mir nun die andere applikation. außderdem sollen ja die funktionen von meinem System A mit genutzt werden können, ohne das diese extra in B nochmal definiert werden müssen. quasi ein "dll"-mechanismus für mikrocontroller und weniger einen bootloader.
Hallo, habe auch schon an soetwas gedacht, ich benötige diese sache um einen font nachträglich auf eine grafiksteuerung zu laden ohne das eigentliche Programm auf dem Controller erneut zu flaschen. also eine funktion die verweise auf speicherbereiche aktiviert und den font an der stelle ablegt, so das man ihn sozusagen selbst entwickeln kann, ohne ahnung vom controller haben zu müssen. ein bootloader funktioniert ja im grunde genaus so, es wäre dann ein fontloader. maddin
@maddin, also daten nachzuladen ist denke ich ist nicht das problem. ich habe eher bedenken wenn es um die ausführung eines nachgeladenen programms geht. Wie kann ich denn denn von A aus den startup-code von B aufrufen und nachher wieder zu A zurückzukehren. Unmittelbar nach dem Startup Code wird ja die int main (void) aufgerufen. wenn die main von B ausgeführt wird kann ich dann sicher sein das mir der Prozessor zu meinem aufrufpunkt (der ja in A liegt) wieder zurückkehrt ? gruß rene
> wenn die main von B ausgeführt wird kann ich dann sicher > sein das mir der Prozessor zu meinem aufrufpunkt (der ja in A liegt) > wieder zurückkehrt ? Darauf würde ich nicht bauen. AFAIK fügt zb. der AVR-gcc in seine Startup-Sequenz nach dem Return von main() eine Endlosschleife ein. Wenn main() tatsächlich zurückkommt, muss ja normalerweise irgendwas geschehen und wenn es nur eine Endlosschleife ist. Ich denke das du so nicht weiterkommen wirst. In C ist ein Programm eine abgeschlossene Einheit und was ausserhalb dieser Einheit liegt ist alles undefiniert.
und wenn ich nun hingehen würde und meinen eigenen startup-code (der ja nichts weiter als die initialisierung der variablen machen muß) in einer funktion des programms B lege um dann zu gewährleisten dass nach aufruf der initialisierung mein programm a wieder zum zuge kommt ? ich denke mir das es doch irgendwie möglich sein muß, zumal wenn ich getrennte speicherbereiche (für stack/heap/variablen bezgen auf ram, und code/const bezogen auf flash) pro programm habe ? scheitert das ganze nur am startup-code ? gruß rene
Wie wär es den,den Startup-Code,den Loader und den Einsprung in die Hauptanwendung als dein Programm zu laden?Dann könnte man z.B nach einem Reset eine Anfrage für ein neues Programm an eine serielle Schnittstelle schicken.Wenn innerhalb von z.B. 100ms eine Antwort kommt lädt der Loader das Programm von der Schnittstelle,andernfalls springt er in das vorhandene Programm (was dann natürlich auch irgendwann mal vom Loader geladen wurden sein musste). Das main()-problem ist dagegen nicht so einfach zu lösen.Wenn man kein stdio und co verwendet kann man VIELLEICHT auf das C-Startup Zeug verzichten.Dann würde es reichen die definierten Funktionen und Daten zu übernehmen.Aber eine Garantie das man nicht irgendwas vom Compiler generiertes ausversehen weglässt hat man dann nie. Alternativ könnte man die main() vielleicht in Assembler schreiben und eine in C programmierte Lib mit der eigentlichen Anwendung dazulinken.Die Lib wär dann nur eine Ansammlung von Funktionen und Daten ohne main() die dann als extern definiert sein muss.
Was Du suchst ist ein "Loader" mit "Relocation". Vielleicht noch ein "Operating System" als Suchbegriff dazu und Du solltest fündig werden (Theorie, keine fertigen Code-Schnipsel). Da Dein Linker Dir die Codestücke nur für einen bestimmten Speicherbereich erstellen kann, musst Du durch eine "Relocation" beim Laden Deines Codes alle absoluten Sprünge im Code und alle absoluten RAM-Adressen so verschieben, dass sie in ihrem zugewiesenen Speicherbereich bleiben. Da alles notwendige, aber nichs falsches anzufassen, ist ohne Zusatzinformationen fast unmöglich. Solche Informationen kann man aber vielleicht aus dem Linker herauskitzeln.
Naja,man kann mit den richtigen Linkereinstellungen schon dafür sorgen,das alle Funktionen und Variablen in den richtigen Adressbereichen liegen.Da braucht man dann auch nix mehr von Hand oder mit irgendwelchen Tools zu sortieren. Und wenn man einmal (ohne ein Betriebssystem was das für einen übernimmt) mit relozieren anfängt,wird es recht schnell sehr ungemütlich wenn´s an die Fehlersuche geht.
Grundsätzlich sehe ich keine Probleme mit deinem Ansatz. Dein Programm A ist quasi ein Betriebssystem und die Programme B1...Bx sind die Anwenderprogramme. Generationen von Programmierern haben sich überlegt, wie man ein Betriebsystem implementiert und wie man die Hooks (Betriebssystemfunktionen) sinnvoll ablegt. Oft wird eine Sprungtabelle am Programmanfang benutzt. Das sollte nachlesbar sein. Technisch am anspruchvollsten finde ich die Nachflasherei, weil du dabei an dem Baum Äste ummodelst, auf denen du sprichwörtlich mit deinem Betriebssystem sitzt. Ich habe schon Datenblätter von Flash-Bausteinen gelesen, bei denen eine Sektorierung des Flash beschrieben war. Gewisse Sektoren konnte man dort gegen überschreiben sichern (nützlich fürs Betriebssystem), wenn man andere neu beschrieben hat. Allerdings durfte dort in der Zeit des Neubeschreibens nicht lesend auf das restliche Flash zugegriffen werden, d.h. die eigentliche Flash-Rewrite-Routine musste zuvor ins SRAM verlagert werden und von dort aus gestartet werden.
> Naja,man kann mit den richtigen Linkereinstellungen schon dafür > sorgen,das alle Funktionen und Variablen in den richtigen > Adressbereichen liegen. Nur, wenn Du jeweils nur ein Programm zu einer Zeit an einer Stelle laufen lässt. Das könnte hier vielleicht sogar so sein. "mehrere Applikationen (von mir aus von SD/MMC) 'laden' und ausführen" - halt nur nie gleichzeitig.
Jap,dann läuft immer nur ein Programm.Welches würde dann beim Reset (oder einem vom Loader überwachten Event) entschieden werden.Der quasi fliegende Wechsel ("Multitasking") ist dann natürlich nicht möglich.Wenn genug Platz im Flash ist,kann man natürlich mehrere Bereiche für Anwendersoftware definieren,aber dann wird es wieder ´ne ganze Ecke komplizierter (Stichwort Task switchin,Task Context sichern usw),von erhöhten RAM bedarf und Rechenleistung mal ganz abgesehen. Den Bootloader ins RAM zu kopieren ist die meist verwendete Variante. Theoretisch könnte man auch externen Flash für die Anwendung(en) anknüpfen und den Loader ins interne Flash packen.
@all hups .. jetzt habe ich die ganze diskussion verpasst :-( @m789 mit dem relokatiblen code ist insofern egal, als das ich dem linker einfach nur sage das das programm in einem bereich gebracht wird der nicht vom betriebssystem benutzt wird. und ich hatte kein multitasking vor :-) und wenn dann nur kooperatives @ronny ich hatte mir gedacht das ich über einen geeigneten mechanismus die funktionen des programms A dem programm B zur verfügung stelle und umgekehrt (deswegen auch die bereiche AX und BX, jeweils für RAM und Flash) @stefan also bei meinem "betriebssystem" was quasi mein programm A ist weiß ich einfach in welchem speicherbereich es steht (linkerfile). und wenn dann sollte eh nur ein einziges programm nachgeladen werden. mit der sprungtabelle hatte ich mir auch überlegt (wie gesagt speicherbereich AX und BX) mal was behind the scenes : mir ist die idee gekommen weil ich an einem "mini-betriebssystem" (funktionsansammlung welche prozesse, software-timer, fifos, message queues, devices und später auch statemachines und einen parser bietet) programmiere welches mit relativ wenig aufwand auf mehrere prozessoren portierbar und vor allem wiederverwendbar ist. weiterhin ist dieses system in weiten grenzen konfigurierbar und ist als kooperatives betriebssystem ausgelegt. evtl. werd ich hier mal vor-/ reinstellen ... der gedanke mit dem "nachflashen" ist mir gekommen um z.b. benchmark-programme/profiling-programme oder software updates für applikationen laufen zu lassen die man von sd-karte laden kann. ausgangsformat wäre dann ein hex-file (da kann man dann auch gucken ob das programm in dem richtigen speicherbereich liegt). das man die betriebssystem funktionen dabei nutzen kann (muß) ist schon fast "zwangsläufig". das einzige was ich noch rausfinden muß ist, wie man am besten so ein interface (datenaustausch der programme) aufbaut, und was der startup-code schlimmstenfalls machen kann (sprich : was der außer initialisierung der variablen noch machen kann, was ich nachbilden muß) für vorschläge immer offen ... gruß rene
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.