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.
Beruflich nutze ich auch Crossworks, nur privat ist mir auch die Personal License zu teuer. Ansonsten, trotzdem Danke!
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 |
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?
Was heißt das überhaupt genau, wenn Code mit der Option "--enable-interwork " übersetzt wird?
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?
Dass Interworking bei einer CPU, die kein Interworking kann und auch keines benötigt, Blödsinn ist. CPU Auswahl: -mcpu=cortex-m3 -mthumb
Heißt das, daß ich Yagarto ohne die Option "--enable-interwork" neu übersetzen muß?
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.
Das Yagarto mit interworking übersetzt wurde, kann natürlich daran liegen, daß der Schwerpunkt in der Anwendung immer noch bei den ARM7TDMI liegt.
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!
In Bezug auf Deine letze Bemerkung. Ist schon klar, deshalb ist es ja ein Crosscompiler.
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.
Genau genommen ist der mingw der Crosscompiler und nicht der arm-elf-gcc.exe.
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.
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
Leider scheint sich, der entsprechende Artikel nicht modifizieren zu lassen.
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.
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
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?
OK, das entsprechende Symbol müßte also im Startup-Code enthalten sein. Welches wäre das (siehe Anhang)? So?: ENTRY(Reset_Handler)
Anscheinend stimmt das. Siehe hier: http://embdev.net/topic/150574 Vielen Dank, für die Hilfe! Für heute Abend verabschiede ich mich.
@ Martin Thomas: Kannst Du mir bitte ein Beispiel geben, wie man die höchste Stackadresse aus Stackstartadresse und Stackgröße berechnen lassen kann?
Anscheinend hat noch ein abschließendes Semikolon gefehlt. Stimmt aber die berechnete Adresse? _estack = ORIGIN(RAM) + LENGTH(RAM);
@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
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.