mikrocontroller.net

Forum: Compiler & IDEs Wie funktioniert der ARM cortex M3?


Autor: High Performer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Leute,

OK, der Betreff wirkt etwas provokativ. Ich habe folgendes Problem:

ich würde mich gerne ein wenig "from ground up" mit der STM32-Serie 
beschäftigen. Als Compiler möchte ich den gcc verwenden.

Das "from ground up" bedeutet, dass ich auch die Hintergründe verstehen 
möchte. Das Problem: ich scheitere gerade an den Basics.

Ich habe mir jetzt den arm-elf-gcc aus dem Quellen übersetzt. Schon das 
war nicht einfach, da man diverse andere Pakete benötigt, die man irgend 
wie verheiraten muss. Weitere Probleme gibt es mit den 
configure-Optionen. Nun steht die "toolschain", auch die STM32 
peripheral lib habe ich heruntergeladen. Ein einfaches test.c mit leeren 
main() lässt sich als Assemblerausgabe übersetzen. Der erzeugte 
Assemblerquelltext passt soweit.

Nun habe ich jedoch kaum Erfahrung mit dem Einbinden von Startup codes. 
In der Peripheral lib gibt's ja eine Menge Dateien, wo ich schon gar 
nicht weiß, welche ich verwenden will.

Schleuse ich das Testprogramm einfach durch den gcc und lasse dabei auch 
linken, wird gegen die newlib gelinkt, als Ergebnis erhalte ich ein 
a.out. Leider ist das Minimalprogramm fast 100KB groß, also schon zu 
groß für die meisten STM32-Typen.

Das Problem: ich habe circa zwanzig crt0.o im arm-elf-System, zig 
"Linkerscripte", von deren Syntax ich keine Ahnung habe, etc. pp.
Rufe ich gcc mit -nostdlib auf und lasse eine crt0 dazulinken, meckert 
er über fehlende Symbole. Lasse ich crt0 weg, meckert er wegen fehlendem 
_start.

Also zusammenfassend:

1.) Schon bei der Toolchain-Erstellung fehlen mir die notwendigen 
Details zu den möglichen Optionen und deren Auswirkungen. Wo finde ich 
Details?

2.) Mit welchem Startcode komme ich zu einem Minimalprogramm mit 
vernünftiger Größe?

3.) Warum wird schon bei einem leeren main() ein Haufen Zeug aus der 
newlib dazugelinkt?

4.) Wo gibt Details über die Linkerscripte?

5.) Ich habe mir einige Doku von arm und stm angeschaut. Irgend wie ist 
nirgendwo im Detial erklärt, wie der Startprozess bei den cortex-Typen 
aussieht. Ich weiß nur, dass bei boot0 = 0 der Startcode ab 0800 0000 
ausgeführt wird. Abhängig vom Bootmode wird der Flashbereich angeblich 
in den Bereich ab Adresse 0000 0000 gemapped. Irgendwo steht, dass nach 
dem Reset des Prozessors die Stackendadresse aus Adresse 0000 0000 
gelesen und dann mit der Programmausführung an Adresse 0000 0004 
begonnen wird. Da stellt sich mir z.B. gleich die Frage, wo die 
Interruptvektoren liegen.

Ich weiß auch, dass es auf der Gnu homepage eine Menge Doku gibt. Ich 
weiß, dass configure --help geht, ich habe die Doku der STM32 
Prozessoren und die Original ARM-Doku vorliegen. Jetzt muss ich nur noch 
alles verstehen. Ich habe durchaus einige Erfahrung, z.B. mit 
PC-Programmierung (C++, Java, Asembler), verschiedenen einfacheren 
Controllern, Hardwareentwicklung etc.
Aber das "from ground up" bei den ARM-Typen scheint nicht ganz trivial 
zu sein. Und das Thema JTAG ist noch völlig offen. Irgend wie muss ich 
den Code ja noch in den Prozessor kriegen.

Bei den AVR-Teilen war das alles relativ unkompliziert, da habe ich 
sogar kurz ein tool geschrieben, um den Maschinencode in den Prozessor 
zu bekommen (LPT missbraucht, timing ausführlich in der AVR-Doku 
beschrieben). Alles sehr einfach und überschaubar. Auch die toolchain 
war schnell gebaut.

