Forum: Mikrocontroller und Digitale Elektronik STM32 linker scripts


von Sven W. (woehlb)


Lesenswert?

Wie ist das, wenn ich ein Programm für den flash übersetze. Landet alles 
beim programmieren des Mikrocontrollers im Flash, und die Kopien des 
RAM's werden bei dem Start aus dem Flash kopiert? Daher im Linker Script 
die Anweisung ">ram AT > rom" bei den Datenbereichen?

Wenn ein Programm für den RAM übersetzt wird landet auch alles im Flash, 
aber beim Programmstart wird alles(Programm und Datenbereiche) aus den 
Flash in den RAM kopiert? Daher auch hier im Linker Script ">ram AT > 
rom" bei den Datenbereichen?

von Sven W. (woehlb)


Angehängte Dateien:

Lesenswert?

Hier mal noch meine aktuellen Linker Scripte.

von (prx) A. K. (prx)


Lesenswert?

Sven Woehlbier schrieb:

> Wie ist das, wenn ich ein Programm für den flash übersetze. Landet alles
> beim programmieren des Mikrocontrollers im Flash, und die Kopien des
> RAM's werden bei dem Start aus dem Flash kopiert? Daher im Linker Script
> die Anweisung ">ram AT > rom" bei den Datenbereichen?

Korrekt.

> Wenn ein Programm für den RAM übersetzt wird landet auch alles im Flash,
> aber beim Programmstart wird alles(Programm und Datenbereiche) aus den
> Flash in den RAM kopiert? Daher auch hier im Linker Script ">ram AT >
> rom" bei den Datenbereichen?

Normalerweise heisst "für RAM übersetzen", dass das Programm zusammen 
mit den Daten direkt ins RAM geladen und dort ausgeführt wird, und das 
ROM überhaupt nicht angefasst wird.

Der Sinn liegt hier im Debugging. Es schont das Flash, insbesondere wenn 
der Debugger für Breakpoints und Tracing den Code modifizieren muss.

Das jedenfalls ist die übliche Bedeutung. Deine Bedeutung und dein 
RAM-Script passen dazu nicht.

von Sven W. (woehlb)


Angehängte Dateien:

Lesenswert?

@ A.K.

Ok, ich habe das RAM Skript wie ich denke passend zu Deinen Hinweisen 
modifiziert. Ansonsten habe ich die Skripte noch um _bss_start_, 
_bss_end_ und _end ergänzt.

Ich erhalte beim Linken aber auch noch eine Fehlermeldung die ich mir 
nicht erklären kann.

Linking console executable: default\test3.elf
c:/programme/yagarto/bin/../lib/gcc/arm-elf/4.4.2/../../../../arm-elf/bi 
n/ld.exe:  error: 
c:/programme/yagarto/bin/../lib/gcc/arm-elf/4.4.2/../../../../arm-elf/li 
b\libc.a(lib_a-atexit.o)  uses hardware FP, whereas default\test3.elf 
uses software FP

Soweit ich das sehe heißt das, daß die libc eine Hardware Floatingpoint 
Unit benutzt und das Programm eine Software Emulation. Ich habe zwar den 
Yagarto compiler nicht komplett selbst übersetzt, aber soweit ich das 
den Compiling Skripten entnehmen konnte, wird der Yagarto ebenfalls mit 
einer Floatingpoint Emulation übersetzt. Insoweit kann ich mir die 
Fehlermeldung nicht erklären.

von Sven W. (woehlb)


Lesenswert?

Die nächste Frage die sich ergibt ist, wie kann man verhindern das die 
libc benutzt wird? Reicht es keine Funktionen aus der libc zu benutzen?

Nochmal zum Thema Floatingpoint Unit. Es kann natürlich bedeuten das nur 
der Compiler selbst mit einer Floatingpoint Emulation übersetzt wird 
nicht aber die libc (newlibc). Wie löse ich das Problem aber?

von (prx) A. K. (prx)


Lesenswert?

Von dem floating-point Problem habe ich gehört, hatte es selbst aber 
nicht ernsthaft. Es scheint etwas verwirrend zu sein, weil man intuitiv 
auf Soft tippt, nur um festzustellen, dass die Libs nicht dazu passen 
und Hard-Float implizieren, wobei im Resultat aber wieder Software 
verwendet wird. Ich hatte mir nicht die Mühe gemacht, dieses 
Verwirrspiel zu entschlüsseln. Es reichte mir, so zu übersetzen, dass es 
läuft ;-).

Die newlib zu vermeiden ist durchaus möglich und lohnenswert wenn der 
Platz eng ist, allerdings habe ich dafür keine fertige Rezeptur, da dies 
einige Jahre her ist und mit anderen GCC Versionen lief (WinARM, GNUARM, 
aber die sind tot). Was ich dort finde ist beispielsweise eine 
Linker-Option nostartfiles.

Mittlerweile verwende ich Crossworks, wodurch sich solche Probleme 
erledigt haben. Detailfragen über Probleme mit Yagarto kann ich also 
nicht beantworten.

von Sven W. (woehlb)


Lesenswert?

Beruflich nutze ich auch Crossworks, nur privat ist mir auch die 
Personal License zu teuer.

Ansonsten, trotzdem Danke!

von Martin T. (mthomas) (Moderator) Benutzerseite


Lesenswert?

Sven Woehlbier schrieb:
> @ A.K.

Bin zwar nicht A.K. aber dennoch ein Hinweis:

> Linking console executable: default\test3.elf
> c:/programme/yagarto/bin/../lib/gcc/arm-elf/4.4.2/../../../../arm-elf/bi 
n/ld.exe:
> error:
> c:/programme/yagarto/bin/../lib/gcc/arm-elf/4.4.2/../../../../arm-elf/li 
b\libc.a(lib_a-atexit.o)
> uses hardware FP, whereas default\test3.elf uses software FP

