Hallo, Mein Ziel ist folgendes: Ich will mit einem MSP430 (auf eine genaue Version habe ich mich noch nicht festgelegt, aber ich habe schon ein Auge auf den MSP430F5529 geworfen) Programme von einer SD-Karte ausführen. Diese Programme (Programmiersprache: C) verwenden Methoden, die auch im Flash vorhanden sind. (Die Programme selbst sind noch nicht geschrieben, sind also auch vollkommen anpassungsfähig.) Ich habe dann ja drei Möglichkeiten, diese Programme auszuführen: 1. Ich lade sie in den Flash. Vorteil: Kein wirliches Problem mit eventuell zu kleinem Speicher. Nachteil: Flash immer wieder zu programmieren und zu löschen macht ihn mit der Zeit kaputt. 2. Ich lade sie in den RAM. Vorteil: RAM nutzt sich nicht ab. Nachteil: RAM ist lange nicht so groß wie der Flash. 3. Ich lade sie in den RAM und springe bei Methoden, die auch im Flash vorhanden sind, zum Flash. Vorteil: Nicht so hoher Speicherverbrauch wie bei 2. Nachteil: Komplizierter zu programmieren und immernoch, wenn auch kleines, Problem mit dem Speicher. Ich selbst tendiere zu Version 3, aber da sich die Adresse der Funktionen (und wohl auch die Register, in denen Parameter und Rückgabewert gespeichert werden) von Version zu Version verändern können und die Programme von der SD-Karte nicht immer wieder neu kompiliert werden sollen, müssen die Adressen der Funktionen auch noch an einer festgelegten Position im Flash gespeichert werden usw. usf. Hat jemand eine Idee (grobes Schema), wie man Version 3 ohne große Prozessor- und Speicherbelastung umsetzen könnte? Ich hoffe, dass ihr mir helfen könnt und danke ich euch schon mal im Voraus. Sollte ich wichtige Daten vergessen haben, werde ich mich bemühen, diese schnellstmöglich nachzureichen. Mit freundlichen Grüßen
Was hältst du von einem Bootloader ? Nur dass ich dich richtig verstehe. Du willst einen Compiler auf deinen µC drauftun, der dir den C Code von der SD Karte kompiliert und dann ausführt ??? Schonmal einen Compiler geschrieben ?
Nein, die Programme sollen nicht auf dem MSP430 kompiliert werden, nur ausgeführt. Was ich gemeint habe, ist folgendes: Wenn ich ein Programm aus dem RAM ausführe und die Methoden im Flash vom RAM aus aufrufe, muss ich ja die Adressen zu den Methoden wissen. Da diese Adressen sich aber von Version zu Version der Software im Flash ändern können, müssten die Programme ja neu (auf einem Computer) kompiliert (und die Adressen natürlich angepasst) werden. Dies ist nicht gerade das, was ich mir vorstelle, deshalb müssen die Adressen der Methoden an einer gewissen Stelle gespeichert werden, die sich nie ändert. Ich habe jetzt leider nicht viel Zeit, werde das aber in den nächsten 2 Stunden mit einem Beispiel verdeutlichen. Mit freundlichen Grüßen
Ein sportliches Unterfangen, aber wenn man erstmal die grundsätzlichen Methoden und Konzepte fertig hat ist das denke ich ein gangbarer Weg. Ein paar Gedanken: Irgendwie muss ein Weg gefunden werden, speziell im SD-Flash platzierte Funktionen mit einem speziellen Epilog/Prolog (Prolog liegt im MSP-Flash, Epilog im SD-Flash) zu versehen, um die gewünschte Funktion in den RAM zu kopieren und wieder freizugeben. Den Umweg über das interne Flash halte ich für unnötig, ich würde ein MSP430-Derivat mit 16K RAM nehmen - so große Funktionen hat man nie, bzw. sollte man nicht haben. Diese Epi/Pro-Geschichte sollte automatisch arbeiten, soll heissen, dass man die Funktionen die im SD-Flash landen sollen mit einem Attribut versieht was den Compiler/Linker automatisch dazu zwingt den Code zu laden (mithilfe selbstgeschriebener Funktionen). Ich würde es in jedem Fall versuchen zu vermeiden, dass man solche Konstrukte braucht:
1 | // Pseudo-Code. |
2 | |
3 | loadSDCodeToAddress( &someFunctionInSDFlash, 0x1234 ); |
4 | executeRAMCode( 0x1234 ); |
Was, wenn man someFuntionInSDFlash nicht mehr im SD-Flash haben will, sondern im MSP-Flash? Code umstricken wäre dann angesagt. Statt dessen:
1 | #pragma location="SDFlash" |
2 | #pragma myProlog |
3 | void someFunctionInSDFlash(void){ //... } |
4 | |
5 | void main(void) |
6 | { |
7 | // Just call. |
8 | someFunctionInSDFlash(); |
9 | } |
Jetzt muss man sich noch Gedanken machen, wie man zwei getrennte Binaries bekommt, die aber voneinander wissen (z.B. Adressen im SD-Flash). Abschließende Frage: Soll das unabhängig voneinander funktionieren? Beispiel: auf dem MSP läuft immer der selbe Code, nur der SD-Inhalt wird zwischenzeitlich geändert? Dann wird es einerseits einfacher, dafür unflexibler (es sei denn, man scheut sich nicht vor sehr großem Aufwand) - und die Hälfte meines Gesabbels hätte ich mir sparen können. :) Nettes Projekt!
Ich habe die Befürchtung, dass ich missverstanden werde, trotzdem danke ich euch beiden ganz herzlich für eure Beiträge. Ich werde versuchen, es nochmal klarer zu fassen: Ich habe auf der SD-Karte ein (noch nicht geschriebenes) Programm gespeichert. Dieses Programm soll in den RAM des MSPs geladen und dort ausgeführt werden. Dieses Programm auf der SD-Karte verwendet eine Funktion namens "do_something()". Eigentlich kein Problem, schließlich kann ich ja einfach diese Funktion wie jede andere auch in den RAM laden. Jetzt ist aber eben "do_something()" auch im MSP-Flash vorhanden. Konkret habe ich es mit so vorgestellt: Im MSP-Flash befindet sich die Methode "void do_something(void)". Diese fängt bei 0x1A30 an. In dem (natürlich kompilierten) Programm auf der SD-Karte steht also folgendes:
1 | #include "example.h" |
2 | ...
|
3 | do_something() |
4 | ...
|
In "example.h" steht das:
1 | #define do_something() asm("CALL #0x1A30"); //Direkter Sprung zu 0x1A30
|
Wird dieses Programm dann von der SD-Karte in den RAM geladen und ausgeführt, wird bei do_something() nach 0x1A30 gesprungen und "do_something" ausgeführt. Das, oder zumindest so etwas in der Art sollte doch funktionieren, oder nicht? Das Problem: Ändert sich in der nächsten Version der Software im MSP-Flash die Adresse von "do_something()", muss das Programm von der SD-Karte (auf einem Computer) neu kompiliert werden, nachdem in "example.h" die Adresse für "do_something()" angepasst wurde. Um das zu vermeiden kann man ja auch folgendes machen: Wieder die Methode "void do_something(void)" bei 0x1A30, diesmal ist aber zusätzlich an Adresse 0xFF00 die Adresse von do_something(), also 0x1A30, gespeichert. Also steht in der Zelle 0xFF00 und 0xFF01 die Adresse 0x1A30. In "example.h" steht also folgendes:
1 | #define do_something() asm("CALL 0xFF00"); //Sprung zu der Adresse, die bei 0xFF00 gespeichert ist
|
Wird das Programm jetzt ausgeführt, wird also an die Adresse, die bei 0xFF00 gespeichert ist, gesprungen. Wird jetzt die Software im Flash geändert, und sich die Adresse für "do_something()" ändert, wird die neue Adresse einfach nach 0xFF00 geschrieben und das Programm funktioniert auch ohne Anpassung noch. Frage Nr. 1: Würde das so funktionieren? Frage Nr. 2: Wie sollte man das Rückgabewerten und Parameter machen? Mit freundlichen Grüßen
Ich habe dich schon verstanden. Genau solche Konstrukte würde ich vermeiden, ich hatte ein Beispiel gegeben (zugegeben, für die andere Richtung - aber das Beispiel war allgemeingültig gemeint). Wieso sollte der Funktionsaufruf nicht elegant vom Linker/Compiler gehandhabt werden? Deine Idee mit der Sprungtabelle sollte gehen, verbraucht aber Speicher und ist relativ unflexibel bzw. arbeitsintensiv. Auch hier kann der Linker aber das Auffüllen der Adressen zur Compilezeit durchführen. Ich befürchte trotzdem ein heilloses Durcheinander.
>Ich habe dich schon verstanden.
Dann habe ich dich falsch verstanden. ;-)
Danke nochmals für deine Hilfe, ich habe dich jetzt auch verstanden.
Mit freundlichen Grüßen
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.