Wäre nett, wenn mir jemand Tipps geben könnte, auch wenn meine Fragen 
vielleicht ein wenig diffus wirken. OK, zu Not beschaffe ich ein 
Entwicklungsboard, dann habe ich wenigstens kein Problem, das Programm 
in den Prozessor zu bekommen. Aber auch dann denke ich, bleibt noch 
einiges zu tun, wenn ich nicht eine fertige Toolchain verwenden möchte.

Also wie gesagt: ich bin für jeden Tipp dankbar.

Autor: Albert ... (albert-k)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mal eben das zu erklären wie man den startup-Code mit den Vector-tables 
und der initialisierung schreibt wird schwierig, das ist recht 
aufwendig. Du kannst das ganze aber hier nachlesen:
http://books.google.de/books?id=mb5d_xeINZEC&print...

Auf der Arbeit habe ich noch ein pdf wo die erstellung des Startup-Codes 
udn der Linkerscripte für einen stm32 genau erklärt wird. Das schicke 
ich dir morgen auch mal. Da ist es ganz genau step-by-step erklärt.

Die eifnachste Variante wird aber sein sich zumindest mal den startup 
zuschicken zu lassen. Dann must du nur noch das linkerscript und das 
makefile schreiben.

Autor: High Performer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Albert:

vielen Dank für Deine schnelle und nette Antwort! Wie gesagt, ich habe 
mir ja bereits die Library von STM heruntergeladen. Da ist jede Menge 
Startupcode und linker-Beiwerk dabei. Das ganze ist halt ein wenig 
unübersichtlich, wenn man in die Thematik einsteigt. ;-)

Es wäre deshalb sehr nett, wenn Du mir die von Dir erwähnte Doku 
zukommen lassen könntest. Vielen Dank schonmal.

Parallel werde ich mir mal die Doku zu den STM-libs anschauen. 
Vielleicht komme ich ja inzwischen ein wenig weiter.

Autor: High Performer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Albert:

Nachtrag: Das erwähnte Buch liegt schon seit geraumer Zeit in meinem 
Amazon-Wünschzettel. Aber da liegen noch ca. 250 andere ;-)

Werde mir mal die Auszüge auf google anschauen. Ich dachte halt, mit der 
Originaldoku wäre ich eigentlich bestens versorgt. OK, wenn das Buch 
einen guten Eindruck macht, werde ich es mal bestellen.

Autor: Albert ... (albert-k)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Das Buch musst du nciht unbedingt bestellen. Ich finde nicht das es 
nötig ist wenn mal ein projekt zum laufen gebracht hat.

Im Ordner der STM Peripheral Lib gibt es im ordner 
libraries/CMSIS/Documentation ein htm File was schon relativ viel 
erklärt was startup Code und ähnliches angeht. Unter Punkt 3 steht das 
interessante davon.

Hier mal die Art wie ich vorgehen würde:
Als erstes brauchst du mal den startup-code. Diesen findest du im Ordner 
libraries/CMSIS/CM3/DeviceSupport/ST/STM32F10x/startup/arm.
Eines dieser files musst du in dein Projekt einbinden (welche von den 
vielen weiss ich net, müsste man genauer lesen) und dann im Linkerscript 
bekanntmachen. Dieses File ruft dann auch deine int main(void) Funktion 
auf.
Siehe dazu die Codezeilen:
Reset_Handler    PROC
                 EXPORT  Reset_Handler             [WEAK]
     IMPORT  __main
     IMPORT  SystemInit
                 LDR     R0, =SystemInit
                 BLX     R0
                 LDR     R0, =__main 
                 BX      R0 
                 ENDP
Dann brauchst du vl. noch die core_cm3.c und core_cm3.h. Diese findest 
du im Ordner Libraries\CMSIS\CM3\CoreSupport.

Und dann eben die ganzen librarie files.

Ein Makefile für den STM32 findest du hier:
http://svn.savannah.gnu.org/svn/paparazzi/paparazz...
Das musst du natürlich noch anpassen. Also die Pfade zum gcc und deinem 
Linkerscript.

Autor: Albert ... (albert-k)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vergiss den c-Code den ich angehängt habe.

Autor: High Performer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Vergiss den c-Code den ich angehängt habe.

:-)

Habe schonmal die Hilfedatei angeschaut. Die von Dir beschriebene Info 
habe ich allerdings nicht gefunden. Werde gleich nochmal suchen. Andere 
Frage: Reicht prinzipiell der Startupcode, oder muss wirklich ein Teil 
der newlib dazugelinkt werden? So lange ich keinerlei 
Standardfunktionen verwende, sollte doch eigentlich der Startupcode 
reichen, oder nicht?

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