Bei solchen Fehler erstmal:
- Sicherstellen, dass nicht der Linker (arm-*-ld) direkt aufgerufen 
wird, sondern auch zum Linken das Compiler-Frontend (arm-*-gcc, bei 
Yagarto w.r.e. arm-elf-gcc) verwenden.
- Sicherstellen, dass auch beim Linken zumindest die cpu-Option 
(-mcpu=cortex-m3) mitgegeben wird.

Dient alles nur dazu, dass automatisch die richtige libc verlinkt wird, 
denn in Yagarto, CS G++, WinARM etc. sind mehrere für verschiedene 
ARM-Kerne drin. Falls weiterhin Probleme, komplette Ausgabe des 
Build-Vorgangs zeigen, inkl. aller Compiler-, Assembler- und 
Linkeroptionen.

So in der Art:
1
arm-elf-gcc -mthumb -mcpu=cortex-m3 startup.o main.o [...] --output
2
test3.elf -nostartfiles -Wl,-Map=test3.map,--cref,--gc-sections -L.
3
-lc  -lm  -lc -lgcc  -T./mylinkerscript.ld

von Sven W. (woehlb)


Lesenswert?

Ich bin gerade dabei, mir Codeblocks als Entwicklungsumgebung für die 
ARM Cortex M3 Entwicklung einzurichten. Ich habe bereits Codeblocks mit 
dem Openocd Plugin übersetzt, und aktuell passe ich den Projektwizard 
an, damit gleich passende Projekte für die STM32 Mikrocontroller erzeugt 
werden.

Wie kann ich unter Codeblocks einstellen, daß das Compiler-Frontend 
arm-*-gcc für das Linken benutzt wird? Unter den Toolchain Executables 
des GNU ARM Compilers kann ich jedenfalls keinen Linker für normale 
C-Projekte angeben.

von Sven W. (woehlb)


Angehängte Dateien:

Lesenswert?

OK, ich habe mittlerweile die Linker Scripts weiter ergänzt und syscalls 
für die newlib hinzugefügt. Außerdem habe ich unter den toolchain 
executables unter den Punkten "Linker for dynamic libs" und "Linker for 
static libs" das Comnpiler Frontend "arm-elf-gcc.exe" angegeben, damit 
der Linker nicht direkt aufgerufen wird. Jetzt erhalte ich die 
Fehlermeldungen in der angehängten Datei fehler.txt.

Damit scheint das Problem, daß über das Compiler Frontend die richtige 
newlib Bibliothek ausgewählt wird, nach wie vor nicht zu funktionieren.

Das andere Problem sind die Meldungen "interworking not enabled". Soweit 
ich das den Yagarto Build Scripts entnehmen kann wird Yagarto + newlib 
aber mit der Option interworking übersetzt. Das müßte natürlich auch für 
meine Dateien gelten.

Aber mit der Option "-mcallee-super-interworking" bekomme ich entliche 
Meldungen in der Art:

