Partage
  • Partager sur Facebook
  • Partager sur Twitter

Zone mémoire et linker script

Sujet résolu
    17 février 2020 à 22:32:24

    Bonjour à tous

    Alors j'ai un petit soucis.

    Je travaille actuellement sur un STM32. et j'essaie de jouer avec la FLASH de mon µC.

    Ce que je veux faire c'est déclarer des zones dans mon linker script, et créer des symboles pour protéger et gérer ces zones.

    Dans mon linker script j'ai créé une zone "USER MEMORY"

    MEMORY
    {
    RAM (xrw)      : ORIGIN = 0x20000000, LENGTH = 128K
    CCMRAM (rw)    : ORIGIN = 0x10000000, LENGTH = 64K
    USER_MEMORY (rw)     : ORIGIN = 0x8080000, LENGTH = 0x80000
    FLASH (rx)     : ORIGIN = 0x8000000, LENGTH = 0x80000
    }

    Dans les sections, j'ai déclaré des symboles pour protéger cette zone et les autres zones mémoires par la même occasion:

      .MEMORY_USER_TEST :
      {
        . = ALIGN(4);
        _MEMORY_USER_START_ADDR = .;
        KEEP (*(USER_MEMORY))
        . = ORIGIN(USER_MEMORY) + LENGTH(USER_MEMORY);
        _MEMORY_USER_END_ADDR = .;
      } >USER_MEMORY


    J'ai voulu déclarer trois pointeurs pour définir trois addresses particulière : L'adresse de fin du code, l'adresse du début du block "USER_MEMORY" l'adresse de fin du block "USER_MEMORY"

    const unsigned char *FlashEnd __attribute__((section("_etext")));
    
    
    const unsigned char *FlashBlockBegin __attribute__((section("_MEMORY_USER_START_ADDR")));
    
    const unsigned char *FlashBlockEnd __attribute__((section("_MEMORY_USER_END_ADDR")));

    Mon problème c'est que ces trois constantes ne pointent pas vers les adresses que je veux, mais vers des adresses situées dans la RAM de mon µC

    Si dans mon main j'écris ceci :

        unsigned long test1 = &FlashBlockBegin;
        unsigned long test2 = FlashBlockBegin;

    En debug, mes variables prennents ces valeurs :

    test1    unsigned long    0x2000006c (Hex)   
    test2    unsigned long    0xbf022f03 (Hex)   

    J'utilise un STM32F405. D'après la documentation

    La RAM se trouve à l'adresse 0x20000000, et la FLASH à l'adresse 0x8000000.

    La valeur de la variable test1 est donc cohérente. Mais je ne sais pas expliquer la valeur de test2. D'après le maping mémoire du STM32F405, l'adresse 0xbf022f03 correspond aux secteurs de la FSMC (contrôleur pour mémoire externe), que je n'ai pas configuré.


    Le pire c'est que dans mon mapping mémoire mes symboles semblent à peu près cohérents :

    .MEMORY_USER_TEST
                    0x08080000    0x80000
                    0x08080000                . = ALIGN (0x4)
                    0x08080000                _MEMORY_USER_START_ADDR = .
     *(USER_MEMORY)
                    0x08100000                . = (ORIGIN (USER_MEMORY) + LENGTH (USER_MEMORY))
     *fill*         0x08080000    0x80000 
                    0x08100000                _MEMORY_USER_END_ADDR = .
                    0x08001c18                _sidata = LOADADDR (.data)
    
    .data           0x20000000       0x68 load address 0x08001c18
                    0x20000000                . = ALIGN (0x4)
                    0x20000000                _sdata = .

    _MEMORY_USER_START_ADDR
                    0x2000006c        0x4 load address 0x08001c84
                    [!provide]                PROVIDE (__start__MEMORY_USER_START_ADDR, .)
     _MEMORY_USER_START_ADDR
                    0x2000006c        0x4 Src\main.o
                    0x2000006c                FlashBlockBegin
                    [!provide]                PROVIDE (__stop__MEMORY_USER_START_ADDR, .)
    
    _MEMORY_USER_END_ADDR
                    0x20000070        0x4 load address 0x08001c88
                    [!provide]                PROVIDE (__start__MEMORY_USER_END_ADDR, .)
     _MEMORY_USER_END_ADDR
                    0x20000070        0x4 Src\main.o
                    0x20000070                FlashBlockEnd
                    [!provide]                PROVIDE (__stop__MEMORY_USER_END_ADDR, .)



    Je suis encore amateur de la configuration de linker script. C'est un peu pour ça d'ailleurs que je voulais m'y essayer, j'avoue que je commence à sécher un peu...

    Est-ce que vous savez comment initialiser des variables et y insérer les adresses que je souhaite via __attribute__ ?

    Merci pour votre aide :)

    -
    Edité par heryz 24 février 2020 à 22:27:45

    • Partager sur Facebook
    • Partager sur Twitter
      20 février 2020 à 8:25:44

      Avec cette ligne :

      const unsigned char *FlashBlockBegin __attribute__((section("_MEMORY_USER_START_ADDR")));

      Tu crées une variable qui est stocké dans la zone _MEMORY_USER_START_ADDR d'où le fait que l'adresse de cette variable correspond à 0x2000006c.

      En revanche, tu ne l'as pas initialisée donc celle-ci peut contenir n'importe quoi, d'où le fait que tu trouves 0xbf022f03 qui est une valeur complètement aléatoire.

      Il te faudrait lui affecter une valeur si tu veux quelque chose de cohérent.

      const unsigned char *FlashBlockBegin __attribute__((section("_MEMORY_USER_START_ADDR"))) = 0x1234;

      En revanche, cela ne va probablement pas suffire car tu n'as probablement pas ajouté le mécanisme d'initialisation dans ton code.

      L'initialisation des variables globales en RAM se fait par le script de startup en copiant la zone BSS vers la zone RAM.

      • Partager sur Facebook
      • Partager sur Twitter
        21 février 2020 à 21:04:42

        Bonjour,

        Merci pour cette explication mais cela ne correspond pas à ce que je veux...

        Mon symbole _MEMORY_USER_START_ADDR a été créé à l'adresse 0x8080000 et 0x2000006c (LMA et VMA).

        Ce que je souhaite en fait, c'est créer une variable (pointeur ou non) qui contienne la valeur de l'adresse réel de _MEMORY_USER_START_ADDR

        Par exemple, je voudrai créer un code qui puisse afficher ce résultat :

        const unsigned int *maVariable = _MEMORY_USER_START_ADDR; // (C'est à titre d'exemple, cette ligne ne marche pas)
        
        
        printf("@maVariable:%X | Contenu de maVariable:%X", &maVariable, maVariable);

        >>@maVariable:0x200XXXX | Contenu de maVariable:0x8080000

         (l'endroit où est stockée maVariable importe peu, mais je pense que ce serait mieux en RAM pour y accéder)

        Où la même chose avec un variable de base (pas un pointeur)

        const unsigned int maVariable = _MEMORY_USER_START_ADDR; // (C'est à titre d'exemple, cette ligne ne marche pas)
        
        printf("@maVariable:%X | Contenu de maVariable:%X", &maVariable, maVariable);

        >>@maVariable:0x200XXXX | Contenu de maVariable:0x8080000

         (l'endroit où est stockée maVariable importe peu, mais je pense que ce serait mieux en RAM pour y accéder)

        Il n'y a rien à faire, je n'arrive jamais à avoir une variable qui possède 0x8080000 comme contenu ...

        1. Savez-vous comment arriver à ce résultat ?

        -------------------------------------------------------------------------------------------------------------------

        J'ai aussi un deuxième problème, j'ai remarqué en investiguant mon ".list" que mes deux symboles n'étaient pas vraiment déclarés aux adresses que je souhaite. En fait, ils sont positionnés aux dernière adresses utilisées. JE pense que le but du compilateur est d'éviter les pertes de places inutiles, ce qui est intéressant en soi. Malheureusement, je veux utiliser des zones bien distincts, et donc je veux utiliser MES ZONES et pas des zones optimisées par le compilo.

                          CONTENTS, ALLOC, LOAD, DATA
          4 .fini_array   00000004  08001c28  08001c28  00011c28  2**2
                          CONTENTS, ALLOC, LOAD, DATA
          5 .MEMORY_USER_TEST 00080000  08080000  20000000  00030000  2**0
                          ALLOC
          6 .data         00000068  20000000  08001c2c  00020000  2**2
                          CONTENTS, ALLOC, LOAD, DATA
          7 _etext        00000001  20000068  08001c94  00020068  2**0
                          CONTENTS, ALLOC, LOAD, DATA
          8 _MEMORY_USER_START_ADDR 00000004  2000006c  08001c95  0002006c  2**2
                          CONTENTS, ALLOC, LOAD, DATA
          9 _MEMORY_USER_END_ADDR 00000004  20000070  08001c99  00020070  2**2



        J'ai essayé différents trucs comme utilisé ABSOLUTE(.) mais ça semble ne pas marcher ...

        Je vous mets mon code :

        MEMORY
        {
        RAM (xrw)      : ORIGIN = 0x20000000, LENGTH = 128K
        CCMRAM (rw)    : ORIGIN = 0x10000000, LENGTH = 64K
        USER_MEMORY (rw)     : ORIGIN = 0x8080000, LENGTH = 0x80000
        FLASH (rx)     : ORIGIN = 0x8000000, LENGTH = 0x80000
          .MEMORY_USER_TEST :
          {
            . = ALIGN(4);
            _MEMORY_USER_START_ADDR = ABSOLUTE(.);
            KEEP (*(USER_MEMORY))
            . = ORIGIN(USER_MEMORY) + LENGTH(USER_MEMORY);
            _MEMORY_USER_END_ADDR = ABSOLUTE(.);
          } >USER_MEMORY AT >RAM

        2. Savez-vous comment aligner mes données directement sur l'adresse de base de MEMORY_USER_TEST ?

        3. Savez-vous à quoi sert la LMA ? Je comprend pas l'intérêt d'avoir un LMA et un VMA ? J'ai l'impression que tous les symboles que je créés sont utilisé dans la VMA (dans la RAM), du coup tout ce que je fais ne sert à rien car à aucun moment je peux récupérer l'adresse de la LMA...

        -
        Edité par heryz 21 février 2020 à 21:48:32

        • Partager sur Facebook
        • Partager sur Twitter
          24 février 2020 à 22:27:11

          C'est bon je pense avoir trouvé.

          Alors mon problème semble être lié à ces lignes :

          const unsigned long *FlashBlockEnd __attribute__((section("_MEMORY_USER_END_ADDR")));
          
          const unsigned long *FlashBlockStart __attribute__((section("_MEMORY_USER_START_ADDR")));

           Lorsque j'enlève l'attribute pour mettre l'adresse du symbole :

          extern const unsigned char *_MEMORY_USER_START_ADDR, *_MEMORY_USER_END_ADDR;
          
          const unsigned char *FlashBlockBegin = &_MEMORY_USER_START_ADDR;
          
          const unsigned char *FlashBlockEnd = &_MEMORY_USER_END_ADDR;

          Les deux symboles vont contenir l'adresse que je leur ai donné dans mon linker script. Alors que si je passe par

          const unsigned char *FlashBlockBegin __attribute__((section("_MEMORY_USER_START_ADDR")));
           
          
          const unsigned char *FlashBlockEnd __attribute__((section("_MEMORY_USER_END_ADDR")));

          Il stocke mes variables directement dans la RAM aux adresse 0x2xxx6c comme j'ai indiqué plus haut.

          Je ne sais pas vraiment pourquoi il fait ça, il doit y avoir une raison ....

          J'ai passé un temps de fou sur ce problème ! désolé pour les questions. Bonne journée !

          -
          Edité par heryz 24 février 2020 à 22:29:36

          • Partager sur Facebook
          • Partager sur Twitter
            25 février 2020 à 8:25:29

            L'attribut section permet de spécifier un endroit où est stockée la variable, mais pas sa valeur.

            Ces sections sont à définir dans le linker à l'aide du mot clef KEEP par exemple.

            // Linker:
            .text_application :
            {
                __text_application = .;
                KEEP(*(.app_vectors))
                ...
            }
            
            // Source:
            void *pAppVectors __attribute__((section(".app_vectors")) = { 0, 0, 0 }; 

            Dans ton cas, _MEMORY_USER_START_ADDR n'est pas une section mais une valeur, donc cela n'a aucun sens d'utiliser l’attribut section dessus.

            Le compilateur place donc cette variable là où il la placerait habituellement, soit dans la RAM pour une variable non constante ou dans la FLASH pour une variable constante.

            Comme tu l'as dis, tu ne cherches pas à ce que ton pointeur soit stocké dans une section précise (on se fiche de savoir que ce pointeur soit stocké en RAM ou en flash) mais qu'il pointe sur une section précise.

            Du coup, tu cherches simplement à lui affecter une valeur, ce qui se fait avec le signe égal, comme tu l'as évoqué dans ton précédant message.

            // Linker:
            .text_application :
            {
                __text_application = .;
                KEEP(*(.app_vectors))
                ...
            }
            
            // Source:
            extern const char *__text_application;               // Variable externe, en provenance du fichier linker
            unsigned char *pPointerApp = &__text_application;    





            -
            Edité par lorrio 25 février 2020 à 8:34:24

            • Partager sur Facebook
            • Partager sur Twitter

            Zone mémoire et linker script

            × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
            × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
            • Editeur
            • Markdown