标准库工程

目录结构

.
├── Libraries
│   ├── CMSIS
│   └── STM32F10x_StdPeriph_Driver
│       ├── inc
│       └── src
├── makefile
├── STM32F103ZETx_FLASH.ld
└── User
    ├── led
    │   ├── bsp_led.c
    │   └── bsp_led.h
    ├── main.c
    ├── stm32f10x_conf.h
    ├── stm32f10x_it.c
    └── stm32f10x_it.h

Makefile

TARGET    := led-blink

# 存放构建时生成的文件的目录
BUILD_DIR := ./Build

# ARM GCC 工具链
TOOLCHAIN  = arm-none-eabi-
CC  := $(TOOLCHAIN)gcc
CP  := $(TOOLCHAIN)objcopy
AS  := $(TOOLCHAIN)gcc -x assembler-with-cpp
SZ  := $(TOOLCHAIN)size
HEX := $(CP) -O ihex
BIN := $(CP) -O binary -S




########################################### 标准库源码 #################################################
ASM_SRC := ./Libraries/CMSIS/CM3/DeviceSupport/ST/STM32F10x/startup/gcc_ride7/startup_stm32f10x_hd.s
C_SRC   := ./Libraries/CMSIS/CM3/CoreSupport/core_cm3.c
C_SRC   += ./Libraries/CMSIS/CM3/DeviceSupport/ST/STM32F10x/system_stm32f10x.c
C_SRC   += $(wildcard ./Libraries/STM32F10x_StdPeriph_Driver/src/*.c)

########################################### 头文件路径 #################################################
INC_DIR := ./Libraries/CMSIS/CM3/CoreSupport/
INC_DIR += ./Libraries/CMSIS/CM3/DeviceSupport/ST/STM32F10x/
INC_DIR += ./Libraries/STM32F10x_StdPeriph_Driver/inc/
INC_DIR += ./User/
INC_DIR += ./User/led/

############################################ 用户源码 ##################################################
C_SRC += $(wildcard ./User/*.c)
C_SRC += $(wildcard ./User/led/*.c)




# 内核架构
CPU := cortex-m3
# 预定义宏
DEFS := -D STM32F10X_HD  -D USE_STDPERIPH_DRIVER
# 链接脚本
LINK_SCRIPT := ./STM32F103ZETx_FLASH.ld
# 编译参数
CP_FLAGS := $(DEFS) $(addprefix -I,$(INC_DIR)) -mcpu=$(CPU) -g -gdwarf-2 -mthumb -Os -Wall -Wextra -fdata-sections -ffunction-sections -fmessage-length=0 -MMD -MP 
# 汇编参数
AS_FLAGS := $(CP_FLAGS)
# 链接参数
LD_FLAGS := -mcpu=$(CPU) -T $(LINK_SCRIPT) -specs=nano.specs -Wl,-Map=$(BUILD_DIR)/$(TARGET).map,--cref,--gc-sections,--print-memory-usage




# 设置文件搜索路径,.h 文件路径由 gcc -I 参数指定
vpath %.c $(sort $(dir $(C_SRC)))
vpath %.s $(sort $(dir $(ASM_SRC)))
# 保留 .o 文件,make 可能会删除生成的 .o 文件
.PRECIOUS: $(BUILD_DIR)/%.o




.PHONY: all
all: $(BUILD_DIR) $(BUILD_DIR)/$(TARGET).elf $(BUILD_DIR)/$(TARGET).bin $(BUILD_DIR)/$(TARGET).hex
	@echo "Done"

%.elf: $(addprefix $(BUILD_DIR)/,$(notdir $(C_SRC:.c=.o))) $(addprefix $(BUILD_DIR)/,$(notdir $(ASM_SRC:.s=.o)))
	$(CC) $(LD_FLAGS) $^ -o $@

$(BUILD_DIR)/%.o: %.c
	$(CC) -c $(CP_FLAGS) $< -o $@

$(BUILD_DIR)/%.o: %.s
	$(AS) -c $(AS_FLAGS) $< -o $@

%.hex: %.elf
	$(HEX) $< $@

%.bin: %.elf
	$(BIN) $< $@

$(BUILD_DIR):
	mkdir -p $@




clean:
	rm $(BUILD_DIR)/ -rf

st-flash: $(BUILD_DIR)/$(TARGET).bin
	st-flash --format binary write $(BUILD_DIR)/$(TARGET).bin 0x8000000

st-erase:
	st-flash erase

isp-flash: $(BUILD_DIR)/$(TARGET).bin
	stm32flash -b 115200 -i '-dtr&rts,dtr:-dtr&-rts,dtr' -v -w $(BUILD_DIR)/$(TARGET).bin /dev/ttyUSB0

isp-erase:
	stm32flash -b 115200 -i '-dtr&rts,dtr:-dtr&-rts,dtr' -o /dev/ttyUSB0

isp-info:
	stm32flash -b 115200 -i '-dtr&rts,dtr:-dtr&-rts,dtr' /dev/ttyUSB0

rebuild: clean all

install: st-flash




# 包含由 gcc -MMD 参数生成的 .d 文件
-include $(BUILD_DIR)/*.d

链接脚本

使用 STM32CubeMX 生成:

随便建个工程,按图中所示选择 Makefile 生成代码即可,STM32F103ZETx_FLASH.ld 如下:

// 设置入口符号
ENTRY(Reset_Handler)

// 初始栈顶地址
_estack = ORIGIN(RAM) + LENGTH(RAM);

// 设置堆栈大小
_Min_Heap_Size = 0x200;
_Min_Stack_Size = 0x400;

MEMORY
{
// RAM 起始地址和大小
RAM (xrw)      : ORIGIN = 0x20000000, LENGTH = 64K
// FLASH 起始地址和大小
FLASH (rx)      : ORIGIN = 0x8000000, LENGTH = 512K
}

// 后面是段的分配,一般不需要改
// 略...

GCC 编译报错

/tmp/cceEC3n9.s:599: Error: registers may not be the same -- `strexb r0,r0,[r1]'
/tmp/cceEC3n9.s:629: Error: registers may not be the same -- `strexh r0,r0,[r1]'

修改标准库中 Libraries/CMSIS/CM3/CoreSupport/core_cm3.c 文件

__STREXB__STREXH 函数中的 =r 改为 =&r ,一共有两处:

__ASM volatile ("strexb %0, %2, [%1]" : "=&r" (result) : "r" (addr), "r" (value) );

貌似是 gcc 编译优化导致的问题,参考下列文章:

GCC 参数说明

参数说明
-D STM32F10X_HD表示芯片容量
-D USE_STDPERIPH_DRIVER表示使用官方标准固件库
-mcpu=cortex-m3指定芯片内核架构
-g产生调试信息
-gdwarf-2调试信息格式
-mthumb表示使用 thumb 指令集
-Os优化代码大小
-Wall允许输出所有警告
-MMD生成依赖关系文件 .d,依赖不包括系统头文件
-MP依赖规则中的所有 .h 依赖项都会在该文件中生成一个伪目标,其不依赖任何其他依赖项
-fdata-sections为每个 data item 分配独立的 section,方便后面链接器优化
-ffunction-sections为每个 function 分配独立的 section,方便后面链接器优化
-specs=nano.specs使用精简版的 C 库替代标准 C 库,可以减少最终程序映像的大小
-T指定链接脚本
-Wl表示后面跟的参数传递给链接器,用逗号分隔
-Map=<filename>生成 map 映射文件
--crefCross Reference 的简写,输出交叉引用表
--gc-sections不链接未用函数,减小可执行文件大小

HAL 库

目录结构

.
├── Drivers
│   ├── CMSIS
│   │   ├── Device
│   │   └── Include
│   └── STM32F1xx_HAL_Driver
│       ├── Inc
│       └── Src
├── makefile
├── STM32F103ZETx_FLASH.ld
└── User
    ├── led
    │   ├── bsp_led.c
    │   └── bsp_led.h
    ├── main.c
    ├── stm32f1xx_hal_conf.h
    ├── stm32f1xx_it.c
    └── stm32f1xx_it.h