C:\DOKUME~1\woehlb\LOKALE~1\Temp\cceDzPXh.s|14|Error: selected processor 
does not support ARM opcodes|
C:\DOKUME~1\woehlb\LOKALE~1\Temp\cceDzPXh.s|25|Error: attempt to use an 
ARM instruction on a Thumb-only processor -- `sub sp,sp,#4'|
C:\DOKUME~1\woehlb\LOKALE~1\Temp\cceDzPXh.s|29|Error: attempt to use an 
ARM instruction on a Thumb-only processor -- `str r0,[sp,#0]'|

Mit der Option "-mcaller-super-interworking" erhalte ich die selben 
Fehlermeldungen wie in der Datei fehler.txt.

Habt Ihr eine Idee wie ich diese beiden Probleme lösen kann?

von Sven W. (woehlb)


Lesenswert?

Was heißt das überhaupt genau, wenn Code mit der Option 
"--enable-interwork " übersetzt wird?

von (prx) A. K. (prx)


Lesenswert?

Dass man ARM Code und Thumb Code mischen will. Auf einem CM3 ein Ding 
der Unmöglichkeit.

von Sven W. (woehlb)


Lesenswert?

Ich weiß, daß die ARM Cortex M3 im Gegensatz zu den ARM7TDMI nicht mehr 
zwei Befehlssätze unterstützen, sondern nur einen der eine Kombination 
aus den beiden Befehlssätzen der ARM7TDMI darstellt.

Aber was bedeutet Deine Bemerkung genau?

von (prx) A. K. (prx)


Lesenswert?

Dass Interworking bei einer CPU, die kein Interworking kann und auch 
keines benötigt, Blödsinn ist.

CPU Auswahl: -mcpu=cortex-m3 -mthumb

von Sven W. (woehlb)


Lesenswert?

Heißt das, daß ich Yagarto ohne die Option "--enable-interwork" neu 
übersetzen muß?

von Sven W. (woehlb)


Lesenswert?

Was bedeutet das interworking?

von (prx) A. K. (prx)


Lesenswert?

Dass man ARM Code und Thumb Code mischen will.

von Sven W. (woehlb)


Lesenswert?

Das geht natürlich bei einem ARM Cortex-M3 nicht, da er nur einen 
Befehlssatz unterstützt. Aber zurück zu meiner letzten Frage! Muß ich 
Yagarto ohne interworking neu übersetzen?

von (prx) A. K. (prx)


Lesenswert?

Sven Woehlbier schrieb:

> Heißt das, daß ich Yagarto ohne die Option "--enable-interwork" neu
> übersetzen muß?

Willst du Yagarto auf dem STM32 laufen lassen?

Ich dachte bisher, dass man Yagarto verwendet, um Code für den STM32 
zu übersetzen. Nur sollte man dabei eine Lib verwenden, die korrekt für 
den CM3 übersetzt wurde. Eine Lib für ARM bringt da nix.

Zur Yagarto direkt kann ich wenig beitragen. Verwende ich nicht.

von Sven W. (woehlb)


Lesenswert?

Nein, da hast Du jetzt was in den falschen Hals bekommen. Ich möchte nur 
mein Programm mit Yagarto für einen STM32 übersetzen. Die 
Fehlermeldungen mit dem interworking verwirren mich nur, denn es muß ja 
einen Grund geben, warum Yagarto mit interworking übersetzt wurde, 
obwohl es die ARM Cortex-M3 unterstützt.

von Sven W. (woehlb)


Lesenswert?

Natürlich muß die newlib auf dem STM32 laufen.

von Sven W. (woehlb)


Lesenswert?

Das Yagarto mit interworking übersetzt wurde, kann natürlich daran 
liegen, daß der Schwerpunkt in der Anwendung immer noch bei den ARM7TDMI 
liegt.

von (prx) A. K. (prx)


Lesenswert?

Bei solchen Umgebungen ist es eigentlich üblich, Libs in diversen 
Varianten anzubieten. Also solche für ARM7, für Thumb, für Thumb2, ... 
Wer die und wie man die auswählt habe ich grad nicht parat.

Aber da musst du mal jemanden finden, der Yagarto verwendet.

von (prx) A. K. (prx)


Lesenswert?

PS: Dein Sprachgebrauch irritiert immer wieder. Yagarto wurde für x86 
übersetzt, sonst würde es auf deinem PC nicht laufen. Wofür dann 
wiederum Yagarto übersetzt, das entscheidet sich über die Parameter.

Ein Compiler wird für die Maschine übersetzt, auf der er läuft (passiver 
Sprachgebrauch). Er selbst übersetzt dann für die Maschine, auf der das 
Programm läuft (aktiver Sprachgebrauch).

von Sven W. (woehlb)


Lesenswert?

@ A.K.

Vielen Dank, daß Du mir wieder so schnell geantwortet hast! Es macht 
Spaß sich mit der Materie zu beschäftigen, wenn man auf solche Leute wie 
dich trifft, und sich nicht irgendwelche trolligen Antworten gefallen 
lassen muß.

Jedenfalls nehme ich mal die Anregung mit, das Yagarto ohne interworking 
zu übersetzen. Vor längerer Zeit habe ich schon mal versucht, Yagarto zu 
übersetzen. Damals bin ich aber daran gescheitert. Aber ich kannte zu 
diesem Zeitpunkt die Seite http://www.yagarto.de/source/index.html noch 
nicht. Ich habe damals alle Quellen zwar mit der richtigen 
versionsnummer, aber irgendwo aus dem Internet gezogen und die 
Buildscripts von sourceforge.

Vor kurzem habe ich die Übersetzung mit den Quellen von 
http://www.yagarto.de/source/index.html neu versucht. Aber bevor die 
Übersetzung fertig war, mußte ich das Abbrechen,da ich den Rechner für 
andere Sachen brauchte. Zu diesem Zeitpunkt war ich aber schon 
wesentlich weiter als bei meinem ersten Versuch. Ich bin mal 
optimistisch, das eine neue Übersetzung was bringt.

Tschau, und noch mals vielen Dank!

von Sven W. (woehlb)


Lesenswert?

In Bezug auf Deine letze Bemerkung. Ist schon klar, deshalb ist es ja 
ein Crosscompiler.

von (prx) A. K. (prx)


Lesenswert?

Sven Woehlbier schrieb:

> In Bezug auf Deine letze Bemerkung. Ist schon klar, deshalb ist es ja
> ein Crosscompiler.

Aber du verwendest permanent eine Sprache, die das nicht so klar 
erscheinen lässt. Das erleichtert das Verständnis deiner 
niedergeschriebenen Gedanken nicht unbedingt.

So weiss ich deshalb immer noch nicht, was du mit "Jedenfalls nehme ich 
mal die Anregung mit, das Yagarto ohne interworking zu übersetzen." 
eigentlich meinst.

von Sven W. (woehlb)


Lesenswert?

Bleiben wir mal zum Beispiel bei der newlib! Sie wird natürlich als 
Bibliothek zunächst mit dem mingw auf einem PC übersetzt, entsprechend 
den Yagarto Buildscripten mit interworking. Was natürlich auf dem PC 
nicht zum tragen kommt. Aber diese mit dem mingw produzierten 
Bibliothekfiles werden benutzt, wenn ich ein eigenes Programm für den 
STM32 unter Verwendung der newlib mit dem Crosscompiler arm-elf-gcc.exe 
für den STM32 übersetze.

Da der STM32 als ARM Cortex M3 kein interworking unterstützt, wie ich 
das in unserer Diskussion festgestellt habe, muß es meiner Meinung nach 
zu Problemen führen, wenn die newlib mit interworking übersetzt wurde. 
Da die newlib dann Befehle enthält, die nicht zum Befehlssatz des STM32 
gehören.

von (prx) A. K. (prx)


Lesenswert?

Sven Woehlbier schrieb:

> Bleiben wir mal zum Beispiel bei der newlib! Sie wird natürlich als
> Bibliothek zunächst mit dem mingw auf einem PC übersetzt,

Da käme dann x86-Code heraus, der gcc aus mingw kann nichts anderes 
erzeugen. Kann man machen, scheint mir aber sinnlos.

Ich weiss, dass du das nicht meinst. Aber du schreibst hier in einem 
eigenen Sven-Deutsch, dass sich anderen nur schwer erschliesst.

Tatsächlich übersetzt du nicht Yagarto mit mingw, sondern du übersetzt 
vermutlich die Newlib mit Yagarto (mit oder ohne Interworking).

> zu Problemen führen, wenn die newlib mit interworking übersetzt wurde.
> Da die newlib dann Befehle enthält, die nicht zum Befehlssatz des STM32
> gehören.

Yep. Die Libs müssen sämtlich für die gleiche CPU erzeugt werden, wie 
der Rest der Anwendung auch.

von Sven W. (woehlb)


Lesenswert?

Bestandteil der Yagarto Buildscripts ist eine Datei _env-only.sh. Diese 
Datei definiert das target für das der mingw übersetzen soll. Über 
folgende Zeile:

export target=arm-elf

Die newlib wird mit dem Script 06-build-newlib.sh für ARM Prozessoren 
übersetzt. Siehe folgenden Auszug:

../$NEWLIB_SRC/configure \
  --target=$target --prefix=$prefix \
  --enable-interwork --enable-multilib \
  --disable-newlib-supplied-syscalls \
  || { echo "Error configuring newlib"; exit 1; }

$MAKE || { echo "Error building newlib"; exit 1; }
$MAKE install || { echo "Error installing newlib"; exit 1; }

Das Interessante dabei ist, daß die Variable $target benutzt wird, um 
das Zieltarget festzulegen, und das ist laut _env-only.sh 
target=arm-elf. Wenn ich also Yagarto mit dem mingw übersetze, kommt 
kein x86 Code sondern ARM Code heraus. Die Übersetzung läuft dabei unter 
der Umgebung MSYS ab, und schon der mingw wird als Crosscompiler 
verwendet.

von Sven W. (woehlb)


Lesenswert?

Genau genommen ist der mingw der Crosscompiler und nicht der 
arm-elf-gcc.exe.

von (prx) A. K. (prx)


Lesenswert?

Wenn du meinst...

Ich geb's jedenfalls auf.

von Sven W. (woehlb)


Lesenswert?

@ A.K.

Trotzdem Danke, gute Nacht!

von 900ss (900ss)


Lesenswert?

Sven Woehlbier schrieb:
> Wenn ich also Yagarto mit dem mingw übersetze, kommt
> kein x86 Code sondern ARM Code heraus

?

Sven Woehlbier schrieb:
> Genau genommen ist der mingw der Crosscompiler und nicht der
> arm-elf-gcc.exe.

Du hast entweder viel zuviel Alkohol getrunken oder verstehst das alles 
noch nicht wirklich. ;-)
Wenn du YAGARTO mit MinGW übersetzt, dann bekommst du eine Toolchain 
(den Crosscompiler + BinUtils + ...). Code für den ARM wird dabei kaum 
erzeugt.

