Ответ 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 и хорошо комментируется, вам, вероятно, будет более комфортно с ним.