Welche Rolle spielen .s-Dateien in einem C-Projekt?

Lesezeit: 5 Minuten

Benutzer-Avatar
Zufallsblau

Ich arbeite mit einem ARM Cortex M3-Chip (STM32F2) und ST bietet eine “Standard-Peripheriebibliothek”. Es enthält einige nützliche .c- und .h-Dateien. Es hat auch .s-Dateien.

Welchen Zweck haben diese .s-Dateien im Kontext eines C-Projekts? Wie bekomme ich meinen Compiler/Linker/? sie berücksichtigen?

Benutzer-Avatar
Clifford

Die Erweiterung .s ist die Konvention, die von GNU und vielen anderen Toolchains für Assembler-Dateien verwendet wird.

Zuletzt habe ich mir angesehen, dass die STM32 Standard Peripheral Library selbst keine Assembler-Dateien enthält, aber die CMSIS-Bibliothek enthält Startcode für verschiedene STM32-Teile, zum Beispiel startup_stm32f2xx.s ist Startcode für alle Geräte der STM32F2xx-Serie. Es gibt verschiedene Implementierungen für verschiedene Werkzeugketten; Sie müssen die Datei erstellen und verknüpfen, die Ihrem spezifischen Teil und Ihrer Werkzeugkette zugeordnet ist. Wenn Sie ein Beispielprojekt verwenden, das erstellt und ausgeführt wird, oder eine IDE, die teilespezifische Projekte für Sie erstellt, ist dies wahrscheinlich bereits geschehen – wenn Sie Code haben, der ausgeführt wird, ist dies sicherlich der Fall.

Wie Sie den Code erstellen und verknüpfen, hängt davon ab, welche Toolkette Sie verwenden. Die meisten IDE-basierten Tools erkennen die Erweiterung automatisch und rufen den Assembler auf, um eine Objektdatei zu generieren, die wie jede andere verknüpft wird. Der genaue Inhalt unterscheidet sich leicht zwischen den Toolchain-Versionen, erstellt aber hauptsächlich die C-Laufzeitumgebung (Stack und Heap), initialisiert den Prozessor, definiert eine anfängliche Interrupt-/Exception-Vektortabelle, initialisiert statische Daten und springt zu main().

Der Kern der Datei für die Keil/ARM RealView-Version sieht beispielsweise so aus:

; 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 ist die Adresse des Programmzähler (PC)-Registers, auf die nach einem Prozessor-Reset gesetzt wird.

SystemInit ist eine externe C-Code-Funktion, die den Großteil der Initialisierung durchführt – dies muss möglicherweise an Ihre Hardware angepasst werden. Cortex-M ist insofern ungewöhnlich, als er sofort nach dem Zurücksetzen mit der Ausführung von C-Code beginnen kann, da die Vektortabelle sowohl die Rücksetzadresse als auch die anfängliche Stapelzeigeradresse enthält, die beim Zurücksetzen automatisch in das SP-Register geladen wird. Infolgedessen benötigen Sie nicht viel Assembler-Kenntnisse, um einen zum Laufen zu bringen.