A. K. schrieb:
> Aber du schreibst hier in einem
> eigenen Sven-Deutsch, dass sich anderen nur schwer erschliesst.

Ich verstehe ihn auch nicht.

von Sven W. (woehlb)


Lesenswert?

@ 900ss D.:
OK, wahrscheinlich habe ich wirklich zu ungenau formuliert.

--

Ich habe mir den Build-Prozeß für Yagarto nochmal angesehen. Mit dem 
mingw wird zunächst das Toolchain erzeugt. Somit besteht das Toolchain 
natürlich aus x86-Code. Muß ja auch so sein, da es auf dem PC laufen 
soll. Für die Compilierung der Newlib wird aber dann das Toolchain 
selbst benutzt, so daß die Newlib aus ARM-Code besteht. Auch das ist 
logisch, denn die Bibliothek wird ja mit den ARM-Programmen gelinkt, so 
daß deren Code Bestandteil des erzeugten Binary- oder Hex-Files wird, 
das auf dem ARM laufen soll.

Ich bin aber mittlerweile zum Sourcery G++ Lite gewechselt. Damit die 
Auswahl der korrekten Newlib bei der Übersetzung sicher gestellt ist, 
habe ich unter Codeblocks bei den "Toolchain Executables->Linker for 
dynamics libs" das GCC-Frontend arm-none-eabi-gcc.exe angegeben. Als 
Linker search directories habe ich folgende Verzeichnisse ausgewählt:

C:\Programme\CodeSourcery\Sourcery G++ Lite\arm-none-eabi\lib
C:\Programme\CodeSourcery\Sourcery G++ Lite\lib

Somit werden die korrekten libc und libgcc jetzt ausgewählt. Außerdem 
habe ich mir die STM32F10x_StdPeriph_Lib_V3.1.2 von ST heruntergeladen. 
Aus dem Verzeichnis 
..\STM32F10x_StdPeriph_Lib_V3.1.2\Libraries\CMSIS\Core\CM3\startup\gcc 
benutzte ich startup_stm32f10x_md.s als Startup-Code. Als Link-File 
kommt stm32f10x_flash_extsram.ld aus dem Verzeichnis 
..\STM32F10x_StdPeriph_Lib_V3.1.2\Project\Template\RIDE zum Einsatz, 
sollte am besten zum Sourcery G++ Lite passen. Auf diese Weise kann ich 
jetzt jedenfalls mein Programm fehlerlos übersetzen. Hoffentlich ist es 
auch auf meinem STM32 lauffähig, aber dafür muß ich erst noch meinen 
neuen JLINK-EDU integrieren.

Warum diese Verfahrensweise mit Yagarto nicht funktioniert hat, kann ich 
nicht mit Sicherheit sagen. Der entscheidende Unterschied bei beiden 
Toolchains dürfte aber das verwendete Linking-Format (ELF bei Yagarto; 
EABI bei Sourcery G++ Lite) sein. Da EABI einige Vorteile bieten soll, 
vermute ich die Ursache in diesem Bereich. Nach den Unterschieden 
zwischen beiden Formaten muß ich aber nocheinmal genauer recherchieren.

Ansonsten benutze ich jetzt den JLINK-EDU, damit hat sich auch die 
Comppilierung von Codeblocks mit dem Openocd-Plugin erledigt. Als 
Ausgangspunkt benutzte ich zur Zeit den Wizard für ein 
Consolen-Programm.
Als Grundlage habe ich mich dabei nach der folgenden Seite gerichtet:

