Hallo NG, habe eben versucht, die Daten fest nach 0x20a000 zu bekommen (sozusagen rein in der Binary, die in den Speicher geladen wird.) fogelndes habe ich gemacht: im .ld: MEMORY { /* memory map of AT91SAM7S256 */ ROM (rx) : ORIGIN = 0x00100000, LENGTH = 256k RAM (rwx) : ORIGIN = 0x00202000, LENGTH = 32k SID (rwx) : ORIGIN = 0x0020A000, LENGTH = 1k } ... SECTIONS { ... .sid : { } >SID ... im Quelltext dann folgendes: #pragma DATA_SECTION(".sid"); static unsigned char* mysid = "êêêêêêêêêêêêêêêêêêêê"; die Daten befinden sich aber "vogelwild" bei 0x480c in der binary (Offset Dateibeginn = 0x00). Ich möchte aber gerne, dass nach einem gewissen "Leeraum" die Daten von Oben in diesem Beispiel bei Offset 0x8000 liegen, so dass diese dann nach dem Hochladen ins SRAM (0x202000) dann automatisch bei 0x20a000 liegen. Ich will nicht die Daten zuerst in ein Array speichern und dann von dort aus "kopieren". Bei so wenig Speicher wäre das Verschwendung. Vielen Dank an alle, die hier Licht ins Dunkle bringen ;-) MfG Peter
Peter Pippinger schrieb: > habe eben versucht, die Daten fest nach 0x20a000 zu bekommen (sozusagen > rein in der Binary, die in den Speicher geladen wird.) > MEMORY { /* memory map of AT91SAM7S256 */ > ROM (rx) : ORIGIN = 0x00100000, LENGTH = 256k > RAM (rwx) : ORIGIN = 0x00202000, LENGTH = 32k > SID (rwx) : ORIGIN = 0x0020A000, LENGTH = 1k > } Hallo, du kannst keine Daten per Linker in ein RAM schreiben - wie sollte das im Stand alone Betrieb denn gehen? Die Daten stehen beim Einschalten ausschliesslich im ROM, das RAM ist zufällig. Also musst du die Daten erst vom ROM ins RAM kopieren. Entweder gleich beim Booten mit ein paar Assembler-Befehlen oder die Runtime Library erledigt das, weil es sich um initialisierte Variablen handelt, oder im Startcode der Hochsprache, das ist so ziemlich immer das Gleiche. Das RAM ohne Programm mit Daten zu füllen geht nur mit Hilfe des Debuggers - willst du den und den PC mitliefern? Ausserdem, nach dem gesagten ist das nur zu Testzwecken sinnvoll. Gruss Reinhard
Doch. Man kann Code & Konstaten fest an eine Adresse schreiben. Die noetige Anweisung nennt sich ORG .
Nein. Damit kann man zwar festlegen, daß Variablen an bestimmten Adressen liegen - deren Wert aber ist, wenn sie im RAM liegen, nach dem Einschalten des Systems undefiniert, und muss daher erst mal initialisiert werden.
Ok, ich sehe du bist doch mit Linker Scripten etwas vertraut, dann kann ich das aus dem anderen Thread etwas ausbreiten hier. Erst mal streich die SID aus der MEMORY raus, dass macht keinen Sinn. Alle zusammengehörigen Segmente bekommen einen Eintrag, also RAM wieder LENGTH = 64K. In den SECTIONS, mach ins Ende von dem Block für .data (vor etwaigen aligns) die Einträge
1 | . = 0x8000; |
2 | *(.sid) |
Genauer könnte ich es sagen, wenn ich das ganze Script sehen könnte. Wobei ich statt dem Namen .sid eher .data.sid vorschlagen würde, da weiß man dass es eine Sektion ist, die zu .data gehört. Diese Lösung funktioniert ganz ohne Änderungen am Startup. Problem ist halt, dass das restliche .data des ganzen Projekts nicht länger als 32 kB sein darf. Zweitens wird das Vorspulen mittels ". = 0x8000;" mit nutzlosen Füllbytes erreicht, die auch im ROM im Abbild der .data Sektion Platz belegen. Und an "Tretet den Trog": ORG (bzw. .org im GNU Assembler) funktioniert nicht, da es relativ zum Sektionsstart in dieser Datei ist. Werden andere Dateien mit einem .data davor gelinkt, verschiebt sich das entsprechend.
Hallo Andreas B., In mein Linkerskript habe ich nun folgendes eingebaut: MEMORY { /* memory map of AT91SAM7S256 */ ROM (rx) : ORIGIN = 0x00100000, LENGTH = 256k RAM (rwx) : ORIGIN = 0x00202000, LENGTH = 64k } .data : { __data_load = LOADADDR (.data); __data_start = .; KEEP(*(.jcr)) *(.got.plt) *(.got) *(.shdata) *(.data .data.* .gnu.linkonce.d.*) . = 0x3000; *(.data.sid) . = ALIGN (4); _edata = .; } >RAM AT>RAM Allerdings siehts in meiner .bin-Datei immer noch so aus: 00480C0 EA EA EA EA EA EA EA EA EA EA ... Was allerdings schon passiert, ist, dass die Datei größer wird... Muss ich das Segment im C-Quelltext anders definieren? #pragma DATA_SECTION(".data.sid"); static unsigned char* mysid = "êêêêêêêêêêêêêêêêêêêê"; Was ich eben noch gesehen habe: Der Linker spuckt folgendes aus: src/main.c:869:0: warning: ignoring #pragma DATA_SECTION Gruß Peter
Hi, versuchs mal mit
1 | static unsigned char* mysid __attribute__((section(".sid"))) = "êêêêêêêêêêêêêêêêêêêê"; |
Aber auch dann würde ich nur davon ausgehen, dass er den Pointer an der Adresse speichert, nicht aber das Array. Gruß Lasse
Peter Pippinger schrieb: > Muss ich das Segment im C-Quelltext anders definieren? > > #pragma DATA_SECTION(".data.sid"); > static unsigned char* mysid = "êêêêêêêêêêêêêêêêêêêê"; > > Was ich eben noch gesehen habe: Der Linker spuckt folgendes aus: > src/main.c:869:0: warning: ignoring #pragma DATA_SECTION Ja, wenn es sich um den gcc handelt dann ignoriert der Pragmas. Wie Lasse S. geschrieben hat, musst du da die attribute-Syntax von gcc verwenden und die Variable besser nicht als Pointer deklarieren:
1 | static unsigned char mysid[] __attribute__((section(".data.sid"))) = "êêêêêêêêêêêêêêêêêêêê"; |
Der String wird sonst in .rodata und damit im ROM abgelegt. Auf jeden
Fall ist .rodata normalerweise nach .text abgelegt und damit sicher
woanders.
Außerdem, nur um sicher zu gehen:
> } >RAM AT>RAM
Das funktioniert nur, solange das komplette Programm für die Ausführung
im RAM gelinkt wird, also nicht geflasht werden kann. Wenn das Absicht
war, in Ordnung.
Das Ganze ist als Einführung in die Linkerscript Erstellung sicher
interessant, aber die Frage bleibt: Ist hinter der festen Position für
den String ein tieferer Sinn?
Hallo Lasse S, hallo Andreas B., ich habe eure Versionen mal getestet. Aber leider kommen die Chars immer nach Datei-Offset 0x480c. @Andreas: >> } >RAM AT>RAM > Das funktioniert nur, solange das komplette Programm für die Ausführung > im RAM gelinkt wird, also nicht geflasht werden kann. Wenn das Absicht > war, in Ordnung. Naja, irgendwie habe ich es nie geschafft mir einen Debugger anzuschaffen. In der Arbeit - so blöd sich das anhört - verwende ich auch immer den "Poor Man's Debugger" (PHP :-) RAM ist also in diesem Fall ok. Habe mir eine Batch geschrieben, die zuerst aufräumt, dann kompiliert und linkt und das Ergebnis direkt via SAM-BA ins RAM legt und dort auch ausführt. Dadurch ist das alles schon ok, zumal ja RS232 schon super hinhaut... Zu Deiner Frage, warum ich das im RAM an einer bestimmten Adresse ablegen möchte: Ich bin ja gerade dabei einen SID-Player zu bauen. Dieser soll die alten Musikstücke vom C64 abspielen können. Dazu muss die CPU vom C64 emuliert werden (was jetzt schon funktioniert). Eine der wenigen Gemeinsamkeiten vom AT91SAM7P256 sind 64KB RAM. Diese 64KB möchte ich später auch als Hauptspeicher der Emulation verwenden. Und jetzt zum Testen habe ich das Problem, dass sich der ARM mit der Emulation des C64 den Speicher teilen müssen, bis alles fertig ist und ich es ins EEPROM verfrachten kann. Den Stack für den ARM mit ein paar Variablen werde ich dann an Stellen im RAM versetzen, die ich für die Emulation nicht brauche (z.B. $0400+)... Die Sid-Musikfiles liegen alle an verschiedenen Stellen im Speicher - je nachdem, wie sie programmiert wurden. Mein Teststück, mit dem ich alles teste sollte am Ende in $C000 (also übertragen 0x20C000) landen. Naja, zum Testen werde ich wohl nicht herumkommen, als dass ich die Daten dann doch beim Init an die passende Stelle schaufle... Falls ihr doch noch eine Idee habt, dann bitte gerne her damit. Wäre echt cool. MfG Peter
So, jetzt habe ich diese Hürde auch genommen :-) War zwar ein lustiges Raten, aber es geht... im Linkerskript doch wieder mit SID: MEMORY { /* memory map of AT91SAM7S256 */ ROM (rx) : ORIGIN = 0x00100000, LENGTH = 256k RAM (rwx) : ORIGIN = 0x00202000, LENGTH = 56k SID (rwx) : ORIGIN = 0x0020F000, LENGTH = 1k } SECTIONS { ... .sid : { . = 0x00; *(.sid) } >SID AT>SID ... } und im Programm: static unsigned char mysid[] __attribute__((section(".sid"))) = "êêêêêêêêêêêêêêêêêêêê"; Im Hexeditor stehen dann die EA EA EA... an 0xd000 wenn man das nun alles an 0x202000 läd, ergibt sich eine Adresse von 0xf000. Ein Ausführen mit Programmcounter @ 0xf000 im Emulator liefert nun wie gewollt: NOP NOP NOP ... Alles gut, ich kann schlafen gehen ;-) Gute Nacht.
Ok, wenn alles im RAM ist, gab es natürlich ein Problem mit meiner Version: Ich hatte den Offset relativ zum Start von .data, da aber .text und .rodata im Allgemeinen davor gelinkt werden, liegt .data nicht am Anfang vom RAM und es verschiebt sich alles... Dann nochmal eine bessere Version: Peter Pippinger schrieb: > im Linkerskript doch wieder mit SID: > > MEMORY { /* memory map of AT91SAM7S256 */ > ROM (rx) : ORIGIN = 0x00100000, LENGTH = 256k > RAM (rwx) : ORIGIN = 0x00202000, LENGTH = 56k > SID (rwx) : ORIGIN = 0x0020F000, LENGTH = 1k > } Würde ich wieder nicht empfehlen, das macht man alles in den SECTIONS. Außer es soll wirklich ein Bereich fester Länge fürs SID freigelassen werden und nicht für sonstige >RAM Sektionen genutzt werden dürfen. > SECTIONS { > ... > .sid : { > . = 0x00; > *(.sid) > } >SID AT>SID > ... > } Zustimmung, eine eigene Sektion für .sid wird gebraucht. Aber die Startadresse einer Sektion lässt sich einfach vorgeben:
1 | .sid 0x20f000 : { |
2 | *(.sid) |
3 | } |
Das >RAM kann man sich sparen wenn die Adresse vorgegeben ist. Für den Fall, dass es dann doch ins Flash soll, braucht die .sid Sektion ein AT>ROM und analog zu .data definierte start und size Symbole und das Startup muss die Daten analog zur .data Sektion kopieren. Das Ganze nur falls die Daten initialisiert sein müssen und nicht sowieso erst im Betrieb geladen werden, versteht sich. Die Zeile mit ". = 0x00;" macht keinen Sinn, der Zähler ist am Anfang einer Sektion sowieso Null. Außerdem ist AT> nur nötig, wenn die Ausführregion und Laderegion unterschiedlich sind. Damit man nachher einfach zwischen Linken für RAM und Linken für ROM umschalten kann, verwendet man REGION_ALIAS.
*** PERFEKT!!! *** Endlich mal jemand, der sich mit Linkern auskennt :-) Gruß Peter
...eine Frage hätte ich da noch: ist es eigentlich auch möglich, in dieser Sektion binäre Daten einer Datei "einzuhängen"? Das mit dem Array finde ich ein bisschen unschön... MfG Peter
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.