使用CMake编译stm32f103并烧录

1. 交叉编译工具安装

ubuntu中下载arm-none-eabi-gcc交叉编译工具,安装过程省略,并将arm-none-eabi-gcc所在文件夹添加到path,验证:

arm-none-eabi-gcc -v

2.使用STM32生成Makefile版本项目,编译烧录测试

2.1生成项目并编译

  1. stm32cubeMX生成代码时选择Makefile,复制到ubuntu环境,或者直接在ubuntu中的stm32cubeMX生成

  2. 内容如下:
    在这里插入图片描述

  3. 终端中打开文件夹输入make命令,会使用之前安装的arm-none-eabi交叉编译工具链编译,生成elf、bin、hex格式的文件
    在这里插入图片描述

2.2STM32CubeProg烧录

  1. stlink连接到ubuntu主机,右上角选择ST-LINK,Seraial number点击圆圈刷新,Connect点击连接,左上方点击+加号打开文件,生成的elf或hex都可以。
    在这里插入图片描述
  2. 点击Download下载,下载完成后程序未运行,需要断开连接Disconnect,开发板重启后程序运行

3.使用CMake编译

文件夹内容:
在这里插入图片描述

3.1根据Makefile文件编写CMakeLists.txt

  1. 生成的Makefile
##########################################################################################################################
# File automatically-generated by tool: [projectgenerator] version: [4.1.0] date: [Sun Nov 17 10:10:13 CST 2024]
##########################################################################################################################
# ------------------------------------------------
# Generic Makefile (based on gcc)
#
# ChangeLog :
#	2017-02-10 - Several enhancements + project update mode
#   2015-07-22 - first version
# ------------------------------------------------
######################################
# target
######################################
TARGET = 20230411GPIO_3
######################################
# building variables
######################################
# debug build?
DEBUG = 1
# optimization
OPT = -Og
#######################################
# paths
#######################################
# Build path
BUILD_DIR = build
######################################
# source
######################################
# C sources
C_SOURCES =  \
Core/Src/main.c \
Core/Src/stm32f1xx_it.c \
Core/Src/stm32f1xx_hal_msp.c \
Core/Src/stm32f1xx_hal_timebase_tim.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_gpio_ex.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_tim.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_tim_ex.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_rcc.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_rcc_ex.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_gpio.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_dma.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_cortex.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_pwr.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_flash.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_flash_ex.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_exti.c \
Core/Src/system_stm32f1xx.c  

# ASM sources
ASM_SOURCES =  \
startup_stm32f103xb.s
#######################################
# binaries
#######################################
PREFIX = arm-none-eabi-
# The gcc compiler bin path can be either defined in make command via GCC_PATH variable (> make GCC_PATH=xxx)
# either it can be added to the PATH environment variable.
ifdef GCC_PATH
CC = $(GCC_PATH)/$(PREFIX)gcc
AS = $(GCC_PATH)/$(PREFIX)gcc -x assembler-with-cpp
CP = $(GCC_PATH)/$(PREFIX)objcopy
SZ = $(GCC_PATH)/$(PREFIX)size
else
CC = $(PREFIX)gcc
AS = $(PREFIX)gcc -x assembler-with-cpp
CP = $(PREFIX)objcopy
SZ = $(PREFIX)size
endif
HEX = $(CP) -O ihex
BIN = $(CP) -O binary -S
#######################################
# CFLAGS
#######################################
# cpu
CPU = -mcpu=cortex-m3
# fpu

# NONE for Cortex-M0/M0+/M3
# float-abi
# mcu

MCU = $(CPU) -mthumb $(FPU) $(FLOAT-ABI)
# macros for gcc