http://www-user.tu-chemnitz.de/~neufr/codeblocks/crossgnuarm.php

Aber nur grundsätzlich, eins zu eins anwenden geht nicht, da die 
Beschreibung für den ARM7 und für ein Codeblocks unter Linux gilt.

von 900ss (900ss)


Lesenswert?

Fast hast du es jetzt :-)
Mit der Codesourcery Toolchain.... Die verwende ich auch und mein Linker 
erzeugt ELF-Files. Du solltest nochmal prüfen wofür ELF bzw. (E)ABI 
stehen.

von Martin T. (mthomas) (Moderator) Benutzerseite


Lesenswert?

Sven Woehlbier schrieb:
>...
> Für die Compilierung der Newlib wird aber dann das Toolchain
> selbst benutzt, so daß die Newlib aus ARM-Code besteht. Auch das ist
> logisch, denn die Bibliothek wird ja mit den ARM-Programmen gelinkt, so
> daß deren Code Bestandteil des erzeugten Binary- oder Hex-Files wird,
> das auf dem ARM laufen soll.

So in der Art, jedoch wird meist nicht nur eine "Newlib" gebaut, sondern 
mehrere für verschiedene ARM-cores (es gibt mehrere Dateien mit Namen 
libc.a in den meisten Binärpaketen wie Yagarto, CS G++ lite, ehedem 
WinARM etc.). Je nach verwendeten Mulitlib-Einstellungen z.B. für arm, 
thumb, thumb-interwork. Es gibt noch mehr Möglichkeiten (z.B. 
big-endian, little-endian).

> Ich bin aber mittlerweile zum Sourcery G++ Lite gewechselt. Damit die
> Auswahl der korrekten Newlib bei der Übersetzung sicher gestellt ist,
> habe ich unter Codeblocks bei den "Toolchain Executables->Linker for
> dynamics libs" das GCC-Frontend arm-none-eabi-gcc.exe angegeben. Als
> Linker search directories habe ich folgende Verzeichnisse ausgewählt:
>
> C:\Programme\CodeSourcery\Sourcery G++ Lite\arm-none-eabi\lib
> C:\Programme\CodeSourcery\Sourcery G++ Lite\lib

Die Pfade muss man eigentlich nirgends angeben, wenn man das Frontend 
(arm-*-gcc) nutzt. Das kann intern den Linker mit den richtigen Optionen 
aufrufen, auch denen zur Auswahl der passenden libgcc und libc, sofern 
man die von A.K. oben gennanten Option nicht nur beim Compilieren, 
sondern auch beim Linken mitgibt. Nie den Linker (arm-*-ld) direkt 
aufrufen, das gibt nur Verdruss.

> Somit werden die korrekten libc und libgcc jetzt ausgewählt.

Das macht die Toolchain, wenn richtig verwendet, auch selbst. Ich nutze 
ebenfalls meist CS G++ lite und musste dieses Pfadgebastel nie machen. 
Linker hier jedoch ausschliesslich "indirekt" über das Frontend 
aufgerufen.

>...
> Auf diese Weise kann ich
> jetzt jedenfalls mein Programm fehlerlos übersetzen.

Das ist doch schon mal was.

> Hoffentlich ist es
> auch auf meinem STM32 lauffähig, aber dafür muß ich erst noch meinen
> neuen JLINK-EDU integrieren.

Man kann den Maschinencode auch mittels STM32 Bootloader/UART/RS232 
übertragen. Aktivierung Bootloader siehe STM32 Manual. PC-Software siehe 
st.com/Flash Loader Demonstrator o.ä.

> Warum diese Verfahrensweise mit Yagarto nicht funktioniert hat, kann ich
> nicht mit Sicherheit sagen.

Nach meinen Informationen (=nicht selbst ausprobiert), sind neuere 
Versionen von Yagarto samt multilib-Einstellungen so gebaut, das auch 
Code für ARMv7/thumb2 erzeugt werden kann.

> Der entscheidende Unterschied bei beiden
> Toolchains dürfte aber das verwendete Linking-Format (ELF bei Yagarto;
> EABI bei Sourcery G++ Lite) sein.

Nicht ganz. Streiche ELF, setzte (old)ABI. Der Ausdruck "Linking-Format" 
ist mir bisher nicht begegnet.

> Da EABI einige Vorteile bieten soll,
> vermute ich die Ursache in diesem Bereich. Nach den Unterschieden
> zwischen beiden Formaten muß ich aber nocheinmal genauer recherchieren.

EABI soll u.a. einen Standard für object-code schaffen, so dass man mit 
Tools verschiedener Hersteller erzeugten object-code zusammenlinken 
kann. Mehr dazu kann aber gut bei arm.com "recherchiert" werden.

von Sven W. (woehlb)


Lesenswert?

@Martin Thomas:
>So in der Art, jedoch wird meist nicht nur eine "Newlib" gebaut, sondern
>mehrere für verschiedene ARM-cores (es gibt mehrere Dateien mit Namen
>libc.a in den meisten Binärpaketen wie Yagarto, CS G++ lite, ehedem
>WinARM etc.). Je nach verwendeten Mulitlib-Einstellungen z.B. für arm,
>thumb, thumb-interwork. Es gibt noch mehr Möglichkeiten (z.B.
>big-endian, little-endian).

Aus dem Grund habe ich auch die Übersetzung von Yagarto ohne die Option 
--enable-interwork abgebrochen. Denn wenn man mal die Pfade von Yagarto 
durchforstet, sieht es so aus als ob alle notwendigen Versionen der 
Newlib vorhanden sind. Außerdem gibt es ohne --enable-interwork etliche 
Fehlermeldungen im Buildprozeß.

