Hallo, ich habe folgendes Problem. Ich setze hier einen MPC555 PowerPC ein. An diesem sind 8MB Flash extern angebunden, sowie 1MB RAM. Die Applikation, die ausgeführt werden soll, wird beim Booten teilweise ins RAM kopiert, da dort die Ausführung schneller ist (z.B. irgendwelche digitalen Regler usw.). Der TCP-Stack hingegen und ein paar andere Teile, die nicht so kritisch sind, laufen aus diesem externen Flash. Ich soll jetzt eine Software implementieren, die das Laden einer neuen Software via Browser & TCP/IP ermöglicht. Das klappt auch ganz gut; in der Applikation ist ein kleiner Webserver integriert, der mittels HTML-Formular eine Datei hochladen und im Flash speichern kann. Nun habe ich mir zum Updaten der Software folgendes ausgedacht. Man teilt den Flash-Speicher in zwei Teile (Applikation ist < 4MB gross, passt also) und überschreibt beim Softwareupdate dann die jeweils ältere Version. Ein kleiner Bootloader, der im internen Flash des PowerPC sitzt, schaut beim Booten dann nach, welche Version neuer ist, und startet dementsprechend diese. Das Problem an der ganzen Sache ist jetzt aber: diejenigen Codeteile, die aus dem Flash ausgeführt werden, müssen Position-independent sein, da ich zur Compilierzeit ja nicht weiss, von wo aus mein Code ausgeführt wird. Diejenigen Teile hingegen, die aus dem RAM laufen, sollen so bleiben, wie sie sind. Die Frage, die sich mir jetzt natürlich stellt: Ist so ein Setup grundsätzlich überhaupt möglich? Kann ich Teile der Applikation so kompilieren lassen, dass ich sie irgendwo ins Flash speichern kann, und die Ausführung dann trotzdem klappt? Zumindest die Hardwareregister und das externe RAM müssen ja dann doch wieder absolut adressiert werden. Und falls einer den Diab PowerPC Compiler kennt und mir ein wenig Hilfestellung geben könnte, wär das auch toll ;-)
Hallo, da es sich um Programmierung handelt bist du eigentlich im falschen Forum!?
Danke für deinen nicht sehr hilfreichen Beitrag. 1. handelt es sich um Mikrocontroller & Elektronik. Passt also. 2. Da ich nicht den GCC verwende, gehört es nicht ins GCC Forum. 3. Kein Fertiger Code, keine PC-Software, mit Ausbildung, Offtopic, HF & Funk & Feldern usw. hat es auch nichts zu tun, erst recht mache ich keine Leiterplatte, also gehört der Thread da auch nicht rein.
Wieso lässt Du Deinen Bootloader nicht einfach den "hinteren" Teil des Flash Speichers auf den "vorderen" kopieren?
Tobias Plüss schrieb: > Die Frage, die sich mir jetzt natürlich stellt: Ist so ein Setup > grundsätzlich überhaupt möglich? Antorten zu möglichen Memory-Modellen und "positionsunabhängigem" Code sollten eigentlich in der Dokumentation zu deinem Compiler bzw. Entwicklungssystem zu finden sein. Oliver
Jim Meba, das Kopieren wollte ich wenn möglich vermeiden. Wenn jemand in dem Moment, wo kopiert wird, den Netzstecker zieht, oder sonst was schief geht, dann ist die zuvor lauffähige Applikation zerschossen und der Benutzer hat ein Problem. Mit dem PIC-Code hätte ich immer noch als "Backup" die jeweils ältere Version der Software bereits im Memory. Oliver, ja natürlich, ich habe das Compilermanual gelesen. Aber leider hat der dort angegebene Compilerswitch nicht funktioniert; der Compiler bringt Fehlermeldungen. Dazu gibts wohl 2 Gründe: 1. Woher soll der Compiler wissen, dass gewisse Teile der Applikation zur Ausführung ins RAM kopiert werden und somit an einer festen Adresse liegen, im Gegensatz zum Flash-Code, der irgendwo liegen kann? 2. Der Compiler kann scheinbar Sprungtabellen, die irgendwelche Funktionspointer enthalten, nicht Position Independent compilieren. Aber das kann doch nicht sein? Wozu soll eine PIC-Option da sein, wenn sie keine Funktionspointer compilieren kann? Ich blicke da nicht so ganz durch. Leider ist unser Compiler hier von 1999, und der Support schon längst abgelaufen. Sonst hätte ich da längst ne Mail hin geschickt ;-)
Tobias Plüss schrieb: > 2. Der Compiler kann scheinbar Sprungtabellen, die irgendwelche > Funktionspointer enthalten, nicht Position Independent compilieren. Aber > das kann doch nicht sein? Wozu soll eine PIC-Option da sein, wenn sie > keine Funktionspointer compilieren kann? Ich blicke da nicht so ganz > durch. Logisch dass das nicht geht. Normalerweise (!PIC) würde der Linker schon zur Compile-Time die Funktionstabellen (mit Konstanten) füllen. Bei PIC-Code stehen diese aber noch nicht fest. d.H. beim Laden/verschieben des Codes müssten alle Funktionspointer verändert werden. Kein Problem, dafür gibts "dynamische Linker". http://en.wikipedia.org/wiki/Dynamic_linker http://en.wikipedia.org/wiki/Dynamic_loading Diese gibts natürlich auch für PowerPC, aber halt üblich im Betriebsystem-Kontext. (linux, ld.so, elf-dateien)
Naja, so logisch finde ich das jetzt nicht :-) Wenn ich in den Funktionstabellen anstatt der absoluten Adresse jeder Funktion nur deren Offset speichere, dann ist doch alles in Ordnung. Dann muss ich zur Startadresse meines Programms nur noch diesen Offset dazu addieren, dann ist mir jede Funktion bekannt. Es gab meines Wissens für 68k Prozessoren mal ein Betriebssystem, wo sämtlicher Code vollständig position independent war und alles von einer nahezu beliebigen Adresse her ausgeführt werden konnte. Leider weiss ich nicht genau, wie das gemacht wurde. Ein ELF-Loader wird hier nicht funktionieren, da das ELF-File ja ungünstigerweise im Flash liegt und nur bestimmte Teile aus dem RAM laufen, während andere Teile weiter im Flash bleiben sollen :-/
Tobias Plüss schrieb: > ungünstigerweise im Flash liegt und nur bestimmte Teile aus dem RAM > laufen, während andere Teile weiter im Flash bleiben sollen :-/ Damit beschreibst du genau, warum deine Idee (Relative statt Absolute Funktionspointer) nicht funktioniert. Weil: Du brauchst ja beide Arten (absolute Pointer in den Flash, relative für PIC code) Welcher Typ wo gebraucht wird, kann der Compiler nicht wissen, da Funktionspointer evtl. erst zur Laufzeit gesetzt und geändert werden. Also muss der Programmierer ran, und das dem Compiler mitteilen. Leider bietet C nur einen Pointer-Typ an, d.H. mit Plain-C geht das nicht. Also: Assembler muss ran. Damit geht auch sowas: Tobias Plüss schrieb: > Es gab meines Wissens für 68k Prozessoren mal ein Betriebssystem, wo > sämtlicher Code vollständig position independent war Mit viel Fleiß lasst sich ein relativer Funktions-Pointer vielleicht als C++-Template-Klasse mit inline-ASM machen, aber auch da habe ich meine Zweifel. Überleg mal, welchen Aufwand alleine die Umsetzung dieses Pseudo-Code-Schnippsels machen würde:
1 | relative_function_ptr_t a; |
2 | relative_function_ptr_t b; |
3 | |
4 | // Bedenke, a enthält den Offset zwischen der Funktion und der eigenen Speicherstelle, der muss berechnet werden.
|
5 | a=calculate_function_offset_relative(fun_a, &a); |
6 | |
7 | // Bedenke: b liegt an einer anderen Speicherstelle als a, die Zuweisung muss den Wert verändern!
|
8 | // d.H. diese Zuweisung muss anderen Code ausführen als die obere.
|
9 | b=a; |
Ich habe aus einem früheren Jahrhundert vage in Erinnerung, dass AIX Adresstabellen verwendet, d.h. ein Register zeigt stets auf die Adresstabelle des aktuellen Moduls. Weil die PowerPCs in den Befehlen weder den ganzen Adressraum erfassen, noch wie ARMs auf einfache Art relativ zum Program Counter adressieren können (ausser in Sprungbefehlen). Auf dem Weg lässt sich positionsunabhängiger Code erzeugen, indem diese Adresstabellen nicht fester Bestandteil vom Program-Image sind, sondern vom Loader erzeugt werden. Das kommt sicherlich auch den (nicht nur) in Unix recht verbreiteten shared libraries entgegen.
Hmm, okay, dann geht das dann wohl doch nicht, so wie ich mir das vorstelle? Ich bin grade noch am Überlegen, ob ich eventuell mit dem Memory Controller des MPC555 gewisse Bereiche vom Flash ummappen kann. Konkret stelle ich mir das so vor: Das Flash beginnt ab Adresse 0x2000000. Die Applikation wird auch für diese Adresse kompiliert (kein PIC-Code). Wenn ich eine neue Software runter lade, dann wird diese an Adresse 0x2400000 gespeichert. Und nun "verbiege" ich mit dem Memory Controller den Adressbereich des Flash so, dass die Adresse 0x2400000 und 0x2000000 "getauscht" werden. Geht sowas wohl? Kennt hier jemand diesen Prozessor? Ich muss zugeben, dass ich von der MPC555 Hardware nicht sehr viel Ahnung habe. Es ist ein schrecklicher Prozessor und ich befasse mich möglichst nicht mit Hardwareabhängigkeiten, aber jetzt komme ich wohl nicht drum herum ;-)
Du wirst vor allem nicht darum herumkommen, überhaupt erst einmal festzustellen, wie der Compiler mit Adressen umgeht. Wenn er sie als Literals in 2 Befehlen zusammen baut hast du verloren. Wenn er Tabellen verwendet, stehen die Chancen besser.
A.K., ja das mit dem PIC und PID propagieren sie, dass der Compiler das kann. Wenn ich compiliere, kommt aber Fehler Nr. 1061: "Address taken in initializer". Im Handbuch steht zu diesem Fehler: "You used the Address of a Variable or Function in a variable's initializer. For such code, PIC/PID does not work." Meines erachtens sollte man das aber können, wenn ich keine Pointer benutzen kann, dann ist es ja sinnfrei, eine PIC-option überhaupt anzubieten :o
Tobias Plüss schrieb: > "Address taken in initializer". Nun kommen wir der Sache schon näher. Du kannst durchaus Pointer verwenden, aber nicht als statisch initialisierte Variablen. Was also nicht geht: static int x; static int *px = &x; oder analog mit Zeigern auf Funktionen. Das Problem dürfte verschwinden, wenn diese Variablen zur Laufzeit initialisiert werden.
Eventuell ist es einfacher, den Code für die beiden möglichen Positionen zu übersetzen und in ein File zusammenzupacken. Der Bootloader entscheidet dann, welchen Teil er zum Flashen verwendet und ignoriert den Rest. Jörg
Naja, ich sehe das Problem nicht. Dieser Code wird dann ja eh ins RAM kopiert und läuft von einer festen Adresse aus :-) Wirklich nur der Code, der die Applikation ins RAM kopiert sowie der TCP/IP Stack und das User Interface müssen Position Independent sein, denn nur diese werden aus dem Flash, und somit von unterschiedlichen Adressen aus, ausgeführt. Leider bietet der Compiler keine Option an, um nur einzelne Dateien Position Independent zu compilieren; entweder kann ich nur das ganze Projekt oder nichts, jedenfalls so wie ich das jetzt verstehe. Lustigerweise unterstützt der Compiler aber Features wie vorhergehendes ins-RAM-Kopieren von Code und implementiert das richtig. :-/
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.