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?
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.
@ 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.
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 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.
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:
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.
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?
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?
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?
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.
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.
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.
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).
@ 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!
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.
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.
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.
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.
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.
@ 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.
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.
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.
@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?
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
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?
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?
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?
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.
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.
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 ;-)
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.
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.
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.
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.
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?
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.
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.
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 ;-)
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?
@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.
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