@900ss D./Martin Thomas:
>Fast hast du es jetzt :-)
>Mit der Codesourcery Toolchain.... Die verwende ich auch und mein Linker
>erzeugt ELF-Files. Du solltest nochmal prüfen wofür ELF bzw. (E)ABI
>stehen.

Wie oben gesagt, in die Richtung muß ich nochmal genauer recherchieren.

@Martin Thomas:
>Nicht ganz. Streiche ELF, setzte (old)ABI. Der Ausdruck "Linking-Format"
>ist mir bisher nicht begegnet.

Der Begriff Linking-Format stammt von einer englischsprachigen Seite. 
Frage mich jetzt bloß nicht welche. Was wäre für ELF und EABI der 
gängige Begriff?

von 900ss (900ss)


Lesenswert?

Sven Woehlbier schrieb:
> Was wäre für ELF und EABI der
> gängige Begriff?

ELF: Executable and Linking Format
EABI: Embedded Application Binary Interface

von Sven W. (woehlb)


Angehängte Dateien:

Lesenswert?

OK, ich bin ja jetzt soweit gewesen, daß ich mein Porgramm fehlerlos 
übersetzten kann. Im Moment benutzte ich das Linker-Script im Anhang. 
Dazu habe ich aber noch 2 Fragen.

1) Stackstartadresse:
Der Stack muß am Ende des RAM beginnen, da seine Größe in Richtung der 
fallenden Adressen ausgedehnt wird. Im Moment habe ich die 
Stackstartadresse auf die höchste RAM-Adresse gesetzt.

_estack = 0x20004FFF;  //RAM-Size=20k

Braucht der JLink-EDU einen RAM-Bereich zum Debuggen? Wenn ja wie groß 
muß dieser sein? Befindet sich dieser RAM-Bereich am Ende des RAM's, muß 
_estack ja auf eine kleinere Adresse gesetzt werden.

2) Unbenutzte Funktionen entfernen:
Entsprechend dem folgenden Artikel würde ich gern unbenutzte Funktionen 
die im Quellcode noch vorhanden sind, im Hex- bzw. Bin-File entfernen.

http://www.mikrocontroller.net/articles/GCC:_unbenutzte_Funktionen_entfernen

Die Compiler- und Linker-Optionen aus diesem Artikel habe ich bereits 
gesetzt. Ich bin mir aber unsicher wie ich das Linker-Script anpassen 
muß. Welche Speicherbereiche entsprechen denen im angeführten Artikel?

von Sven W. (woehlb)


Lesenswert?

Noch eine Frage!

Muß ich für den Speicherbereich, den der JLink-EDU eventuell für das 
Debuggen benötigt, im Linker-Script einen eigenen Speicherbereich 
vereinbaren? Wenn ja wie?

von Sven W. (woehlb)


Angehängte Dateien:

Lesenswert?

Ich habe mir eine Variante eines Linker-Scripts für das Entfernen von 
unbenutzten Funktionen jetzt selbst zusammengesucht. Das aktualisierte 
Linker-Script findet Ihr im Anhang. Wie im oben genannten Artikel habe 
ich auch die Compiler- und Linker-Optionen gesetzt.

Das Problem ist nur, das Compilat verkleinert sich nicht, obwohl ich 
definitiv etliche Funktionen der eingebundenen STM32-Bibliothek nicht 
benutze.

Was mache ich falsch?

von 900ss (900ss)


Lesenswert?

Sven Woehlbier schrieb:
> Was mache ich falsch?

Die nicht benutzten Funktionen aus dem Sourcecode entfernen. Wenn du sie 
eh nicht brauchst, was sollen sie dort?
Die entsprechenden Optionen sind so überflüssig wie eine Warze unterm 
Fuß. Meine Meinung.

Wenn du möchstest das der Linker aus der ST-Lib nur die Funktionen 
nimmt, die du auch nutzt, dann bau eine ECHTE Library daraus und linke 
sie dazu. Dann sorgt der Linker dafür dass es klappt.

Der J-Link benötigt kein Extraram aus deinem Controller. Wäre ja noch 
schöner :-) Ansonsten würdest du darauf einen Hinweis in dem guten 
Handbuch finden.

von Sven W. (woehlb)


Lesenswert?

Aus der ST-Lib eine echte Biliothek bauen, gute Idee. Was mache ich aber 
mit nicht benötigten reentrant Funktionen auf die die Newlib aufbaut?

OK, ich könnte natürlich immer nur die Funktionen im Quellcode 
bereitstellen, die wirklich benötigt werden. Es wäre mir aber lieber, 
wenn ich meine Datei syscalls.c, die die reentrant Funktionen enthält, 
immer wieder verwenden könnte.

von Sven W. (woehlb)


Lesenswert?

Ich habe rausgefunden, was noch zur Entfernung der nicht benötigten 
Funktionen gefehlt hat. Aus der im Artikel

http://www.mikrocontroller.net/articles/GCC:_unbenutzte_Funktionen_entfernen

verwendeten Linker-Option "--gc-sections" muß "-Wl,--gc-sections" 
werden. Siehe hier:

http://gcc.gnu.org/onlinedocs/gcc-4.3.4/gnat_ugn_unw/Compilation-options.html

von Sven W. (woehlb)


Lesenswert?

Leider scheint sich, der entsprechende Artikel nicht modifizieren zu 
lassen.

von 900ss (900ss)


Lesenswert?

Sven Woehlbier schrieb:
> Aus der ST-Lib eine echte Biliothek bauen, gute Idee. Was mache ich aber
> mit nicht benötigten reentrant Funktionen auf die die Newlib aufbaut?