Bewertung
0 lesenswert
nicht lesenswert
- Startupcode für GNU Assembler ist in der STM-Library 
lib/cmsis/core/cm3/startup/gcc suffix betr. die "Baureihe" md entspr. 
medium density (habe ich selbst für STM noch nicht verwendet, wird aber 
sicher funktionieren)

- ein Linker-Script für GNU Linker ist in proj/templ/RIDE, muss evtl. 
ein wenig angepasst werden, ist aber eine brauchbare Basis (war sie 
zumindest für mich)

- man kann ohne newlib auskommen, auf jeden Fall ohne die recht 
speicherfressenden stdio Funktionen (also erstmal kein printf oder 
ähnliches verwenden - und wenn dann wenigstens iprintf)

- target arm-elf wird nicht mehr häufig genutzt, toolchain mit target 
arm-eabi konfigurieren wenn selbst bauen unvermeidbar. Besser fertig 
gebaute toolchain verwenden, bleiben noch genug andere "Baustellen"

- crt0 und linker-scripte in der toolchain habe ich nie genutzt, sind 
etwas zu generell und scheinbar für Systeme, die mehr Speicher und einen 
ununterbrochenen Adressraum haben. Weiterhin werden durch diese Dateien 
auch Abhängigkeiten erzeugt (mglw. Fehlermeldungen bei exit() o.ä. die 
dann stdio/vfprintf nachziehen). Ja, das ist leider nicht so schön wie 
bei avr-libc wo alles gut vorgekaut und auf kleine Controller abgestimmt 
ist.

Autor: noch ein (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ High Performer

Gib uns Bescheid, wenn Du im startup-code für STM32
über das hier stolperst:
0xF1E0F85F
Dann wird es für mich interessant. ;-)
Ich konnte dafür noch keine schlüssige Erklärung
finden, außer dass notwendig. Nur wieso, schreibt
niemand. Habe es zumindest noch nicht gefunden.

