Подтвердить что ты не робот

Какова роль файлов .s в проекте C?

Я работаю с чипом ARM Cortex M3 (STM32F2), а ST предоставляет "стандартную периферийную библиотеку". Он имеет некоторые полезные файлы .c и .h. Он также имеет файлы .s.

Какова цель этих файлов .s в контексте проекта C? Как получить мой компилятор/компоновщик/? принять их во внимание?

4b9b3361

Ответ 1

Расширение .s - это соглашение, используемое GNU и многими другими инструментальными цепочками для файлов ассемблера.

В последнее время я смотрел, что стандартная периферийная библиотека STM32 сама по себе не содержит ассемблерных файлов, однако библиотека CMSIS содержит код запуска для различных частей STM32, например startup_stm32f2xx.s - это код запуска для всех устройств серии STM32F2xx. Существуют различные реализации для разных цепей инструментов; вам необходимо создать и связать файл, связанный с вашей конкретной частью и цепочкой инструментов. Если вы используете примерный проект, который строит и запускает, или среду IDE, которая создает для вас проекты для отдельных частей, это, вероятно, уже было сделано - если у вас есть код, который работает, он, безусловно, имеет.

Как вы создаете и связываете код, будет зависеть от того, какую цепочку инструментов вы используете. Большинство инструментов на основе IDE автоматически распознают расширение и вызывают сборщик для создания объектного файла, который будет связан как любой другой. Точный контент немного отличается между версиями цепочки инструментов, но в основном создает среду выполнения C (стек и кучу), инициализирует процессор, определяет начальную таблицу векторов прерываний/исключений, инициализирует статические данные и переходит к main().

Ядро файла для версии Keil/ARM RealView, например, выглядит следующим образом:

; 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 - адрес регистра счетчика программ (ПК) будет установлен после процессора reset.

SystemInit - это внешняя функция кода C, которая выполняет основную часть инициализации - для этого может потребоваться настройка вашего оборудования. Cortex-M необычен тем, что он может запускать код C сразу после reset, потому что векторная таблица включает в себя как адрес reset, так и адрес указателя начального стека, который автоматически загружается в регистр SP на reset. В результате вам не нужно много знаний ассемблера, чтобы запустить его.

__main() - это точка входа для компилятора для вашего C-кода. Это не основная функция(), которую вы пишете, но выполняет инициализацию стандартной библиотеки, статических данных, кучи перед вызовом функции `main().

Вариант GCC несколько более востребован, так как он выполняет большую часть работы, выполняемой __main() в версии Keil/ARM RealView, но по сути он выполняет ту же функцию.

Обратите внимание, что в CMSIS SystemInit() определяется в system_stm32f2xx.c и может потребоваться настройка вашей платы (правильная частота кристалла, настройка PLL, внешняя конфигурация SRAM и т.д.). Поскольку это код C и хорошо комментируется, вам, вероятно, будет более комфортно с ним.

Ответ 2

Обычно они содержат код сборки. Ассемблер превращает их в объектные файлы, которые позже связаны компоновщиком с основным материалом. Но я думаю, что это зависит от компилятора, инструментальной цепочки и т.д.

Ответ 3

Вероятно, вы создали среду разработки на основе Keil для своего набора ST. В зависимости от версии вашего компилятора файл проекта должен иметь разные разделы для кода C, С++ и ассемблера. В своей среде IDE откройте проект и найдите "Свойства проекта" или что-то в этом роде.

Вы можете импортировать и экспортировать символы в и из кода ассемблера, чтобы связать его и код C/С++. С Кейлом все это хорошо сочетается.

Директива EXPORT сообщает ассемблеру, чтобы сделать указанный символ общедоступным, чтобы ваш код C/С++ мог ссылаться на него.

Директива IMPORT сообщает ассемблеру, что указанный символ определен в другом месте и будет разрешен во время соединения.