Du meinst sicher die Funktionen in syscalls.c. In der ST-Lib ist nichts, 
was du für die newlib brauchst. Also aus der ST-Lib eine ECHTE Lib zu 
machen ergibt Sinn.
Und die syscalls.c enthält ein paar kurze übersichtliche Funktionen. 
Wenn du diese Datei immer komplett dazulinkst, wird dir das kaum das 
Flash sprengen. Ich bin mir ziemlich sicher, dass du durch Änderung 
eigener Routinen mehr sparen kannst ;-)
Außerdem, wenn dein Speicher in dem STM32 so eng ist, dass es reicht, 
wenn du die syscalls.c kürzt, dann hast du entweder zu verschwenderisch 
kodiert oder einen zu kleinen Controller genommen ;-)

von 900ss (900ss)


Lesenswert?

Sven Woehlbier schrieb:
> Leider scheint sich, der entsprechende Artikel nicht modifizieren zu
> lassen.

Die Beschreibung dort ist RICHTIG. Der Linker braucht die Option 
"--gc-sections". Damit der Compiler diese an den Linker weiterreicht 
mußt Du beim COMPILER "-Wl,--gc-sections" angeben.

Also lass den Artikel so oder ergänze mit Hinweis auf die 
Compileroption.

von Martin T. (mthomas) (Moderator) Benutzerseite


Lesenswert?

Linker-Script sieht ganz brauchbar aus. Würde noch ein ENTRY reinsetzen, 
sollte aber wegen KEEP der Vektoren nicht notwendig sein. Wenn man eh 
den Stack an der höchsten RAM Adresse anfangen lässt, kann per origin() 
und length() die Adresse vom Linker auch aus den Memory-Informationen 
errechnet werden. Sind die Compiler- und Linker-Optionen wirklich 
richtig gesetzt? Alles mit den geänderten Compiler-optionen nochmal neu 
compiliert und gelinkt (make clean all)? --gc-sections bei Linker-Aufruf 
über Frontend mit -Wl übergeben? Was steht im map-file (insbes. bei 
Discarded input sections)?
Mglw. findet sich darin etwas Zusatzinformation: 
http://www.siwawi.arubi.uni-kl.de/avr_projects/arm_projects/arm_memcards/index.html#stm32_memcard 
Es sollte darin alles für unused-code-removal eingerichtet sein. Ich 
teile 900ss D.s Meinung betr. der Funktionalität function-, 
data-sections u. gc-sections nicht (und auch nicht die zu OpenOCD). Aber 
ist auch egal, jeder wie er mag. Betr. J-LINK-EDU kann ich nichts 
beitragen, habe keines. Mein J-Link ist noch aus der 
vor-AT91SAM7S-Zeit,lag aber lustigerweise einem AT91SAM7S-EK bei als es 
noch kein SAM-ICEs gab.

EDIT: hoppla, da waren ja schon einige schneller. Na ja - vielleicht 
dennoch ein paar nützliche Schnippsel in meinem Geschreibsel.

von Sven W. (woehlb)


Lesenswert?

Die Option "-Wl,--gc-sections " ist bei mir notwendig, da ich nicht den 
Linker direkt sondern über das Compiler Frontend arm-elf-gcc aufrufe. 
Der Grund dafür ist, daß arm-elf-gcc die richtige Version der Newlib 
auswählt.

von 900ss (900ss)


Lesenswert?

Martin Thomas schrieb:
> und auch nicht die zu OpenOCD

OT: Schrieb ich hier etwas zu meinem Lieblingstool OpenOCD? ;-)

Wo siehst du denn die Vorteile, wenn man einen J-Link für 65Euro bekommt 
und für einen JTAG-Debugger von Amontec 49,00 Euro oder Olimex 39,00 
Euro bezahlen muß?
Und dann muß man sich dieses OOCD-Zeugs auch noch selber zusammen 
kompilieren. Wenn ich ein Auto brauche, dann kaufe ich es 
funktionsfertig und nicht als Bausatz (obwohl es das ja gibt ;-)). Das 
wäre aber nicht soo schlimm wenn OOCD nicht elendig langsam wäre 
gegenüber dem J-Link und die Parametrisierung sich einfacher gestalten 
würde (was das allerschlimmste ist). Und die Doku dazu ist auch nicht 
das, was man brauchbar nennt. In meinen Augen ist das was für die 
Geiz-Ist-Geil-Fraktion oder Schüler, die sich den Debugger mit dem 
FTDI-Chip selber bauen um wirklich noch Taschengeld für die Disco zu 
haben ;-)

So, OT Ende. Deine Argumente für OOCD würden mich schon interessieren 
(auch wenn es hier OT ist). Danach können wir ja wieder zum Thema kommen 
:-)
Schönen Abend noch.

von Sven W. (woehlb)


Lesenswert?

Ich habe versucht im Linker-Script ENTRY anzugeben.

ENTRY(.isr_vector)

Dann erhalt ich aber die folgende Fehlermeldung.

c:/programme/codesourcery/sourcery g++ 
lite/bin/../lib/gcc/arm-none-eabi/4.4.1/../../../../arm-none-eabi/bin/ld 
.exe:  warning: cannot find entry symbol .isr_vector; defaulting to 
0800010c

Wie muß der ENTRY-Eintrag aussehen, und an welcher Stelle muß er stehen?

von 900ss (900ss)


Lesenswert?

Sven Woehlbier schrieb:
> Die Option "-Wl,--gc-sections " ist bei mir notwendig, da ich nicht den
> Linker direkt sondern über das Compiler Frontend arm-elf-gcc aufrufe.

Ja, so soll es ja auch sein. Aber -Wl ist nur beim Compiler nötig um ihm 
zu sagen, er soll die darauf folgende Option an den Linker 
weiterreichen. Beim Linker wäre -Wl nicht nötig. Und nichts anderes 
steht auf der GNU Doc Seite.

von 900ss (900ss)


Lesenswert?

Sven Woehlbier schrieb:
> Wie muß der ENTRY-Eintrag aussehen, und an welcher Stelle muß er stehen?

Guckst hier:
http://sourceware.org/binutils/docs-2.20/ld/index.html
unter 3.4.1

