Hallo Leutz,
hab mal wieder ein Problemchen. Bei meinem LPC2378 habe ich mit Bsp.
Progs angefangen und ganz einfache Sachen mal selbst ausprobiert, wie
Eingänge ansteuern. Mit dem eingebauten KEIL Compiler funktioniert das
auch reibungslos. Ich würde aber gern die GNU-Arm Collection verwenden.
Leider gibt es da beim kompilieren mehrere Fehler. Diese beziehen sich
jeweils auf die Startupdatei und die Bibliothek für die Hardware. Bei
der IDE von KEIL ist beides, angeblich für GNU, enthalten, gibt aber wie
gesagt Fehler. Gibt diese Dateien evtl. irgendwo als Download? Mir würde
auch ne Seite helfen wo die einzelnen Befehle erklärt sind, so dass ich
die vorhandenen modifizieren kann. Bzw. wäre es interessant, was die
Startup genau macht. Würde es vielleicht reichen die "originale" von
Keil zu nehmen und nur die Kommentare in "@" umzuwandeln?
Aber vielleicht kann mir auch jemand diesen Code erklären, bzw. wo der
Fehler liegt. Bin leider mit Assembler noch weniger vertraut als in C.
..\gnu\lpc2378_demo1\Common\src\Startup.S(75): error: junk at end of line, first unrecognized character is `F'
Ab FIQ kann er also nicht mehr lesen, oder verstehen... Was soll dieses
"+ \" eigentlich bedeutet, oder ist das ein falsch umgewandelter
Zeilentrenner? Der Code nach dem \ war vorher auf der nächsten Zeile.
Das würde zumnidest die Fehler erklären.
Wenn ich den \ weg nehme, dann kommt dieser Fehler nicht mehr, dafür
aber folgende:
/cygdrive/c/Programme/GNUARM/Bin/../lib/gcc/arm-elf/4.1.1/../../../../arm-elf/bin/ld: failed to merge target specific data of file .\startup.o
Steht FP für Floatpoint?
Weiterhin:
1
.\startup.o: In function `SWI_Handler':
2
..\gnu\lpc2378_demo1\Common\src/Startup.S(142): error: undefined reference to `SoftwareInterrupt'
3
.\startup.o: In function `IRQ_Handler':
4
..\gnu\lpc2378_demo1\Common\src/Startup.S(305): error: undefined reference to `TargetResetInit'
Die Codezeilen dazu sind:
1
SWI_Handler: B SoftwareInterrupt @ see swi_handler.S
und
1
ldmia sp!, {pc}^
Die Startup Datei scheint von Martin Thomas für GNU angepasst worden zu
sein. Das wundert mich auch, da er ja, glaub ich, der Mann hinter WInarm
ist, oder? Also vermutlich Ahnung hat.
Naja, genug erst mal ich hoffe ihr könnt mir Hinweise, Links, etc. zum
Problem geben.
Soweit schon mal danke, bis bald,
Hendi
> Was soll dieses "+ \" eigentlich bedeutet,> oder ist das ein falsch umgewandelter> Zeilentrenner? Der Code nach dem \ war vorher auf der nächsten Zeile.> Das würde zumnidest die Fehler erklären.
Genau so ist es. \ am Ende einer Zeile ist ein sogenannter "continuation
character". Wenn Du mehrere Zeilen zusammenfasst, musst Du dies
entfernen.
Also:
Ok, hab den Slash nun herausgenommen, jetzt treten halt besagte andere
Fehler auf.
Als vorher die Zeilen getrennt waren hat es aber mit Slash auch nicht
funktioniert, warum nicht? Welchen Assembler benutzt denn Winarm? Ist
das nicht auch der der GNU Tollchain, oder wurden da Änderungen
vorgenommen?
> Würde es vielleicht reichen die "originale" von Keil zu nehmen und nur die> Kommentare in "@" umzuwandeln?
Nein, neben dem Kommentarzeichen sind z.B. sind diverse andere Dinge
unterschiedlich (z.B. besagtes equ und auch section-defintionen)
>Steht FP für Floatpoint?
Ja. Sieht so aus, also würde der Compiler nicht mit den richtigen
Parametern aufgerufen. Habe GNUARM mit Keil uVision aber nie
ausprobiert.
Mein WinARM-Sammlung kann man in uVision einbinden:
http://www.siwawi.arubi.uni-kl.de/avr_projects/arm_projects/winarmtests/WinARM_uVision_glue_20070510.zip
Habe es aber nur oberflächlich mit der uVision Evaluierungsversion
getestet.
>Weiterhin:>.\startup.o: In function `SWI_Handler':
...
Die Funktionen Softwareinterrupt und TargetResetInit sind in anderen
Quellcodedateien implementiert, diese muss man ebenfalls
compilieren/assemblieren und linken.
>Als vorher die Zeilen getrennt waren hat es aber mit Slash auch nicht>funktioniert, warum nicht?
"Zeilenverlängerung" stellt meines Wissens bei der GNU-Toolhchain der
Preprocessor um. Der Realview Assembler kann das wohl von sich aus. Ruft
man den GNU Assembler über das Compiler-Frontend (arm-elf) und nutzt
grosses S in der Dateierweiterung (oder eine Option die ich grade nicht
im Kopf habe, irgendwas in der Art --assemblerwithcpp) wird der
Preprocessor automatische aufgerufen und neben continuation hat man noch
gleich noch die anderen praktischen Preprocessor-Funktionen zur
Verfügung (#define, #if etc.).
>Welchen Assembler benutzt denn Winarm?
Den Assembler aus den GNU Binutils hier in der arm-elf "Ausprägung"
(arm-elf-as). Das ist bei GNUARM, Yagarto etc. aber nicht anders.
> Ist das nicht auch der der GNU Tollchain, oder wurden da Änderungen> vorgenommen?
WinARM ist im Kern die GNU-Toolchain für arm-elf. Änderungen wurde nur
für Kompatibilität mit dem Host ("Windows PC") vorgenommen, aber keine
in Bezug auf das Target (ARM).
Martin Thomas
Hallo Thomas, danke dir für die ausführliche Antwort. Dachte mir schon,
dass Winarm genau die gleichen Files verwendet, deswegen kam mir das
komisch vor, ich werde mal versuchen noch die fehlenden Files
einzubinden und dann sehen wir weiter, wenn nicht komme ich gern auf
deinen Download zurück, aber ich muss da noch kurz selber rum frickeln,
das wurmt mich...
Ich geb dann Bescheid, bis dahin muss es Keil halt alleine tun.
So, hab mich jetzt noch mal n bissel mit der Materie beschäftigt, werd
aber immernoch nicht ganz schlau. Ich hab jetzt erst mal grundsätzliche
Funktionalität eines Demoprogs, von Martin Thomas, hinbekommen. Ich hab
allerdings immernoch das Problem mit den Software und Hardware Floating
Points. Hat der 2378 denn Hardwarefloatpoints? Wenn ja wäre es doch am
günstigsten diese auch zu nutzen, oder? Wie tu ich das denn, ich muss
doch sicher irgendein Bit setzen, nur wo, das Manual hat mir keine
dieser Fragen beantwortet.
Dann noch was, der C-Compiler compiliert die C-Sources, der Assembler
die ASM Sourcen und der Linker verknüpft alles. Warum kann so ein
Linkerskript so unheimlich aufgebläht sein, kommt das durch die
Speicherzuteilung? Das Linkerskript ist doch veranwortlich wo was
gespeichert wird, oder? Dieser bss-Speicher, wo packt man den denn hin?
oder setzt man den dynamisch nach den Daten an?
Dann wollte ich gern noch wissen, was so eine Startupdatei eigentlich
genau macht. Ich hatte das so verstanden, dass sie den Code enthält, der
als Erstes, also nach einem Reset ausgeführt wird. Also ist das Teil so
etwas wie eine große Konfigurationsdatei, kann man das so sagen? Also,
alles, was nicht zur Laufzeit umgestellt werden soll kann da rein, oder?
An welcher Stelle der startup steht eigentlich, dass die main()
aufgerufen werden soll? Ist ein Prog auch ohne diese Datei lauffähig?
Danke für eure Antworten, auf für den einen oder anderen triviale
Fragen,
Hendi
> Hat der 2378 denn Hardwarefloatpoints?
Hätte er sowas wie VFP, wäre es sicher einer der ersten Punkte in der
Feature-List.
> Dann noch was, der C-Compiler compiliert die C-Sources, der Assembler> die ASM Sourcen und der Linker verknüpft alles. Warum kann so ein> Linkerskript so unheimlich aufgebläht sein, kommt das durch die> Speicherzuteilung?
Was heisst aufgebläht? Was erscheint überflüssig? Schon mal das default
Linker-Script angeschaut (arm-elf-ld --verbose)? Schon versucht jede
Zeile eine "aufgeblähten" Linker-Skritps zu versehen und nachzusehen, ob
die überflüssig ist?
> Das Linkerskript ist doch veranwortlich wo was gespeichert wird, oder?
Im Prinzip ja.
> Dieser bss-Speicher, wo packt man den denn hin?
Ins RAM. Der darin abgelegte Variableninhalt muss zwar beim Start 0
sein, kann sich aber zur Laufzeit ändern.
> oder setzt man den dynamisch nach den Daten an?
Benötigten Platz errechnet der Linker, Start- und Endaddresse werde
ebenfalls definiert und später bei der Initialisierung genutzt. in bss
kommt der Inhalt statischer mit 0 initialisierten Variablen. "Dynamisch"
ist er üblich für Verwaltung von Speicher auf dem Heap aber das ist
wieder etwas anderes.
>Dann wollte ich gern noch wissen, was so eine Startupdatei eigentlich>genau macht.
Üblich: Execpetions-Vectoren einrichten, Stack-Pointer der verschiedenen
Modi setzten, Betriebsmodus beim start von main() setzen, .data ins RAM
kopieren, .bss auf null setzten. Funktionalität kann aber in mehreren
Quellcodedateien implementiert sein (in der Art vectors.s, startup.s,
lowlevelinit.s/.c), muss nicht unbedingt alles in der "Startupdatei"
sein.
> Ich hatte das so verstanden, dass sie den Code enthält, der> als Erstes, also nach einem Reset ausgeführt wird.
Ungefähr. Bei Reset wird von der Hardware eine bestimmte Adresse
angesprungen (typisch PC auf 0x00000000, erster Execeptions-Vector, kann
auch "virtuell" sein, vgl. remapping). Üblicherweise steht dort ein
Sprung zum Reset-Code. Das muss nicht zwangsläufig alles in einer
"Startupdatei" implementiert sein, ist aber grade bei Projekten nach dem
"Keil Schema" (alles an "lowlevel" in einer Assembler-Quellcodedatei
namens startup.s) nicht unüblich.
> An welcher Stelle der startup steht eigentlich, dass die main()> aufgerufen werden soll?
Uff, die Mühe gemacht, nach der Zeichenkette main zu suchen?
Bei Verwendung der GNU-Toolchain oft in einer Sequenz: .extern main, LDR
Rx, main, BX R1. Bei Code für Realview werden einige
Initialisierungsarbeiten (data, bss, stdio(?) u.a.) in einer Funktion
__main gemacht, die ihrerseits main() ruft, aber genug Realview, dies
ist ja das GCC-Forum.
Martin Thomas
Ich danke dir, das hat wieder ne ganze Menge Licht in die Geschichte
gebracht. Jetzt ist dann auch das mit dem Memoryremapping klar. Ich
dachte ich hätte nach der Main gesucht, aber scheinbar hab ich die zwei
kleinen Einträge überlesen....sorry. Das mit dem aufgebläht hab ich nur
gemeint, weil einem dass gar nicht so bewusst ist, wenn die IDE alles
übernimmt und man zum dummen Schaf wird, dass nur zwei Adressen eingeben
muss, da scheint einem diese plötzliche Mehrarbeit doch recht
unangenehm, das war keine persönliche Kritik! Ich habe mich nur
ansatzweise damit beschäftigt und bin der Meinung, dass man da ne Weile
braucht um 100% durchzusteigen. Ich hoffe das wird noch, halt noch n
"paar" Manuals lesen. Gut, ich danke dir erstmal für deine
Ausführlichkeit!
Bis bald,
Hendi