5 votes

Comment obtenir la valeur d'une variable définie dans ld linker script à partir de C

Je suis en train d'écrire un programme pour faire fonctionner le métal nu. J'essaie d'obtenir une variable à partir d'un linker personnalisé script pour l'utiliser en C voici ce que j'ai tenté.

De C :

extern unsigned long* __START_OF_PROG_MEMORY;
volatile unsigned long *StartOfProgram = (unsigned long*) (&__START_OF_PROG_MEMORY);

Linker script :

SECTIONS
{
    . = 0x80000;
    PROVIDE(__START_OF_PROG_MEMORY = .);
    .text : { KEEP(*(.text.boot)) *(.text .text.* .gnu.linkonce.t*) }
    .rodata : { *(.rodata .rodata.* .gnu.linkonce.r*) }
    PROVIDE(_data = .);
    .data : { *(.data .data.* .gnu.linkonce.d*) }
    .bss (NOLOAD) : {
        . = ALIGN(16);
        __bss_start = .;
        *(.bss .bss.*)
        *(COMMON)
        __bss_end = .;
    }
    _end = .;
    PROVIDE(__END_OF_PROG_MEMORY = .);

   /DISCARD/ : { *(.comment) *(.gnu*) *(.note*) *(.eh_frame*) }
}
__bss_size = (__bss_end - __bss_start)>>3;

Est-ce la bonne façon d'obtenir le contenu de la variable définie dans le linker script ?

3voto

yugr Points 6089

Typiquement, cela se fait comme suit

// Volatile is normally not needed but it seems you have a special case
extern volatile unsigned char __START_OF_PROG_MEMORY[];
volatile unsigned char * const StartOfProgram = &__START_OF_PROG_MEMORY;

(voir ce poste dans Binutils ML ).

3voto

Gabriel Staples Points 1804

1. Documentation officielle pour accéder aux variables linkerscript dans votre code source :

Voir les exemples au bas de cette page : https://sourceware.org/binutils/docs/ld/Source-Code-Reference.html

Par conséquent, lorsque vous utilisez un symbole défini par le linker script dans le code source, vous devez toujours prendre l'adresse du symbole, et ne jamais essayer d'utiliser sa valeur. Par exemple, supposons que vous voulez copier le contenu d'une section de mémoire appelée .ROM dans une section appelée .FLASH et que le script du linker contient ces déclarations :

  start_of_ROM   = .ROM;
  end_of_ROM     = .ROM + sizeof (.ROM);
  start_of_FLASH = .FLASH;

Alors le code source C pour effectuer la copie serait :

  extern char start_of_ROM, end_of_ROM, start_of_FLASH;

  memcpy (& start_of_FLASH, & start_of_ROM, & end_of_ROM - & start_of_ROM);

Notez l'utilisation des opérateurs "&". Ceux-ci sont corrects. Alternativement, les symboles peuvent être traités comme des noms de vecteurs ou de tableaux et le code fonctionnera alors comme prévu :

(Mon approche préférée) :

  extern char start_of_ROM[], end_of_ROM[], start_of_FLASH[];

  memcpy (start_of_FLASH, start_of_ROM, end_of_ROM - start_of_ROM);

Notez que l'utilisation de cette méthode ne nécessite pas l'utilisation des opérateurs '&'.

2. Votre cas spécifique :

Donc, si je voulais récupérer la valeur de la variable linkerscript __START_OF_PROG_MEMORY pour l'utiliser dans mon programme C, je le ferais :

#include <stdint.h>

extern uint32_t __START_OF_PROG_MEMORY[]; // linkerscript variable; NOT an array; `[]` is required to access a linkerscript variable like a normal variable--see here: https://sourceware.org/binutils/docs/ld/Source-Code-Reference.html
uint32_t start_of_program = (uint32_t)__START_OF_PROG_MEMORY;

3. Notez que si vous faites cela pour les microcontrôleurs STM32 :

Une autre astuce pour saisir l'adresse du début de la mémoire du programme (usu. Flash--d'où le début du programme est stocké) est de saisir simplement l'adresse de la balise g_pfnVectors le tableau de la table vectorielle ISR globale, qui est défini dans votre fichier d'assemblage de démarrage (ex : "startup_stm32f746xx.s"). Pour cela, faites ce qui suit :

extern uint32_t g_pfnVectors[];  // true array (vector table of all ISRs), from the startup assembly .s file
uint32_t application_start_address = (uint32_t)&g_pfnVectors[0]; // Get the address of the first element of this array and cast it to a 4-byte unsigned integer

Voilá ! C'est magique :).

En rapport :

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X