web-dev-qa-db-fra.com

Quel est le rôle de fichiers .s dans un projet C?

Je travaille avec un ARM Cortex M3 (STM32F2) et ST fournit une "bibliothèque périphérique standard". Il a des fichiers utiles .C et .h. Il a aussi des fichiers .s.

Quel est le but de ces fichiers .s dans le contexte d'un projet C? Comment puis-je obtenir mon compilateur/mayer /? pour les prendre en compte?

23
Randomblue

L'extension .s est la convention utilisée par GNU et de nombreuses autres chaînes d'outils pour les fichiers d'assembleur.

Dernièrement, j'ai regardé la bibliothèque périphérique standard STM32 ne contient aucun fichier d'assembleur, mais la bibliothèque CMSIS contient du code de démarrage pour différentes pièces STM32, par exemple STERTUP_STM32F2XX.S est un code de démarrage pour tous les périphériques de la série STM32F2XX. Il existe différentes implémentations pour différentes chaînes d'outils; Vous devez créer et relier le fichier associé à votre pièce et à une chaîne d'outils spécifique. Si vous utilisez un exemple de projet qui construit et exécute ou un IDE==== Crée des projets spécifiques à une pièce à part, cela aura probablement déjà été fait - si vous avez du code qui le gère certainement.

Comment vous construisez et liez le code dépendra de la chaîne d'outils que vous utilisez. La plupart IDE OUTOY OUTOYS reconnaît automatiquement l'extension et invoquera l'assembleur pour générer un fichier d'objet qui sera lié comme n'importe un autre. Le contenu exact diffère légèrement entre les versions de la chaîne d'outils, mais crée principalement la C environnement d'exécution (pile et tas) initialise le processeur, définit une table de vecteur d'interruption/exception initiale, initialise des données statiques et des sauts à la main ().

Le noyau du fichier pour la version de View View Keil/ARM par exemple ressemble à ceci:

; Reset handler
Reset_Handler    PROC
                 EXPORT  Reset_Handler             [WEAK]
        IMPORT  SystemInit
        IMPORT  __main
                 LDR     R0, =SystemInit
                 BLX     R0
                 LDR     R0, =__main
                 BX      R0
                 ENDP

Reset_Handler Le registre du programme d'adressage (PC) sera défini sur après une réinitialisation du processeur.

SystemInit est une fonction de code C externe qui fait la majeure partie de l'initialisation - cela peut avoir besoin de personnalisation pour votre matériel. Cortex-M est inhabituel en ce qu'il peut commencer à exécuter le code C immédiatement après la réinitialisation car le tableau de vecteur inclut à la fois l'adresse de réinitialisation et l'adresse de pointeur de pile initiale, qui est automatiquement chargée sur SP Inscrivez-vous sur réinitialiser. En conséquence, vous n'avez pas besoin de beaucoup de connaissances de l'assembleur pour obtenir une course à pied.

__main() est le point d'entrée fourni compilateur pour votre code C. Ce n'est pas la fonction principale () que vous écrivez, mais effectue l'initialisation de la bibliothèque standard, des données statiques, du tas avant d'appeler votre fonction `Main () '.

La version GCC est quelque peu plus impliquée car elle fait une grande partie du travail effectué par __main() dans la version View de Keil/Bras, mais essentiellement la même fonction.

Notez que dans la CMSIS SystemInit() est définie dans System_STM32F2XX.C, et peut avoir besoin de personnalisation de votre carte (fréquence cristalline correcte, configuration PLL, configuration sram externe, etc.). Parce que c'est C code C et bien a commenté, vous serez probablement plus à l'aise avec cela.

35
Clifford

Ils contiennent généralement du code de montage. L'assembleur les transforme dans des fichiers d'objet qui sont ensuite liés par la liaison avec le truc principal. Mais j'imagine que cela dépend du compilateur, de la boîte à outils, etc.

8
cnicutar

Les fichiers .s contiennent généralement les tables de vecteur. Il définit ce que le système devrait faire quand une interruption se produit. Cette table (code) est placée dans une adresse de mémoire définie par vous dans le fichier de liaison. Par exemple, chaque fois qu'une réinitialisation se produit ou plutôt où votre processeur devrait-il commencer, quel code devrait-il fonctionner. De même, il existe d'autres gestionnaires (vecteurs d'interruption). Dans la STM32, le contrôleur boucle généralement sur des gestionnaires particuliers. Comme indiqué dans l'exemple ci-dessous: voir ce lien pour une explication détaillée

    .section INTERRUPT_VECTOR, "x"
    .global _Reset
    _Reset:
      B Reset_Handler /* Reset */
      B . /* Undefined */
      B . /* SWI */
      B . /* Prefetch Abort */
      B . /* Data Abort */
      B . /* reserved */
      B . /* IRQ */
      B . /* FIQ */

    Reset_Handler:
      LDR sp, =stack_top
      BL c_entry
      B .

Ce code d'assemblage ultérieurement est converti en fichiers d'objet et liés à vos fichiers .c et .ld pour créer des fichiers .OF ou .bin.

2
Chandrika Joshi

Vous avez probablement un environnement de développement basé sur Keil pour votre kit St. Selon la version de votre compilateur, le fichier de projet doit avoir différentes sections pour C, C++ et le code de l'assembleur. Dans votre IDE, ouvrez votre projet et recherchez "Propriétés du projet" ou quelque chose comme ça.

Vous pouvez importer et exporter des symboles vers et depuis le code de l'assembleur de sorte que le code C/C++ soit associé. Avec Keil, tout cela s'intègre tout à fait bien.

La directive à l'exportation indique à l'assembleur de rendre le symbole spécifié public de sorte que votre code C/C++ puisse être associé à celui-ci.

La directive d'importation indique à l'assembleur que le symbole spécifié est défini ailleurs et sera résolu au moment de la liaison.

1
Craig Mc