# AS defines
AS_DEFS = 
# C defines
C_DEFS =  \
-DUSE_HAL_DRIVER \
-DSTM32F103xB
# AS includes
AS_INCLUDES = 
# C includes
C_INCLUDES =  \
-ICore/Inc \
-IDrivers/STM32F1xx_HAL_Driver/Inc \
-IDrivers/STM32F1xx_HAL_Driver/Inc/Legacy \
-IDrivers/CMSIS/Device/ST/STM32F1xx/Include \
-IDrivers/CMSIS/Include
# compile gcc flags
ASFLAGS = $(MCU) $(AS_DEFS) $(AS_INCLUDES) $(OPT) -Wall -fdata-sections -ffunction-sections
CFLAGS += $(MCU) $(C_DEFS) $(C_INCLUDES) $(OPT) -Wall -fdata-sections -ffunction-sections

ifeq ($(DEBUG), 1)
CFLAGS += -g -gdwarf-2
endif
# Generate dependency information
CFLAGS += -MMD -MP -MF"$(@:%.o=%.d)"
#######################################
# LDFLAGS
#######################################
# link script
LDSCRIPT = STM32F103C8Tx_FLASH.ld
# libraries
LIBS = -lc -lm -lnosys 
LIBDIR = 
LDFLAGS = $(MCU) -specs=nano.specs -T$(LDSCRIPT) $(LIBDIR) $(LIBS) -Wl,-Map=$(BUILD_DIR)/$(TARGET).map,--cref -Wl,--gc-sections
# default action: build all
all: $(BUILD_DIR)/$(TARGET).elf $(BUILD_DIR)/$(TARGET).hex $(BUILD_DIR)/$(TARGET).bin
#######################################
# build the application
#######################################
# list of objects
OBJECTS = $(addprefix $(BUILD_DIR)/,$(notdir $(C_SOURCES:.c=.o)))
vpath %.c $(sort $(dir $(C_SOURCES)))
# list of ASM program objects
OBJECTS += $(addprefix $(BUILD_DIR)/,$(notdir $(ASM_SOURCES:.s=.o)))
vpath %.s $(sort $(dir $(ASM_SOURCES)))
$(BUILD_DIR)/%.o: %.c Makefile | $(BUILD_DIR) 
	$(CC) -c $(CFLAGS) -Wa,-a,-ad,-alms=$(BUILD_DIR)/$(notdir $(<:.c=.lst)) $< -o $@
$(BUILD_DIR)/%.o: %.s Makefile | $(BUILD_DIR)
	$(AS) -c $(CFLAGS) $< -o $@
$(BUILD_DIR)/$(TARGET).elf: $(OBJECTS) Makefile
	$(CC) $(OBJECTS) $(LDFLAGS) -o $@
	$(SZ) $@
$(BUILD_DIR)/%.hex: $(BUILD_DIR)/%.elf | $(BUILD_DIR)
	$(HEX) $< $@
$(BUILD_DIR)/%.bin: $(BUILD_DIR)/%.elf | $(BUILD_DIR)
	$(BIN) $< $@		
$(BUILD_DIR):
	mkdir $@		
#######################################
# clean up
#######################################
clean:
	-rm -fR $(BUILD_DIR)  
