mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Keil und Startup-Code


Autor: Jürgen G. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Hugo B. (stinkywinky)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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".

Autor: Jürgen G. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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!
:-(

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>- 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...!!!!!

Autor: Jürgen G. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> 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!

Autor: Martin Thomas (mthomas) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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).

Autor: Marcus Harnisch (mharnisch) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Jürgen G. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Marcus Harnisch (mharnisch) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.d...

Hilfreich ist auch das hier
http://infocenter.arm.com/help/topic/com.arm.doc.d...

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/

Autor: Jürgen G. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Marcus Harnisch (mharnisch) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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/

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.