Von einem Kollegen habe ich einen selbst compilierten GCC welcher
ehemals notgedrungen von Cortex-A auf Cortex-M umgebogen wurde. Es gibt
nur noch ein EXE von 2006 welche nie weiter gepflegt wurde. Die
Anpassungen an der Runtime sind fraglich. Konsolausgaben landen auf
einem Breakpoint, es gibt kein malloc usw. Deshalb möchte ich meine
alten Projekte auf die offiziell von ARM gepflegte aktuelle GCC Version
umstellen. Ich verwende derzeit noch keine IDE, dafür aber die alten
selbst gemachten Startup Quellen und Linker Skripts. Letzeres mit
möglichst kleinen Änderungen.
Projekt 1 compiliert (und funktioniert auch alles)
Projekt 2 linkt nicht wegen fehlendem memcpy
Projekt 3 linkt nicht wegen fehlendem __eabi_uldivmod
Wenn ich das korrekt annehme, sind beides Fehler im Zusammenhang mit
nicht korrekt gelinkter Runtime Bibliotheks-Archive welche Bestandteil
von gcc-arm-none-eabi sein sollten. Zumindest die Verwendung von memcpy
ist plausibel ohne die Notwendigkeit in den Quellen aktuell genauer zu
untersuchen. Projekt 2 krieg ich nun gelinkt, wenn ich folgende Dinge
gleichzeitig mache:
1) Für einen STM32F103 und F107 nehme ich an, daß die
Laufzeitbibliotheken aus dem Verzeichniss ../v7-m/ für Cortex-M3 benutzt
werden sollten.
2) Diese Verzeichnisse finde ich gleich an zwei verschiedenen Stellen
der Installation. Dazu habe ich im Linker Skript folgende Suchpfade
eingerichtet:
Warum die Dateien auf zwei verschiedene Verzeichnisse verteilt sind (was
den Suchpfad im Linkerskript auch noch versionsabhängig macht) verstehe
ich hier nicht. Ich hoffe aber, nicht versehentlich die Archive vom GCC
für das Linux System (also gcc ohne arm-none-eabi) zu verwenden.
3) Wenn ich die Readme richtig verstehe, hat ARM eine optimierte Version
der Runtime newlib mit dem modifizierten Dateinamen ..._nano verfügbar.
Um diesen zu benutzen, habe ich im Linker Aufruf den Parameter
-specs=nano.specs übergeben (was nutzlos war). Um ein
projektunabhängiges Linkerskript zu bekommen, habe ich die zu linkenden
Objektfiles ebenfalls in der Kommandozeile übergeben. Ich weis, dass
dies auch im Linkerskript gehen würde.
4) Die Runtime lib _nano.a muß in der Liste der zu linkenden Objekt
Files angegeben werden, während die ohne _nano auch ohne explizite
Benennung als Linker Input nachgefragt werden. Eigentlich habe ich
gedacht, daß diese nur alternativ verwendet werden? Ist da der Parameter
-specs=nano.specs nicht wie beabsichtigt verwendet ?
5) Um zu Linken, muss ich nun die libc.a, libm.a, libgcc.a und
libc_nano.a in das Quellverzeichniss des Projekts kopieren. Die im
Linkerskript angelegten Suchpfad scheinen also nicht korrekt zu
funktionieren? Erst libgcc_nano.a linkt memcpy und das auch ohne dass
-specs=nano.specs verwendet wird.
Summa Summarum scheint das beschriebene Vorgehen nicht wirklich korrekt
und führt bei Projekt 3 auch nicht zum Erfolg.
Wenn du den neuen GCC (wobei 6.3.1 jetzt nicht wirklich neu ist)
verwendest brauchst du dich im Linkerscript nicht um irgendwelche Pfade
kümmern. Der Compiler findet die schon selber abhängig von der gewählten
Architektur (-mcpu=cortex-m3).
Auch die Standardbibliotheken wie libc und libgcc linkt der GCC
automatisch dazu wenn man ihm das nicht explizit untersagt (-nostdlib).
Ich hab sowas
https://embedds.com/programming-stm32-discovery-using-gnu-tools-linker-script/
als Grundlage für unser aktuelles Linkerscript verwendet.
Matthias
libc.a libgcc.a bringen leider eine Fehlermeldung dass der Linker sie
nicht findet. Erst wenn ich sie im Projektverzeichniss habe wird
gelinkt. Mit -nostdlib kann ich die im Projektverzeichniss löschen und
es geht trotzdem. Lösche ich dann aber noch den Pfad, kommt wieder ein
Linkfehler.
Die 6.3.1 ist leider auch eine ältere Version aus dem Ubuntu Debian
Paket welches mit sudo apt-get installiert wurde. Leider habe ich bei
der Installation des Tarballs von ARM noch einige weitere Probleme die
ich gerade nicht verstehe. Daher vorsichtshalber mal das ältere Paket
aus dem Ubuntu Archiv.
Μαtthias W. schrieb:> Wenn du den neuen GCC verwendest brauchst du dich im Linkerscript> nicht um irgendwelche Pfade kümmern.
Von wegen neuer GCC: mit dem Debian-Paket für den GCC-7 war es auch
schon so einfach und dein Ubuntu-Paket wird nicht so viel anders sein.
Installieren und fertig. Keine Pfade irgendwo anpassen, keine lib extra
angeben oder gar kopieren, weil
> Der Compiler findet die schon selber abhängig von der gewählten> Architektur (-mcpu=cortex-m3).
Das funktioniert aber viel besser/einfacher, wenn der gcc selbst den
Linker aufruft. Ich würde als erstes den Aufruf vom arm-none-eabi-ld und
das -nostdlib ausbauen. Der gcc bekommt stattdessen ein -o für das
fertige Programm. Die restlichen Fehler sollten sich dann ohne Tricks
beheben lassen.
Den Linker nicht direkt aufrufen, sondern bitte über den gcc. (also -ld
durch -gcc ersetzen). Der kümmert sich dann automatisch um die Pfade
wenn man die CPU wie beim Compilieren mit angibt. ("-mcpu=cortex-3m").
Den Linkerargumente "-Wl," voranstellen. Z.b. aus "-M=map.txt" wird
"-Wl,-M=map".
-
> Erwischt das Makefile auch wirklich den richtigen Compiler?
Bin jetzt wenigstens etwas in Version vorgerrückt auf das was bei Ubuntu
"aktuell" sein soll. Hier der Output im Erfolgsfall:
Entfernt man libc_nano.a aus der Liste des Linker Inputs (oder dem
Quellverzeichniss), erscheint trotz korrektem Suchpfad im Linkerfile und
dort vorhandenen Standardbibliotheken
In main.c:99 wird strcpy tatsächlich berechtigt verwendet um einen
String in den UART Sendepuffer abzulegen welcher sodann im Hintergrund
über INT verschickt wird:
1
{strcpy((char*)PcTxBuf,"Num Flow Temp Volt iTmp Leak-Rpts Posi Flux Supl Torq Sped Baro Sink Time Exor\n\r");
Entfernt man nun libc.a zusätzlich aus dem Quellverzeichniss, so ändert
sich der Fehler (obwohl der Pfad im Linkerskript stimmt) auf
au weia - es wird immer schlimmer. Eine Section .data gibts zwar, aber
.init LMA habe ich im ganzen Linkfile nicht angelegt. Probiert der jetzt
vielleicht was anders als meinen eigenen Startup zu nehmen ?
J. V. schrieb:> Eine Section .data gibts zwar, aber> .init LMA habe ich im ganzen Linkfile nicht angelegt.
Linker sind hochspezialisierte Sonderlinge, und eine verständliche
Ausdrucksweise gehört nicht zu deren Stärken.
Was der dir vielleicht sagen will, ist, daß der gerne eine init-Section
hätte.
Oliver
Oliver S. schrieb:> Was der dir vielleicht sagen will, ist, daß der gerne eine init-Section> hätte.
Das Linkerscript bestätigt das. .init taucht nirgends auf.
@TO
Mach mal nach *(.glue_7t) ein KEEP (*(.init)) rein.
Matthias
Μαtthias W. schrieb:> Mach mal nach *(.glue_7t) ein KEEP (*(.init)) rein.
Resultat bleibt gleich aber der Name der section ändert sich von init in
fini:
section .fini LMA [00000000080045a0,00000000080045a3] overlaps section
.data LMA [00000000080045a0,00000000080045b3]
Ich hatte mir letztens mal die Cube-IDE installiert.
Da waren für viele STM Prozessoren die benötigten Architektur abhängigen
Dateien dabei.
Ich habe mir dann mit der IDE ein Projekt gezimmert. Danach alles, was
benötigt wurde rüberkopiert. Einen Standard ARM-Compiler noch dazu (oder
den aus der IDE), und alles in Makefiles verpackt.
War einen Tag Arbeit, aber nun kann ich Remote compileren, ohne IDE.
Evtl geht dieser Weg ja auch für die älteren Prozessoren.
Und man hat die aktuelle STM HAL-Implementation.
J. V. schrieb:> zumindest für die vom Linker erfundenen .init und .fini hilft das nicht.
Der linker erfindet eigentlich gar nichts. Woher .init und .fini kommen,
erzählt dir auf Nachfrage google.
Kurzfassung: die brauchts bei deinem System halt einfach.
Oliver
Das indirekte Aufrufen des Linkers funktioniert auch bei Projekt 3
welches damit prompt korrekt gelinkt wird. Alle Suchpfade im
Linkerskript und alle Runtime Lib-Archivdateien in den Verzeichnissen
der Projektquellen können dabei gelöscht werden. Weil der Linker den
Suchpfad trotz Pfadangabe nicht schnallt, haben Andere schon muckiert
(zufällig genauso mit __eabi_uldivmod):
https://answers.launchpad.net/gcc-arm-embedded/+question/693328
Die Anwort hier ist genauso wenig erhellend. Entweders ist das ein
Fehler vom Linker oder wir machen beim Aufrufen etwas falsch. Der dort
empfohlene -lgcc Parameter ist für GCC und hilft dann beim direkten
Linkeraufruf auch nicht (?)
Suchpfade im Linkerscript sollte man vermeiden. Das ist ne Krücke die
man nur braucht wenn man nicht weis wie Linkerkomandozeilen
funktionieren oder zu viele Suchpfade hat.
Wenn Ihr das Thema jahrelang vor euch hergeschoben habt, dann müsste Ihr
jetzt halt in den sauren Apfel beißen und lernen, das Wissen für die
Benutzung eines Compilers einkaufen oder aufhören Software zu erstellen.
Man kann so ein Thema nicht jahrelang links liegeb lassen und dann
erwarten es in wenigen Stunden zu lösen, schon gar nicht wenn man
nichtmal in der Lage ist Anständige Informationen (Vollständige
Makefiles, Linkerscripte, Verwendetet Toolchains etc.) liefert.
J. V. schrieb:> Der dort empfohlene -lgcc Parameter ist für GCC und hilft dann> beim direkten Linkeraufruf auch nicht (?)
Dann mach das eben nicht. "-lgcc" ist genau das, was für __eabi_uldivmod
gebraucht wird. Im Prinzip sagen auch alle nicht hilfreichen Antworten
genau das. Warum muss der Linker überhaupt direkt aufgerufen werden?
Bauform B. schrieb:> "-lgcc" ist genau das, was für __eabi_uldivmod> gebraucht wird.
-lgcc ändert am Linkfehler __eabi_uldivmod bei mir rein gar nichts.
Abgesehen davon ist die Beschreibung dieses Parameters in meinem GCC-PDF
dazu schwach bis für mich ganz unverständlich.
-nostartfiles führt alleine dazu, daß der Linker einfach kein ELF mehr
erzeugt. Dazu wird noch nicht mal eine Fehlermeldung absetzt was ebenso
zu den zahlreichen für mich unergründlichen Details gehört
Jan
Da werden so viele Sachen durcheinandergebracht. Du musst aufpassen das
du nicht aufgrund von Irrungen den Holzweg einschlägst:
Janvi schrieb:> -nostartfiles führt alleine dazu, daß der Linker einfach
Zielt zwar nicht direkt auf arm-none-eabi hat hier aber halbwegs
ergiebige Erklärungen zu -lgcc und zu den Suchpfaden bei direktem und
indirektem Aufruf:
https://wiki.osdev.org/Libgcc