#######################################
# dependencies
#######################################
-include $(wildcard $(BUILD_DIR)/*.d)
# *** EOF ***

3.2编写的CMakeLists.txt文件

cmake_minimum_required(VERSION 3.14)

# 项目信息# 指定工程名称和语言类型,后面三个一定要加,特别是ASM不加不会加载.s启动文件
project(20230411GPIO_3 C CXX ASM )#

SET(CMAKE_SYSTEM_NAME Generic)
SET(CMAKE_SYSTEM_PROCESSOR cortex-m3)#这个不重要,arm也能行
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)

# 设置 CMake 输出目录
set(CMAKE_BINARY_DIR ${CMAKE_SOURCE_DIR}/bin)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin)

# 定义 STM32F103xB 作为目标设备
add_definitions(-DSTM32F103xB)
add_definitions(-DDUSE_HAL_DRIVER)

# 设置编译器和工具链路径(确保 arm-none-eabi 工具链已安装并正确配置)
set(CMAKE_C_COMPILER arm-none-eabi-gcc)
set(CMAKE_CXX_COMPILER arm-none-eabi-g++)
set(CMAKE_ASM_COMPILER arm-none-eabi-gcc)
set(CMAKE_AR arm-none-eabi-ar)
set(CMAKE_OBJCOPY arm-none-eabi-objcopy)
set(CMAKE_SZ arm-none-eabi-size)



set(CMAKE_CXX_STANDARD 17)
set(CMAKE_C_STANDARD 11)

# STM32 系列 MCU 配置
set(MCU_FLAGS "-mcpu=cortex-m3 -mthumb ")
set(FPU_FLAGS "")
set(LINKER_SCRIPT "${CMAKE_SOURCE_DIR}/STM32F103C8Tx_FLASH.ld")
#set(LIBS "-lc -lm -lnosys")#不使用操作系统时可不添加库
 

# 添加源文件路径
set(C_SOURCES
    Core/Src/main.c
    Core/Src/stm32f1xx_it.c
    Core/Src/stm32f1xx_hal_msp.c
    Core/Src/stm32f1xx_hal_timebase_tim.c
    Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_gpio_ex.c
    Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_tim.c
    Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_tim_ex.c
    Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal.c
    Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_rcc.c
    Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_rcc_ex.c
    Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_gpio.c
    Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_dma.c
    Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_cortex.c
    Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_pwr.c
    Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_flash.c
    Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_flash_ex.c
    Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_exti.c
    Core/Src/system_stm32f1xx.c
)
#启动文件
set(ASM_SOURCES
    "${CMAKE_SOURCE_DIR}/startup_stm32f103xb.s"
)

# 设置 CFLAGS
set(CMAKE_C_FLAGS "${MCU_FLAGS} ${FPU_FLAGS} -Wall -fdata-sections -ffunction-sections -Og")

# 添加调试选项(如果是调试构建)
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -gdwarf-2")
endif()

# 设置汇编文件的编译标志
set(CMAKE_ASM_FLAGS "${MCU_FLAGS} ${FPU_FLAGS} -x assembler-with-cpp -Wall -fdata-sections -ffunction-sections -Og")

# 添加包含路径
include_directories(
    Core/Inc
    Drivers/STM32F1xx_HAL_Driver/Inc
    Drivers/STM32F1xx_HAL_Driver/Inc/Legacy
    Drivers/CMSIS/Device/ST/STM32F1xx/Include
    Drivers/CMSIS/Include
)

# 创建目标文件(对象文件)
add_executable(${PROJECT_NAME}.elf ${C_SOURCES} ${ASM_SOURCES})



# 设置链接选项
target_link_options(${PROJECT_NAME}.elf PRIVATE
    -T ${LINKER_SCRIPT}
    -specs=nano.specs
    ${LIBS}
    -Wl,-Map=${CMAKE_BINARY_DIR}/${PROJECT_NAME}.map,--cref
    -Wl,--gc-sections
)


# 添加生成 .hex 和 .bin 文件的自定义命令
add_custom_command(TARGET ${PROJECT_NAME}.elf POST_BUILD
    COMMAND ${CMAKE_OBJCOPY} -O ihex ${CMAKE_BINARY_DIR}/${PROJECT_NAME}.elf ${CMAKE_BINARY_DIR}/${PROJECT_NAME}.hex
    COMMAND ${CMAKE_OBJCOPY} -O binary -S ${CMAKE_BINARY_DIR}/${PROJECT_NAME}.elf ${CMAKE_BINARY_DIR}/${PROJECT_NAME}.bin
)

# 设置清理命令
add_custom_target(clean-all
    COMMAND rm -rf ${CMAKE_BINARY_DIR}/*
    COMMAND rm -rf ${CMAKE_BINARY_DIR}/*.elf
    COMMENT "Cleaning build files..."
)


3.3编译运行

  1. 创建bin文件夹mkdir bin

  2. cd bin

  3. cmake … && make生成Makefile文件并编译
    在这里插入图片描述

  4. 可知在/bin文件夹中生成了elf文件,用章节2的方法使用STM32CubeProgramer烧录

  5. 之后要修改文件使用CMake比Makefile更加方便