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?
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.
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.
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.
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.