Autor: gerhard (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hallo High Performer,
auch auf die gefahr hin von einigen gcc freaks "gesteinigt" zu werden, 
hier meine empfehlung wenn es dir um das verstehen des stm32 bzw. des 
cortex m3 geht und nicht um die inbetriebnahme einer tool-kette:

lade dir die kickstart version der iar entwicklungsumgebung von der iar 
homepage (kostet nichts und du kannst projekte bis 32kbyte code 
erzeugen), installiere sie, lade eines der beispielprogramme und 
versuche diese zu verstehen.
zeitaufwand: ca. 30 Minuten

wenn du das ganze debuggen möchtest:
kauf dir den J-Link EDU von segger (kostest ca. €70,- inkl. versand).

gruss
gerhard

Autor: Heinz (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Auch interessant:

www.state-machine.com/arm/Building_bare-metal_ARM_with_GNU.pdf

(weiss allerdings nicht sicher, ob das den Cortex abdeckt).

GNU Tools gibt's fertig bei CodeSourcery.

heinz

Autor: Heinz (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@noch ein Gast

0xF1E0F85F ->

https://my.st.com/public/STe2ecommunities/mcu/List...

Heinz

Autor: High Performer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@gerhard:

>hallo High Performer,
>auch auf die gefahr hin von einigen gcc freaks "gesteinigt" zu werden,
>hier meine empfehlung wenn es dir um das verstehen des stm32 bzw. des
>cortex m3 geht und nicht um die inbetriebnahme einer tool-kette:

Vielen Dank für den Tipp. Warum sollten Dich dafür gcc-freaks steinigen? 
;-)

Ich gebe zu, dass ich auch gerne mit dem gcc arbeite. Die 
Linux-Entwicklung läuft bei mir mit dem gcc, auch das avr-Zeugs 
übersetze ich mit gcc. Deshalb wäre es natürlich schon günstig, wenn ich 
auch die ARM-Schiene mit dem gcc erschlagen könnte.

Ich denke mal, das Hauptproblem beim Einstieg in eine neuer Architektur 
ist wohl, die toolchain zum Laufen zu bekommen und das erste 
Blinkprogramm auf dem Prozessor laufen zu lassen. Das ist das eigentlich 
spannende ;-) Der Rest ist dann Datenblattstudium (OK OK, es gibt bei 
jeder Architektur Pferdefüße) und testen der Peripherie. Aber damit habe 
ich eigentlich nie Probleme.

Trotzdem nochmal vielen Dank für Deinen Tipp.

Autor: High Performer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Aktueller Stand:

habe alle mir bekannten relevanten Dateien (.c und .s) mit gcc und as 
übersetzt. Beim Versuch, das ganze mit ld mit dem in der STM-library 
vorhandenen Linkerscript zu linken, stürzt anscheinend ld ab 
(Speicherzugriffsfehler). Ohne die crt0.o aus der Toolchain findet ld 
auch die Marke _start nicht. In der STM-library habe ich keine 
crt*-Dateien finden können. OK, ich schaue mal nach in welcher Datei aus 
der STM-library _start definiert ist. Bleibt nur das Problem mit dem 
ld-Absturz...

Autor: noch ein (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Heinz
super!
vielen Dank!

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

Bewertung
0 lesenswert
nicht lesenswert
High Performer schrieb:
> Aktueller Stand:
>
> habe alle mir bekannten relevanten Dateien (.c und .s) mit gcc und as
> übersetzt.
> Beim Versuch, das ganze mit ld mit dem in der STM-library
> vorhandenen Linkerscript zu linken, stürzt anscheinend ld ab
> (Speicherzugriffsfehler).

- Immer nur mit dem Compiler-Frontend arbeiten, direkte Aufrufe von as 
und ld vermeiden. Geht alles auch über arm-*-gcc und spart Stress.

- Absturz Speicherzugriffsfehler darf nicht sein. Das kann man getrost 
Codesourcery mitteilen. Linker sollte sich zumindest mit einer 
ordentlichen Fehlermeldung verabschieden.

> Ohne die crt0.o aus der Toolchain findet ld
> auch die Marke _start nicht.

Fehler oder Warnung? Im Zweifel im verwendeten Linker-Script (ist mit -T 
dem Linker anzugeben) zu Beginn ein ENTRY(Reset_Handler); sollte Warnung 
verschwinden lassen.

>In der STM-library habe ich keine
> crt*-Dateien finden können.

Die im o.g. Pfad zu findenden Startup-Codes heissen nur nicht crt*, 
enthalten aber den erf. Startcode (.data copy, bss clear, main rufen) 
und auch den Vector-Table

> OK, ich schaue mal nach in welcher Datei aus
> der STM-library _start definiert ist.

Womöglich nirgends. Evtl. kann man im Assembler-Startup hinter 
Reset_Handler: noch eine Zeile _start: schreiben.

>Bleibt nur das Problem mit dem ld-Absturz...

Das ist nicht gut. Ist mir aber noch nicht begegnet, nutze CS G++ lite 
schon seit vielen Versionen (unter MS Win).


Zwar "Eigenwerbung" aber hier ist ein Projekt für STM32 und GNU Tools 
(CS G++ lite verwendet): 
http://www.siwawi.arubi.uni-kl.de/avr_projects/arm.... 
Geht weniger um den Anwendungscode, vielmehr einfach die Ausgabe von 
"make all" betrachten. Das hilft vielleicht etwas, die Schritte und erf. 
Dateien zu verstehen. Gibt Variationsmöglichkeiten aber die im Projekt 
gezeigte Vorgehensweise funktioniert hier ganz gut.

Autor: High Performer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Absturz Speicherzugriffsfehler darf nicht sein. Das kann man getrost
>Codesourcery mitteilen.

Würde wohl nicht viel bringen. Ich habe die toolchain direkt aus den 
gnu-Quellen erstellt.

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hier noch ein paar nützliche Links:

Toolchain bauen: http://github.com/esden/summon-arm-toolchain

GPL'te firmware lib für STM32: 
http://sourceforge.net/projects/libopenstm32/develop

(dort gibts auch simple code-Beispiele und Linkerskripte)

Autor: Matthias K. (matthiask)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>GPL'te firmware lib für STM32:
>http://sourceforge.net/projects/libopenstm32/develop
>(dort gibts auch simple code-Beispiele und Linkerskripte)

Gibts dort auch irgendwas zum Download? Wo?

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Es gibt ein git repository mit code, aber wohl (noch) keine ZIP/TGZ 
Dateien zum downloaden.

Code browsen: 
http://libopenstm32.git.sourceforge.net/git/gitweb...

Dort kannst du auf "snapshot" klicken und bekommst hoffentlich den 
aktuellen Stand als tar.gz Datei (sollte winzip z.B. auch öffnen können 
falls du nicht unter Linux arbeitest).

Autor: High Performer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Leute,

hier mal der aktuelle Stand:

Habe nun, nachdem ld immer abgestürzt ist, mal eine andere Version der 
binutils übersetzt und verwendet. Nach einigen Versuchen kam dann auch 
eine ausführbare Datei mit ca. 2,5KB Code dabei raus. Habe mir ein 
Hexfile draus gebaut und mal angeschaut. Zumindest das Heapende steht, 
wie in der ARM-Doku beschrieben, an Adresse 0. Der Adressraum beginnt 
bei 0x08000000, also landet der Code im Flash. Für mich sehen die Daten 
ab der Adresse vier allerdings eher nach Interruptvektoren aus als nach 
ausführbarem Code. Auch objdump zeigt mir an, dass Vektoren am 
Flashanfang stehen, was also darauf hindeutet, dass irgend etwas schief 
läuft. Laut ARM-Doku soll ja an Adresse 4 der ausführbare Code beginnen. 
Könnte sein, dass ein ungeeignetes Linker Script die Interruptvektoren 
an die falsche Stelle klatscht. Werde mich mal um die Interruptvektoren 
kümmern (weiß jemand, wo die liegen sollen?) und wieder melden. Aber wie 
gesagt: immerhin lief ld fehlerfrei durch. Aber bei int main (void) { 
return 0; } ist das auch keine Kunst. Mal sehen, wenn ich tatsächlich 
ein Programm schreibe, dann vor allem mit Funktionen aus der 
C-Standardlib oder gar Fließkommaarithmetik.

Ich bin weiterhin für alle Hinweise dankbar. Momentan vor allem für das 
Thema Interruptvektoren.

Vielen Dank an dieser Stelle für alle bisherigen und folgenden 
Antworten.

Schönen Abend noch.

Autor: High Performer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
OK, ich sehe gerade, im ausführbaren Code steht an Adresse 4 die 
Adresse des Resethandlers. Ich denke nicht, dass das so korrekt ist, 
oder?

Vom Resethandler geht's dann wie folgt weiter:

LoopCopyDataInit bzw. CopyDataInit, dann
LoopFillZeroBss bzw. FillZeroBss, dann SystemInit und am Schluss main.

Autor: Albert ... (albert-k)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo, das ist so schon richtig. Am Anfang des flashes steht die Vector 
Table für den NVIC. Und an Adresse 4 steht der Reset_Handler. Du hast 
die Doku insoweit missverstanden das der Controller diesen Handler als 
erstes aufrufen wird (wenn er startet). In diesem Reset Handler wird 
manchmal eine lowlevel_init aufgerufen die die CPU Clock einstellt oder 
gleich die main aufgerufen. Hinter der Adresse 0x00000004 stehen ab 
Adresse 0x00000008 die anderen Interrupt Vektoren.

Hier mal noch eien Seite mit dem Startzup Code und dem dazugehörigen 
linkerscript:
http://embeddedfreak.wordpress.com/2009/08/07/cort...

Autor: High Performer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Albert:

OK, nach der Doku im Link passt das so, wie das Hexfile bei mir 
aussieht.

Nächstes Problem: wollte mal etwas aus der Standardlib testen. Habe 
div() verwendet. Nun findet ld diese Funktion nicht, egal, welche lib 
ich angebe (libc müsste doch OK sein, oder?)

Na ja, alles ein wenig zäh, aber der Lerneffekt ist enorm. ;-)
Ich denke, das wird der letzte Prozessor sein, bei dem ich so nackt 
starte. Aber vielleicht packt mich ja der Ehrgeiz wieder mal...

Ach ja, zum Thema Doku wegen des Bootvorgangs. Ich  zitiere aus dem 
STM32 reference manual:

"... After this startup delay has elapsed, the CPU fetches the 
top-of-stack value from address 0x0000 0000, then starts code execution 
from the boot memory starting from 0x0000 0004."

Die Frage ist nun: steht an Adresse vier einfach eine Adresse, oder 
ein Sprungbefehl? Habe mir den Opcode nicht näher angeschaut. Sollte 
so langsam schlafen gehen, morgen wieder arbeitsreicher Tag. Melde mich 
morgen Abend nochmal.

Viele Grüße!

Autor: Albert ... (albert-k)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
High Performer schrieb:
> Ach ja, zum Thema Doku wegen des Bootvorgangs. Ich  zitiere aus dem
> STM32 reference manual:
>
> "... After this startup delay has elapsed, the CPU fetches the
> top-of-stack value from address 0x0000 0000, then starts code execution
> from the boot memory starting from 0x0000 0004."
>
> Die Frage ist nun: steht an Adresse vier einfach eine Adresse, oder
> ein Sprungbefehl? Habe mir den Opcode nicht näher angeschaut. Sollte
> so langsam schlafen gehen, morgen wieder arbeitsreicher Tag. Melde mich
> morgen Abend nochmal.

An Adresse 0x0000 0004 steht NUR die Adresse des Reset Handlers. Aber 
die erste Aufgabe des Controllers ist es an die dort angegebene Adresse 
zu springen. Er fängt also mit einem Sprung an diese Adresse an. Danach 
(ab Adresse 0x0000 0008) folgen andere Interrupt Handler (die ersten 15 
sind Core spezifisch, danach folgen die Herstellerspezifischen für die 
Peripherie). Nachzulesen im Cortex-M3 Insight Guide von Hitex im Kapitel 
2.4.5.3.1
http://www.st.com/mcu/files/mcu/1221142709.pdf

>Nächstes Problem: wollte mal etwas aus der Standardlib testen. Habe
>div() verwendet. Nun findet ld diese Funktion nicht, egal, welche lib
>ich angebe (libc müsste doch OK sein, oder?)

Hast du die include Pfade korrekt angegeben? div() findet sich ja in der 
stdlib.h. Ich gehe mal davon aus das in deinem Linkerscript der Pfad 
nicht korrekt angegeben ist.
Kannst du mal dein Linkerscript anhängen?

P.S. Wenn das Projekt dann mal läuft, besteht die möglichkeit eine kurze 
Anleitung zu bekommen welche Dateien benötigt werden, welche tools du 
verwendest und wie man vl. in 5 Schritten zu nem eifnachen Startprogramm 
kommt?

Autor: High Performer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Hast du die include Pfade korrekt angegeben? div() findet sich ja in der
>stdlib.h. Ich gehe mal davon aus das in deinem Linkerscript der Pfad
>nicht korrekt angegeben ist.

Also die stdlib.h muss ja bereits der compiler finden. Das funktioniert 
ja auch. lediglich ld findet dann beim Zusammenbinden der einzelnen 
Dateien das Symbol nicht.

Also ich habe nun die toolchain nochmal komplett neu erstellt. Altes 
Problem: linker meldet:

"test2.c:(.text+0x12): undefined reference to `div'"

libc.a, libgcc.a und libg.a werden gefunden (--verbose output von ld).

libc.a enthält laut Ausgabe von nm das Symbol div. Warum wird dies nicht 
vom Linker gefunden?

Werde nun mal andere Funktionen aus stdlib testen...

OK, memcpy() findet ld ebenfalls nicht.

Habe schon ein komisches Gefühl, weil ich gcc mit --disable-headers 
übersetzt habe. Allerdings, wie gesagt, gibt's ja erst mit dem linker 
Probleme. Warum findet der shice ld das Symbol nicht. Werde jetzt mal 
die relevanten object files aus den libs rauskopieren und direkt in der 
Kommandozeile von ld angeben...

Scheitert leider ebenfalls. Zuerst hat er __divsi3 und __modsi3 nicht 
gefunden. Habe die entsprechenden Dateien angegeben. Jetzt findet er 
__div0 nicht. __div0 ist jedoch in der Datei _divsi3.o enthalten, in der 
auch __divsi3 definiert ist. Was nun?

Nachdem er ja die beiden bislang fehlenden Symbole gefunden hat, dafür 
aber ein weiteres nicht findet, das aber definiert ist, vermute ich 
irgend ein Problem im Linker. Es sieht so aus, als würde er 
Abhängigkeiten nicht rekursiv auflösen können. Hat jemand von Euch eine 
Idee?

Autor: Happy Hippo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert

Autor: High Performer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
OK, habe die Lösung nach exzessiver Verwendung von google:
Die Reihenfolge der Objektdateien spielt eine entscheidende Rolle beim 
ld! Und zwar, logischerweise, in der umgekehrten Reihenfolge, wie ich 
zuerst dachte. Beispiel:

datei1.o benötigt Symbol A
datei2.o definiert Symbol A.

--> ld datei2.o datei1.o.

ld bindet die Dateien in der angegebenen Reihenfolge. Für datei1.o muss 
Symbol A bereits definiert sein, also in der Symboltabelle des Linkers 
enthalten sein. das Symbol ist nun in datei2.o definiert. Deshalb muss 
datei2.o zuerst angegeben werden.

OK, werde mal noch kurz a.out und das hexfile checken. Dann bis morgen.

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.