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:
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