We followed a different process. I followed a typical C project process to the end. Then delete main.c, and instead include main.S.
I will also choose CMSIS as part of the set-up.
I eventually wrote a small piece of code (h2inc) that generated stm32f0xx.inc from stm32f0xx.h to retain the base addresses. That header file is then included in the main.S to provide base addresses for the code.
Using CMSIS has the advantage of having access to SystemInit() and SystemCoreClockUpdate(), as having your stack / heap set up by the start-up file automatically.
My code looks like this:
.include "stm32f0xx.inc"
.syntax unified
.thumb
@system defines
@RCC offsets
.equ RCC_AHBENR_OFF, 0x14 @ahbner offset
@gpio offsets
.equ GPIO_MODER_OFF, 0x00 @gpio moder offset
.equ GPIO_OTYPER_OFF, 0x04 @output type
.equ GPIO_ODR_OFF, 0x14 @output data register
.equ GPIO_BSRR_OFF, 0x18 @output bit set / reset register
.equ GPIO_BRR_OFF, 0x28 @output bit reset register
@global defines
.equ LED_PORT, GPIOC_BASE @led on gpioc
.equ LED_A, (1<<1) @led anode on pin1
.equ LED_C, (1<<2) @led cathode on pin2
@global variables
.global main @so it gets called from CMSIS
.type main, %function
@.text @declare it in the code section
main:
@user main starts here
init:
@initialize the chip
@enable clock to gpioc
ldr R0, =RCC_BASE @read rcc base address into r0
ldr R1, [R0, #RCC_AHBENR_OFF] @read ahbner register into R1
ldr R2, =RCC_AHBENR_GPIOCEN
orrs R2, R2, R1 @set GPIOCEN bit, R2 | R1 -> R2
str R2, [R0, #RCC_AHBENR_OFF] @update ahbner register
The bulk of the code compiled is actually in the .inc file - almost 400k and 5000+ lines - many of it is actually masked off.
Unfortunately, there is no way to calculate the offsets so you have to manually set them up.