von Sven W. (woehlb)


Lesenswert?

Ok begriffen!

Zum Thema JTAG-Interface:

Den direkten Vergleich zwischen Olimex-ARM-OCD und JLINK habe ich noch 
nicht. Aber  ich stimme  900ss D. soweit zu, daß die Konfiguration von 
Openocd eine Wissenschaft für sich ist. Ich konnte zwar flashen und 
debuggen, habe es aber nie hinbekommen, auch Interruptserviceroutinen zu 
debuggen. Darauf wie das geht, habe ich hier im Forum damals leider 
keine Antwort bekommen. Deshalb bin ich jetzt privat zum JLink-EDU 
gewechselt.

Allerdings hat das JLink einen Hacken. In der Firma haben wir ein 
älteres JLink, und das unterstützt keine STM32. Diese uC werden erst ab 
einer bestimmten Hardwareversion des JLink's unterstützt. Damit ist das 
JLink nicht voll unabhängig vom verwendeten uC. Dieser Punkt gefällt mir 
am JLink nicht.

von 900ss (900ss)


Lesenswert?

Sven Woehlbier schrieb:
> Diese uC werden erst ab
> einer bestimmten Hardwareversion des JLink's unterstützt

Schon mal bei Segger gefragt deswegen?

Das ist ja wie im Chat hier heute ;-)

von Sven W. (woehlb)


Lesenswert?

Diese Information stammt von Segger.

von Sven W. (woehlb)


Lesenswert?

Aber nochmal zurück zum Punkt ENTRY.

Ich habe Linker-Scripte mit diesem Eintrag gefunden.

ENTRY(_start)

Das Symbol _start ist aber nicht im Linker-Script enthalten. Woher kommt 
das Symbol?

Wie muß das ENTRY in meinem Linker-Script aussehen?

von 900ss (900ss)


Lesenswert?

Aus einem File (Sourcecode).

von Sven W. (woehlb)


Angehängte Dateien:

Lesenswert?

Hier mal nochmal mein aktuelles Linker-Script.

von Sven W. (woehlb)


Angehängte Dateien:

Lesenswert?

OK, das entsprechende Symbol müßte also im Startup-Code enthalten sein. 
Welches wäre das (siehe Anhang)?

So?:
ENTRY(Reset_Handler)

von Sven W. (woehlb)


Lesenswert?

Anscheinend stimmt das. Siehe hier:

http://embdev.net/topic/150574

Vielen Dank, für die Hilfe! Für heute Abend verabschiede ich mich.

von Sven W. (woehlb)


Lesenswert?

@ Martin Thomas:

Kannst Du mir bitte ein Beispiel geben, wie man die höchste Stackadresse 
aus Stackstartadresse und Stackgröße berechnen lassen kann?

von Sven W. (woehlb)


Lesenswert?

Richtig so (Linker-Script im Anhang)?

_estack = ORIGIN(RAM) + LENGTH(RAM)

von Sven W. (woehlb)


Angehängte Dateien:

Lesenswert?

Hier noch das komplette Linker-Script.

von Sven W. (woehlb)


Lesenswert?

Anscheinend hat noch ein abschließendes Semikolon gefehlt. Stimmt aber 
die berechnete Adresse?

_estack = ORIGIN(RAM) + LENGTH(RAM);

von Sven W. (woehlb)


Lesenswert?

@900ss D.:

Nochmal kurz eine Bemerkung zu den vom JLink-EDU unterstützten 
Mikrocontrollern. Normalerweise sind die unterstützten Mikrocontroller 
nicht von der Hardwareversion des JLink-EDU abhängig. Die ARM-Cortex-M 
bilden da aber eine Ausnahme.

Siehe hier:
http://www.segger2.com/index.php?page=Thread&threadID=496

Bin mittlerweile sehr zufrieden mit dem JLink-EDU. Es ist unter Eclipse 
einfach zu konfigurieren, und ich kann zuverlässig mit arbeiten.

von Ulrich P. (uprinz)


Lesenswert?

Hi!

Klasse Arbeit hier, Hut ab.
Habe beim Studium dieses Threads einiges über Linker Scripts gelernt und 
auch umgesetzt bekommen.

Nun habe ich nur noch ein einziges kleines Problem.

Mein System soll einige Interrupts zur Laufzeit registrieren und daher 
muss die im Flash vorhandene .isr_vector Tabelle ins RAM umkopiert 
werden:
1
    .text :
2
    { . = ALIGN(4); _svect = .;
3
        KEEP(*(.isr_vector))
4
        _evect = .;
5
        *(.text .text.* .gnu.linkonce.t.*) 
6
        *(.rodata*) . = ALIGN(4); _etext = .;
7
        _sidata = _etext; 
8
    } > FLASH0

Da ich diese Tabelle ganz am Anfang vom RAM haben will, habe ich 
folgende Section mit eingefügt:
1
    .vtable :
2
    { . = ALIGN(4); _vtable = .;
3
      KEEP(*(.vtable))
4
      _evtable = .; 
5
    } > SRAM0
6
    
7
    .data : AT (_sidata)
8
    { . = ALIGN(4); PROVIDE(_sdata = .); 
9
    u.s.w.

Leider funktioniert das nur fast, denn im ausgegebenen .bin und .hex 
File wird nun der komplette Speicher zwischen Flash (hier 0x00000000) 
und RAM+.vtable (0x200001fe) initialisiert, ist also ein 0.5MB großes 
BIN File.

Ich bekomme es einfach nicht hin, dass diese Section zwingend erzeugt 
aber nicht initialisiert wird.

Danke für etwas Hilfe
Gruß, Ulrich

von Ulrich P. (uprinz)


Lesenswert?

Ok, hat sich erledigt.

.vtable (NOLOAD):

hat das Problem beseitigt.

Gruß, Ulrich

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
Noch kein Account? Hier anmelden.