Forum: Compiler & IDEs Fragen zu ld und Linker-Scripts (fill, defsym,.)


von Siddhartha (Gast)


Lesenswert?

Hallo zusammen

ich kämpfe gerade bissl mit dem arm-elf-ld rum und krieg das 
Linker-Script einfach nicht so hin, wie ich gerne will.

Grundsätzlich geht es darum, dass ich meinen Code (für einen 
AT91SAM7S256) so kompilieren/linken will, dass das daraus entstehende 
Binary immer die gleiche Grösse hat, nämlich die Grösse vom internen 
Flash (256 kB). Zudem sollen die letzten Bytes mit dem CRC16-Wert der 
restlichen Bytes gefüllt werden. Die Berechnung des CRC16 wird dabei mit 
einem kleinen Konsolen-Tool gemacht. Nun habe ich dabei aber mehrere 
Probleme, die ich entweder nicht richtig verstehe oder mich einfach noch 
zu wenig mit Linker-Scripts auskenne :-(

Also zuerst einmal wollte ich das mit dem CRC-Wert so machen:
  - Alles kompilieren, linken und mit objcopy ein Binary erstellen 
(dabei werden die Bytes, die für den CRC16 gebraucht werden, mit 0 
gefüllt)
  - CRC16-Tool laufen lassen und so den CRC Wert bestimmen
  - Linker-Script nochmals anwerfen und über --defsym CRC16=0xXXXX den 
berechneten Wert übergeben und vom Linker-Script ganz am Ende einfügen 
lassen.

Der relevante Teil meines Linker-Scripts sieht deshalb folgendermassen 
aus:
1
__CRC_START__  = 0x03FFFE;
2
PROVIDE(CRC16 = 0x0000);
3
4
crc : AT ( __CRC_START__ )
5
{
6
    SHORT(CRC16);
7
}

Aber irgendwie wird immer 0x0000 eingefügt und nicht der berechnete 
CRC16-Wert. Wenn ich mir im Map-File den "Speicher-Aufbau" anschaue, 
erscheint ganz am schluss (nach der crc-section) ein Eintrag zur Adresse 
mit dem Wert des berechneten CRC16-Werts mit dem entsprechenden Wert.
Was mache ich dabei falsch? Oder ist --defsym dafür gar nicht geeignet?

Mein zweites Problem ist, dass ich alles, was nicht mit Code oder 
nutzbaren Daten gefüllt ist, mit 0xFFFFFFFF (was ja der Grundzustand 
eines Flash-Speichers ist) füllen will, damit es da keine Probleme mit 
der CRC-Überprüfung gibt. Dafür gibt es ja das FILL-Kommando oder die 
=fillexp-Angabe bei Sections.
Komischerweise ist es jetzt jedoch so, dass im erstellten Binary zwar an 
den entsprechenden Stellen der korrekte Füllwert steht (wobei .data und 
.bss sections mit 0 und nicht mit 1 gefüllt werden wegen RAM). Wenn ich 
das Binary dann aber über JTAG ins interne Flash des AT91SAM7S256 lade, 
dann steht an den Adressen, wo die .data und .bss sections sind, überall 
1 und nicht 0 und an den Stellen, die ich extra manuell mit 1 gefüllt 
habe, steht teilweise irgendwelcher Code.
Habe ich in dem Vorgehen irgendeinen Denkfehler? Warum wird das Binary 
nicht genau so ins interne Flash geschrieben, wie ich es erstellt habe?

Danke für eure Hilfe!

PS: Ich weiss dass es bissl viel auf einmal ist, sorry.

von Siddhartha (Gast)


Lesenswert?

So konnte beide Probleme lösen.

Das defsym-Problem hat sich damit gelöst, dass ich einfach die Zeile
1
PROVIDE(CRC16 = 0x0000);
weggelassen habe und beim ersten Linker-Aufruf per defsym einfach 0x0000 
übergeben habe und beim zweiten Mal den richtigen CRC16 Wert.

Das andere Problem habe ich mit objcopy und dessen Parameter --gap-fill 
gelöst, das schön alle "Löcher" mit dem angegebenen Wert füllt.

von Sascha M. (siddhartha)


Lesenswert?

So ich bin es doch nochmals, weil ich doch nochmal auf ein Problem 
gestossen bin.

Bisher hat alles gut funktioniert, aber da das Programm unterdessen doch 
schon wieder beachtlich gewachsen ist, hat sich folgendes Problem 
ergeben:

Im Linker-Script werden die Sections in folgender Reihenfolge definiert:

.text
.data
.bss
.crc

Wobei .crc genau 2 Byte vor Flash-Ende (256kB) stehen muss.
Unterdessen ist die .bss Section jedoch so gross geworden, dass die 
ersten drei Sections zusammen grösser sind als 256kB. Da der Linker 
nicht fähig ist, den Location Counter (gibt die momentane Adresse an) zu 
dekrementieren und die .bss Section über die Adresse der .crc Section 
hinaus geht, bricht der Linker natürlich mit einem Section Overlapping 
Error ab.
Das ist meiner Meinung nach theoretisch auch logisch und korrekt, ABER 
schlussendlich steht doch die .bss Section gar nicht im BIN File drin, 
das vom Linker generiert wird. Die wird im Linker-Script ja nur benötigt 
um die Grösse der Section zu ermitteln, damit der Startup Code das dann 
im RAM belegen kann oder nicht?

Basierend auf dieser Überlegung habe ich ausprobiert, was passiert, wenn 
ich die .bss Section hinter die .crc Section lege, sprich eigentlich 
ausserhalb des physikalisch verfügbaren Speicherbereichs. Wenn ich das 
so versuche, motzt der Linker zwar nicht mehr, aber das Programm läuft 
nicht und springt immer wieder zum Startup Code (ich nehme mal an, 
sobald er auf eine Variable, die in .bss stehen würde, trifft).

Hat jemand ne Idee, wie man dieses Phänomen umgehen könnte?
Oder habe ich irgendeinen Denkfehler gemacht?

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.