A Makefile => Makefile +52 -0
@@ 0,0 1,52 @@
+DEVICE?=stm32f446
+CPU?=cortex-m4
+
+APP=blink.elf
+
+BINDIR=bin
+SRCDIR=src
+INCDIR=include
+OBJDIR=obj
+
+DEVICEDIR=devices/$(DEVICE)
+GENERALDIR=devices/general
+
+PROJSRCS=$(wildcard $(SRCDIR)/*.c)
+GENERALSRCS=$(wildcard $(GENERALDIR)/*.c)
+DEVICESRCS=$(wildcard $(DEVICEDIR)/*.c)
+
+SRCS=$(PROJSRCS) $(GENERALSRCS) $(DEVICESRCS)
+OBJS=$(patsubst %.c,obj/%.o,$(SRCS))
+
+CFLAGS=-I$(INCDIR) -I$(DEVICEDIR)/$(INCDIR) -mthumb -mcpu=$(CPU) -nostdlib
+LDFLAGS=-T$(DEVICEDIR)/linker_script.ld -nostdlib
+
+CC=arm-none-eabi-gcc
+LD=arm-none-eabi-ld
+OPENOCD=openocd
+
+$(BINDIR)/$(APP): $(OBJS)
+ mkdir -p $(BINDIR)
+ $(LD) $^ -o $@ $(LDFLAGS)
+
+$(OBJDIR)/src/%.o: $(SRCDIR)/%.c
+ mkdir -p "$(OBJDIR)/src"
+ $(CC) -c $< -o $@ $(CFLAGS)
+
+$(OBJDIR)/$(DEVICEDIR)/%.o: $(DEVICEDIR)/%.c
+ mkdir -p "$(OBJDIR)/$(DEVICEDIR)"
+ $(CC) -c $< -o $@ $(CFLAGS)
+
+$(OBJDIR)/$(GENERALDIR)/%.o: $(GENERALDIR)/%.c
+ mkdir -p "$(OBJDIR)/$(GENERALDIR)"
+ $(CC) -c $< -o $@ $(CFLAGS)
+
+.PHONY: openocd flash clean
+openocd:
+ $(OPENOCD) -f interface/stlink.cfg -f target/stm32f4x.cfg
+
+flash: $(BINDIR)/$(APP)
+ $(OPENOCD) -f interface/stlink.cfg -f target/stm32f4x.cfg -c "program $(BINDIR)/$(APP) verify reset exit"
+
+clean:
+ rm -rf $(OBJDIR) $(BINDIR)
A devices/general/startup.c => devices/general/startup.c +29 -0
@@ 0,0 1,29 @@
+#include <stdint.h>
+#include "defines.h"
+
+extern uint32_t _etext, _sdata, _edata, _sbss, _ebss;
+void main(void);
+
+void reset_handler(void)
+{
+ // Copy .data from FLASH to SRAM
+ uint32_t data_size = (uint32_t)&_edata - (uint32_t)&_sdata;
+ uint8_t *flash_data = (uint8_t*) &_etext;
+ uint8_t *sram_data = (uint8_t*) &_sdata;
+
+ for (uint32_t i = 0; i < data_size; i++)
+ {
+ sram_data[i] = flash_data[i];
+ }
+
+ // Zero-fill .bss section in SRAM
+ uint32_t bss_size = (uint32_t)&_ebss - (uint32_t)&_sbss;
+ uint8_t *bss = (uint8_t*) &_sbss;
+
+ for (uint32_t i = 0; i < bss_size; i++)
+ {
+ bss[i] = 0;
+ }
+
+ main();
+}
A src/main.c => src/main.c +36 -0
@@ 0,0 1,36 @@
+#include <stdint.h>
+
+#define PERIPHERAL_BASE (0x40000000U)
+#define AHB1_BASE (PERIPHERAL_BASE + 0x20000U)
+#define GPIOA_BASE (AHB1_BASE + 0x0U)
+#define RCC_BASE (AHB1_BASE + 0x3800U)
+
+#define RCC_AHB1ENR_OFFSET (0x30U)
+#define RCC_AHB1ENR ((volatile uint32_t*) (RCC_BASE + RCC_AHB1ENR_OFFSET))
+#define RCC_AHB1ENR_GPIOAEN (0x00U)
+
+#define GPIO_MODER_OFFSET (0x00U)
+#define GPIOA_MODER ((volatile uint32_t*) (GPIOA_BASE + GPIO_MODER_OFFSET))
+#define GPIO_MODER_MODER5 (10U)
+#define GPIO_ODR_OFFSET (0x14U)
+#define GPIOA_ODR ((volatile uint32_t*) (GPIOA_BASE + GPIO_ODR_OFFSET))
+
+#define LED_PIN 5
+
+void main()
+{
+ *RCC_AHB1ENR |= (1 << RCC_AHB1ENR_GPIOAEN);
+
+ // do two dummy reads after enabling the peripheral clock, as per the errata
+ volatile uint32_t dummy;
+ dummy = *(RCC_AHB1ENR);
+ dummy = *(RCC_AHB1ENR);
+
+ *GPIOA_MODER |= (1 << GPIO_MODER_MODER5);
+
+ while(1)
+ {
+ *GPIOA_ODR ^= (1 << LED_PIN);
+ for (uint32_t i = 0; i < 500000; i++);
+ }
+}