Hallo, bisher hatte ich mit einer Testversion von Rowley gearbeitet, um Code für meine NXP LPC2000 Mikrocontroller zu erstellen. Rowley funktionierte einigermassen, was mich störte war der Debugger, der nicht wirklich toll ist. Nun ja, wie auch immer. Ich habe da mühsam meinen eigenen Startup-Code zusammen gestellt, da ich einige spezielle Dinge im Startup noch erledigen will, bevor main() beginnt. So, also meinen Startupcode habe ich. Nun bin ich nicht zufrieden mit Rowley und habe mir mal eine Testversion vom Keil MDK besorgt. Das sieht schon besser aus, vor allem der Debugger! Aber leider kann ich da meinen Rowley-Startupcode nicht benutzen. Meine Frage hierzu ist: - wo kann ich beim Keil definieren, wo der Stack liegt? - wo bzw. wie wird beim Keil Startup-Code das RAM initialisiert? beim Rowley gabs da die .bss-Section, welche mit Nullen gefüllt werden musste; beim Keil Startup ist nichts derartiges vorhanden. Auch eine memory-Copy Funktion gibt es nicht, die initialisierte Variablen ins RAM kopiert. Frage: wie wird das bei Keil denn gelöst? Ich hoffe ihr könnt mir weiterhelfen, vielen Dank schon mal.
Bei der Keil-IDE sind Beispiel-Projekte für einige Boards dabei, auch für NXP. Dort solltest Du fündig werden. Bei meinem Luminary-Projekt heisst das File "Startup.s".
Hi Hugo, das Problem ist aber, dass ich auch bei den Beispielprojekten noch nicht wirklich ganz durch blicke, wie und wo der Stack definiert wird. Wie sage ich dem Compiler z.B., dass er den Stack bitteschön an Adresse 0x40002000 machen soll und dass der Stack 1k gross ist? Und dann der Heap: wo lege ich den fest? Ausserdem: wie wird das bei Keil gehandhabt mit nicht initialisierten Variablen (die ja dann im BSS liegen und mit 0 überschrieben werden)? Und müssen bei initialisierten Variablen nicht noch die Initialisierungswerte vom ROM ins RAM kopiert werden? Ich finde den Part nicht, der das erledigt! :-(
>- wo kann ich beim Keil definieren, wo der Stack liegt? >- wo bzw. wie wird beim Keil Startup-Code das RAM initialisiert? Also solche Dinge solltest Du nun wirklich dem Compiler überlassen und nicht selber was damit herumwursteln...!!!!!
> Also solche Dinge solltest Du nun wirklich dem Compiler überlassen und > nicht selber was damit herumwursteln...!!!!! Nöö, ich will selber festlegen können, wo der Stack liegt. Da ich ihn z.B. gerne ins externe SRAM legen würde. Das ist grösser. Ausserdem: wenn der Compiler den Stack selber bestimmt, dann macht er ihn irgendwie 400 Bytes gross oder so. Das ist doch Murks! Wenn ich schon 1 MByte RAM zur Verfügung habe, soll er das gefälligst auch gescheit nutzen. Dasselbe gilt natürlich für den Heap. Da ich mittels selber geschriebenem Memory Manager dynamischen Speicher alloziiere, brauche ich auch einen ordentlichen Heap. Mit diesen Standard-Dingern, die ein paar 100 Bytes gross sind, kann ja keiner was anfangen!
Vom Nutzer wird eine Funktion __user_initial_stackheap bereitgestellt. Diese wird von __main (einer library Funktion) aufgerufen und setzt R0-R4 auf die Adressen für head und stack. __main kümmmert sich auch um data-copy, bss-init und ruft schliesslich main. Im eigenen startup ruft man __main (ARM library-code) statt main (eigenem C-Code). (Ist aber nichts, was nicht auch in der Dokumentation beschrieben wäre).
Jürgen G. schrieb: > Da ich ihn z.B. gerne ins externe SRAM legen würde. Das ist > grösser. Ausserdem: wenn der Compiler den Stack selber bestimmt, > dann macht er ihn irgendwie 400 Bytes gross oder so. Das ist doch > Murks! Wenn ich schon 1 MByte RAM zur Verfügung habe, soll er das > gefälligst auch gescheit nutzen. Denk daran, dass auf den Stack sehr häufig zugegriffen wird. Ich würde wahrscheinlich eher das ganze interne RAM für den Stack reservieren, bevor ich auf externen Speicher ausweiche. Vorausgesetzt natürlich Dein Stack passt überhaupt in den internen Speicher. Bei einer CPU ohne Cache würde ich mir jedenfalls sehr genau überlegen, wo bestimmte Bereiche im Speicher angelegt werden. Womit wir wieder bei der eigentlichen Frage wären: Keil verwendet ein etwas umständliches Verfahren, um Stack und Heap zu definieren. Letztlich sind das Konstanten im Startup.s, die aber über den "Configuration Wizard" dieser Datei einfach konfiguriert werden können. Keil nutzt hier leider nicht die Möglichkeit, das über spezielle Linker Regionen (ARM_LIB_STACK, ARM_LIB_HEAP) im Scatter file zu definieren. RealView Tools seit Version 3.0 unterstützen das. Das hat man halt davon wenn man IDEs verwendet :-) Gruß Marcus http://www.doulos.com/arm
Hi, danke für eure Posts, Martin und Marcus. @Martin: Wo finde ich das mit dem __main? Ich habe sehr wohl in der Onlinehilfe gesucht, aber vielleicht nicht nach dem richtigen Begriff. Kann man sich irgendwo anschauen, was die Funktion __main denn macht? Ich will meinen eigenen Startupcode benutzen, nicht irgend einen anderen der beim Keil dabei ist. Bei Crossworks ging das, dort konnte man alle Dinge, die eigentlich Fest im Projekt eingestellt wurden, trotzdem irgendwie aushebeln und selber schreiben. Und genau DAS will ich machen! Ein Argument, was sehr für Rowley spricht. Der Debugger da ist einfach schlecht und funktioniert nicht zufrieden stellend mit dem J-Link zusammen. Kann ich beim Keil auch irgendwie selber einen Startup-Code integrieren? bzw. dieses __main durch mein eigenes ersetzen.
Jürgen G. schrieb: > Wo finde ich das mit dem __main? Ich habe sehr wohl in der Onlinehilfe > gesucht, aber vielleicht nicht nach dem richtigen Begriff. Ähh, __main im Suchfenster eingegeben? ;-) http://infocenter.arm.com/help/topic/com.arm.doc.dui0203i/index.html Hilfreich ist auch das hier http://infocenter.arm.com/help/topic/com.arm.doc.dui0349b/index.html Diese Links beyiehen sich genaugenommen auf die "große" ARM tool chain (RVDS), die Compiler Tools sind aber weitestgehend identisch. Die entsprechende Keil Doku findest Du etwas weiter unten. Die ist aber je nach verwendeter MDK Version nicht ganz aktuell. Außerdem gibt's bei Keil den Developer Guide nicht, in dem das alles erklärt wird. > Kann man sich irgendwo anschauen, was die Funktion __main denn macht? > Ich will meinen eigenen Startupcode benutzen, nicht irgend einen anderen > der beim Keil dabei ist. Warum? Was ist an Deinem Projekt so speziell? Was genau meinst Du eigentlich mit Startup code -- den von Keil implementierten Reset Handler, oder das C library startup? > Bei Crossworks ging das, dort konnte man alle Dinge, die eigentlich > Fest im Projekt eingestellt wurden, trotzdem irgendwie aushebeln und > selber schreiben. Und genau DAS will ich machen! Normalerweise endet der Reset Handler in einem Sprung nach __main. Du kannst stattdessen einfach eine andere Funktion aufrufen. > Kann ich beim Keil auch irgendwie selber einen Startup-Code integrieren? > bzw. dieses __main durch mein eigenes ersetzen. s.o. Gruß Marcus http://www.doulos.com/arm/
Hi Marcus, dass der Startupcode normalerweise beim __main-Call endet ist mir klar. Was ich machen will: ich habe meinen eigenen Startupcode geschrieben. Der hat z.B. auch einen Dispatcher für alle Interrupts, erlaubt die Verwendung von SWI's mittels eines Dispatchers und hat noch ein paar andere lustige Spielereien drin, die ich einfach haben will. Deshalb will ich diesen Startupcode verwenden und nicht den von Keil. Aber mein Problem ist jetzt, dass der Startupcode ja auch das bss-Memory mit 0 initialisieren soll und dass er bestimmte Daten vom ROM ins RAM kopieren soll. Und beim Keil weiss ich nicht, wo welche Daten kopiert werden müssen oder wo das .bss liegt.
Jürgen G. schrieb: > Was ich machen will: ich habe meinen eigenen Startupcode geschrieben. > Der hat z.B. auch einen Dispatcher für alle Interrupts, erlaubt die > Verwendung von SWI's mittels eines Dispatchers und hat noch ein paar > andere lustige Spielereien drin, die ich einfach haben will. Deshalb > will ich diesen Startupcode verwenden und nicht den von Keil. Und das brauchst Du alles vor main()? Kannst Du nicht aus main() als erstes noch Deinen Code aufrufen? Welche Aufgaben sind so wichtig, dass sie nicht die paar Mikrosekunden warten können? > Aber mein Problem ist jetzt, dass der Startupcode ja auch das bss-Memory > mit 0 initialisieren soll und dass er bestimmte Daten vom ROM ins RAM > kopieren soll. Und beim Keil weiss ich nicht, wo welche Daten kopiert > werden müssen oder wo das .bss liegt. Das .bss heißt bei ARM ZI (Zero Initialize, uninitialisierte Variablen) und schließt normalerweise an die RW (initialisierte Variablen) Region an. Der ARM Compiler optimiert hier aber, so dass nicht unbedingt ein ZI erzeugt wird. Meine Frage wurde ja noch nicht beantwortet: >> Was genau meinst Du eigentlich mit Startup code -- den von Keil >> implementierten Reset Handler, oder das C library startup? Also eigentlich willst Du den Reset Handler neu implementieren, oder? Da sich Teile des neuen Codes auf korrekt kopierte Daten/Code verlassen, muss der neue Reset Handler auch das Scatter Loading enthalten, da er nicht warten kannst bis der entsprechende Code (aus der C library) sowieso ausgeführt wird. Ist dieses Problem nicht rekursiv? Gruß Marcus http://www.doulos.com/arm/
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.