__main() ist der vom Compiler bereitgestellte Einstiegspunkt für Ihren C-Code. Es ist nicht die main()-Funktion, die Sie schreiben, sondern führt eine Initialisierung für die Standardbibliothek, statische Daten und den Heap durch, bevor Sie Ihre `main()’-Funktion aufrufen.

Die GCC-Version ist etwas komplizierter, da sie einen Großteil der Arbeit von erledigt __main() in der Keil/ARM RealView-Version, erfüllt aber im Wesentlichen die gleiche Funktion.

Beachten Sie das im CMSIS SystemInit() ist in system_stm32f2xx.c definiert und muss möglicherweise für Ihr Board angepasst werden (korrekte Quarzfrequenz, PLL-Setup, externe SRAM-Konfiguration usw.). Da dies C-Code ist und gut kommentiert ist, werden Sie sich wahrscheinlich damit wohler fühlen.

  • Außer ich habe gerade bemerkt, dass Sie STM32F2xx angegeben haben. Die Antwort gilt weiterhin, außer dass die jeweiligen Dateinamen in Ihrem Fall startup_stm32f2xx.s und system_stm32f2xx.c sind. Ich habe die Antwort geändert, um sie spezifischer für den STM32F2 zu machen.

    – Clifford

    22. März 2012 um 15:22 Uhr


  • Clifford – in der Dokumentation auf der ARM-Website wird erwähnt, dass die andere Routine in startup_xxx.s, __user_initial_stack_heap, nicht mehr als 88 Byte Stack verwenden sollte. Wisst ihr woher diese Einschränkung kommt? Sehen infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.kui0099a/…

    – NickHalden

    29. Oktober 2014 um 23:11 Uhr


  • @NickHalden: Glaubst du, das verdient es vielleicht, als eigene Frage gepostet zu werden? Diese Frage ist über zwei Jahre alt und nicht einmal Ihre Frage. Dafür ist der Kommentarbereich nicht da – SO ist kein Diskussionsforum. Neben; Auf diese Weise erreichen Sie ein größeres Publikum.

    – Clifford

    29. Oktober 2014 um 23:46 Uhr

  • @Clifford Nun, du hast die genaue Datei erklärt, auf die ich verwiesen habe, also fand ich es nicht zu weit hergeholt, aber ich gebe zu, dass ich nicht bemerkt habe, wie alt das ist. Ich habe hier eine neue Frage gestellt: stackoverflow.com/questions/26643465/arm-cortex-m3-startup-code. Bitte wenn möglich dort antworten, danke.

    – NickHalden

    30. Oktober 2014 um 1:19 Uhr

Sie enthalten normalerweise Assemblercode. Der Assembler verwandelt sie in Objektdateien, die später vom Linker mit dem Hauptmaterial verknüpft werden. Aber ich kann mir vorstellen, dass es vom Compiler, der Toolchain usw. abhängt.

Die .s-Dateien enthalten normalerweise die Vektortabellen. Es definiert, was das System tun soll, wenn ein Interrupt auftritt. Diese Tabelle (Code) wird in einer von Ihnen in der Linker-Datei definierten Speicheradresse abgelegt. Zum Beispiel jedes Mal, wenn ein Reset auftritt, was oder besser gesagt, wo sollte Ihr Prozessor beginnen, welchen Code sollte er ausführen. ebenso gibt es andere Handler (Interrupt-Vektoren). In STM32 schleift der Controller normalerweise bestimmte Handler. Wie im folgenden Beispiel angegeben:Siehe diesen Link für eine detaillierte Erklärung

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

Dieser Assemblercode wird später in Objektdateien konvertiert und mit Ihren .c-Dateien und .ld verknüpft, um .elf- oder .bin-Dateien zu erstellen.

Benutzer-Avatar
Craig Mc

Sie haben wahrscheinlich eine Keil-basierte Entwicklungsumgebung für Ihr ST-Kit. Abhängig von der Version Ihres Compilers sollte die Projektdatei unterschiedliche Abschnitte für C-, C++- und Assembler-Code enthalten. Öffnen Sie in Ihrer IDE Ihr Projekt und suchen Sie nach „Project Properties“ oder etwas Ähnlichem.

Sie können Symbole in und aus dem Assembler-Code importieren und exportieren, sodass dieser und der C/C++-Code verknüpft werden. Bei Keil lässt sich das alles einigermaßen gut integrieren.

Die Direktive EXPORT weist den Assembler an, das angegebene Symbol öffentlich zu machen, damit Ihr C/C++-Code darauf verlinken kann.

Die IMPORT-Direktive teilt dem Assembler mit, dass das angegebene Symbol an anderer Stelle definiert ist und zur Verbindungszeit aufgelöst wird.

1351590cookie-checkWelche Rolle spielen .s-Dateien in einem C-Projekt?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy