Hallo zusammen, ich habe folgendes Problem mit meinem GCC LinkerScript. Ich möchte gerne eine Feste adresse im Flashspeicher vergeben auf die ich im Code wieder zugreifen kann. Die Adresse ist liegt mitten im Flash und muss auch genau dort liegen. Ich kenne mich mit dem Linker einfach zu wenig aus und finde nichts passendes in der Doku. Ich hab keine Ahnung ob das überhaupt funktioniert... Hier mal ein kleines Beispiel. Nicht lauffähig, es geht nur ums Prinzip. Code mit Variable auf fester Adresse: const uint16_t _attribute_ ((section (".FixedSection"))) _attribute_ ((aligned (8))) u16Variable = 0x1234; Linker: .FixedSection 0x8000FF0 : { KEEP(*(.FixedSection)) /* keep my variable even if not referenced */ } > FLASH /* The program code and other data goes into FLASH */ .text : { . = ALIGN(4); *(.text) /* .text sections (code) */ *(.FixedSection) *(.text*) /* .text* sections (code) */ *(.glue_7) /* glue arm to thumb code */ *(.glue_7t) /* glue thumb to arm code */ *(.eh_frame) KEEP (*(.init)) KEEP (*(.fini)) . = ALIGN(4); _etext = .; /* define a global symbols at end of code */ } >FLASH Ich habe jetzt das Problem, dass mein .text Section mit meiner Fest vergebenen Adresse beginnt. Ich schaffe es momentan einfach nicht, dass vor und nach der festen Adresse die ganz normalen Daten abgelegt werden. Wie kann ich das realisieren? Danke für eure Hilfe!
>Die Adresse ist liegt mitten im Flash und muss >auch genau dort liegen. Warum? > finde nichts passendes in der Doku. Kann kaum sein. Welche Doku hast Du gelesen? Das GNI Linker Manual sollte die gewünschte Info liefern. Ich würd's einfach 'mal so versuchen: ----- 8< --------------------------- MEMORY { FLASH : ORIGIN = 0x8000000, LENGTH = ... FLASH_FIXED : ORIGIN = 0x8000FF0 LENGTH = ... FLASH_REST : ORIGIN = .... LENGTH = ... } .text : { . = ALIGN(4); { *(.text) } > FLASH { *(.FixedSection) } > FLASH_FIXED { *(.text) } } > FLASH_REST ..... ------ >8 -------------------------------- Ich hab's selbst nicht probiert. LENGTHs passend machen. Kann man sicher auch den Linker rechnen lassen.
ElBartscho schrieb: > Ich schaffe es momentan einfach nicht, dass > vor und nach der festen Adresse die ganz normalen Daten abgelegt werden. Das geht auch mit dem LD aus Binutils nicht. Der kann Code oder Daten nicht um feste Addressen "drumherum" legen. Was aber meistens geht sind feste Addressen am Ende des Flash. Am Anfang geht oft auch, z.B. zwischen Interrupt Tabelle und restlichem .text Segment. Dann bleibt halt ein Gap übrig.
Hallo Jim, >Das geht auch mit dem LD aus Binutils nicht. Der kann Code oder Daten >nicht um feste Addressen "drumherum" legen. Sicher? Dass er eine Funktion, die vor dem fixen Block nicht reinpasst, nicht aufteilen kann, scheint mir plausibel. Dass er aber diese Funktion in den Block NACH dem fixen schiebt und dann dort mit der Section-Zuweisung weitermacht, hätte ich erwartet. Eine manuelle Zuweisung von Sections an Speicherbblöcke müsste aber in jedem Fall gehen. Das macht er ja im Fall von .text, .data und .bss auch.
Hallo Leute, das mit den Blöcken funktioniert. Laut .map File packt er jetzt die read only blöcke vor die den definierten Speicherblock (.rodata in FLASH). Er teilt also .text nicht wie ich es erwartet habe. Ich denke der ld kann das nicht wie ihr bereits gesagt habt. Auf die Gefahr hin das mein ld script zerfezt wird... habt ihr Anregungen? /* Entry Point */ ENTRY(Reset_Handler) /* Highest address of the user mode stack */ _estack = 0x20020000; /* end of RAM */ /* Generate a link error if heap and stack don't fit into RAM */ _Min_Heap_Size = 0x200; /* required amount of heap */ _Min_Stack_Size = 0x400; /* required amount of stack */ /* Specify the memory areas */ /* Specify the memory areas */ /* r = read only */ /* w = write */ /* x = executable code */ MEMORY { FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 4096 VERSION (r) : ORIGIN = 0x8001000, LENGTH = 8 FLASH_REST (rx) : ORIGIN = 0x8001000 + 8, LENGTH = 252K - 8 RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 128K } /* Define output sections */ SECTIONS { /* Startaddress of ROM */ . = 0x8000000; /* The startup code goes first into FLASH */ .isr_vector : { . = ALIGN(4); KEEP(*(.isr_vector)) /* Startup code */ . = ALIGN(4); } >FLASH /* The program code and other data goes into FLASH */ .text : { . = ALIGN(4); *(.text) /* .text sections (code) */ . = ALIGN(4); } >FLASH .Version : { KEEP(*(.Version)) /* .text sections (code) */ } >VERSION /* The program code and other data goes into FLASH */ .text : { . = ALIGN(4); *(.text) /* .text sections (code) */ *(.glue_7) /* glue arm to thumb code */ *(.glue_7t) /* glue thumb to arm code */ *(.eh_frame) KEEP (*(.init)) KEEP (*(.fini)) . = ALIGN(4); _etext = .; /* define a global symbols at end of code */ } >FLASH_REST /* Constant data goes into FLASH */ .rodata : { . = ALIGN(4); *(.rodata) /* .rodata sections (constants, strings, etc.) */ *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ . = ALIGN(4); } >FLASH .ARM.extab :{ *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH .ARM : { __exidx_start = .; *(.ARM.exidx*) __exidx_end = .; } >FLASH .preinit_array : { PROVIDE_HIDDEN (__preinit_array_start = .); KEEP (*(.preinit_array*)) PROVIDE_HIDDEN (__preinit_array_end = .); } >FLASH .init_array : { PROVIDE_HIDDEN (__init_array_start = .); KEEP (*(SORT(.init_array.*))) KEEP (*(.init_array*)) PROVIDE_HIDDEN (__init_array_end = .); } >FLASH .fini_array : { PROVIDE_HIDDEN (__fini_array_start = .); KEEP (*(SORT(.fini_array.*))) KEEP (*(.fini_array*)) PROVIDE_HIDDEN (__fini_array_end = .); } >FLASH /* used by the startup to initialize data */ _sidata = LOADADDR(.data); /* Initialized data sections goes into RAM, load LMA copy after code */ .data : { . = ALIGN(4); _sdata = .; /* create a global symbol at data start */ *(.data) /* .data sections */ *(.data*) /* .data* sections */ . = ALIGN(4); _edata = .; /* define a global symbol at data end */ } >RAM AT> FLASH /* Uninitialized data section */ . = ALIGN(4); .bss : { /* This is used by the startup in order to initialize the .bss secion */ _sbss = .; /* define a global symbol at bss start */ _bss_start_ = _sbss; *(.bss) *(.bss*) *(COMMON) . = ALIGN(4); _ebss = .; /* define a global symbol at bss end */ _bss_end_ = _ebss; } >RAM /* User_heap_stack section, used to check that there is enough RAM left */ ._user_heap_stack : { . = ALIGN(8); PROVIDE ( end = . ); PROVIDE ( _end = . ); . = . + _Min_Heap_Size; . = . + _Min_Stack_Size; . = ALIGN(8); } >RAM /* Remove information from the standard libraries */ DISCARD : { libc.a ( * ) libm.a ( * ) libgcc.a ( * ) } .ARM.attributes 0 : { *(.ARM.attributes) } }
Zwei gleichnamige Sektionen ".text"? Hätte erwartet, dass der Linker meckert.
Steffen R. schrieb: > Zwei gleichnamige Sektionen ".text"? > Hätte erwartet, dass der Linker meckert. Habe damit etwas experimentiert. Es scheint das die 2. .text Sektion ignoriert wird. Merkt man natürlich erst wenn das Programm mehr Platz braucht als die Sektion bietet. Mit schieben in Tetris Art kann man aber alle Sektionen unterbringen.
Hi, diesen Gedanken hatte ich auch. Ich bin mir nicht 100% Sicher, aber ich glaube der Linker nutzt nur die 2. .text SECTION weil die erste einfach zu klein ist und somit übersprungen wird. Dann packt der ld die Version an den vorgesehenen Ort. und anschließend füllt er .text in den Block FLASH_REST. Die restlichen Variablen warden dann wieder automatisch vor VERSION gepackt.
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.