在Linux环境下,使用Makefile编译STM32标准库工程:针对STM32F103C8T6的指南
目录
前言
一、环境配置
前文疑云
环境安装
stlink驱动与make安装
编译
安装
第一种方式:回到bin的目录中安装
第二种方式:将执行文件手动复制到指定路径
arm-none-eabi-gcc安装
apt指令安装
离线安装
(1) 下载离线包
(2) 解压并安装
(3) 验证安装
(4). 配置环境变量
(5). 验证工具链完整性
检查关键文件
编译测试代码
openocd安装
1. 通过包管理器安装(推荐)
Ubuntu/Debian
Fedora
Arch Linux
2. 从源码编译安装(适合自定义功能或最新版本)
(1) 安装依赖
(2) 下载源码
(3) 配置和编译
(4) 安装到系统
3. 配置 udev 规则(解决权限问题)
4. 验证安装
(1) 检查版本
(2) 测试连接(以 ST-Link 和 STM32F1 为例)
5. 常见问题解决
Q1: 报错 No device found 或 Permission denied
Q2: 配置文件路径错误
Q3: 驱动冲突
6. 使用 OpenOCD 烧录/调试
(1) 烧录固件
(2) 启动 GDB 调试
7. 扩展配置
自定义配置文件
启用更多调试选项
二、标准库文件修改
三、Makefile文件修改
第一处—-C源文件
第二处—-启动汇编文件
第三处—-宏定义
第四处—-头文件路径
第五处—-链接文件
第六处—-清除指令
第七处—-下载指令
注意事项
前言
前几天,学习了Makefile。了解到其批量编译的作用,尝试将其转移到STM32里面的过程。再不断探索的同时实现了再Window平台成功。不过我刚好有一块在咸鱼上捡漏得到的香橙派orangepiPC,里面安装的是ubantu系统,刚刚好拿来做这个实验。
本次使用的材料:
- Stlink-v2
- 香橙派orangepiPC
- 一台笔记本
- STM32F103C8T6
- STM32F103C6T6
一、环境配置
这次我们需要三个编译环境arm-none-eabi-gcc,openocd,make,同时我们还需要上次在Window环境下的STM32的模板文件。这些文件,无论是在Window下还是Linux下都是互通的。
前文疑云
这里解答之前这两个文件的本身含义Windows环境中,脱离Keil,使用Makefile来编译标准库STM32工程 —- STM32F103C8T6-CSDN博客
如果要脱离Keil软件,采用其它方式来编写STM32,比如这里使用GCC来编译,那么这两个文件是必不可少的。
这里简单过一下,我们需要一个STM32标准库函数的模板(无论是正点原子还是自己搞的,但是一定要有),然后去STM32CubeMx生成对应芯片的Make file工程模板。如果本身就有Makefile的模板,但是还是需要CubeMX的库,你可以没有软件,但是一定要有库,这点很关键!这点关系到你的这个方法能不能再其它芯片通用。
C:\Users\用户名\STM32Cube\Repository\STM32Cube_FW_F1_V1.8.5\Drivers\CMSIS\Device\ST\STM32F1xx\Source\Templates\gcc
这个库的默认安装路径一般再这里,如果你再cubemx在线下载库的话。
这是启动文件.s
这是链接文件 .ld
对应关系:
链接脚本文件 | 启动文件 | 芯片类型 | Flash大小 | RAM大小 |
---|---|---|---|---|
STM32F100XB_FLASH.ld |
startup_stm32f100xb.s |
STM32F100xB 系列(如 STM32F100C4, STM32F100R6) | 16KB – 128KB | 4KB – 8KB |
STM32F100XE_FLASH.ld |
startup_stm32f100xe.s |
STM32F100xE 系列(如 STM32F100RC, STM32F100ZE) | 256KB – 512KB | 24KB – 32KB |
STM32F101X6_FLASH.ld |
startup_stm32f101x6.s |
STM32F101x6 系列(如 STM32F101C4, STM32F101R6) | 16KB – 32KB | 4KB – 6KB |
STM32F101XB_FLASH.ld |
startup_stm32f101xb.s |
STM32F101xB 系列(如 STM32F101C8, STM32F101RB) | 64KB – 128KB | 10KB – 16KB |
STM32F101XE_FLASH.ld |
startup_stm32f101xe.s |
STM32F101xE 系列(如 STM32F101RC, STM32F101RE) | 256KB – 512KB | 32KB – 48KB |
STM32F101XG_FLASH.ld |
startup_stm32f101xg.s |
STM32F101xG 系列(如 STM32F101RG, STM32F101VG) | 512KB – 1MB | 48KB – 80KB |
STM32F102X6_FLASH.ld |
startup_stm32f102x6.s |
STM32F102x6 系列(如 STM32F102C4, STM32F102R6) | 16KB – 32KB | 4KB – 6KB |
STM32F102XB_FLASH.ld |
startup_stm32f102xb.s |
STM32F102xB 系列(如 STM32F102C8, STM32F102RB) | 64KB – 128KB | 10KB – 16KB |
STM32F103X6_FLASH.ld |
startup_stm32f103x6.s |
STM32F103x6 系列(如 STM32F103C6, STM32F103R6) | 32KB | 6KB |
STM32F103XB_FLASH.ld |
startup_stm32f103xb.s |
STM32F103xB 系列(如 STM32F103C8, STM32F103RB) (包含 STM32F103C8T6) |
64KB – 128KB | 20KB |
STM32F103XE_FLASH.ld |
startup_stm32f103xe.s |
STM32F103xE 系列(如 STM32F103RC, STM32F103RE) | 256KB – 512KB | 48KB – 64KB |
STM32F103XG_FLASH.ld |
startup_stm32f103xg.s |
STM32F103xG 系列(如 STM32F103RG, STM32F103VG) | 512KB – 1MB | 64KB – 96KB |
STM32F105XC_FLASH.ld |
startup_stm32f105xc.s |
STM32F105xC 系列(如 STM32F105R8, STM32F105VC) (互联型,带 USB OTG) |
64KB – 256KB | 64KB |
STM32F107XC_FLASH.ld |
startup_stm32f107xc.s |
STM32F107xC 系列(如 STM32F107RB, STM32F107VC) (互联型,带以太网) |
256KB | 64KB |
这里贴出我使用的Makefile文件,作为模板使用
##########################################################################################################################
# File automatically-generated by tool: [projectgenerator] version: [4.3.0-B58] date: [Fri Mar 14 19:48:43 CST 2025]
##########################################################################################################################
# ------------------------------------------------
# Generic Makefile (based on gcc)
#
# ChangeLog :
# 2017-02-10 - Several enhancements + project update mode
# 2015-07-22 - first version
# ------------------------------------------------
######################################
# target
######################################
TARGET = make_again
######################################
# building variables
######################################
# debug build?
DEBUG = 1
# optimization
OPT = -Og
#######################################
# paths
#######################################
# Build path
BUILD_DIR = build
######################################
# source
######################################
#第一处需要修改的地方
# C sources
C_SOURCES = \
$(wildcard ./CMSIS/*.c) \
$(wildcard ./Library/src/*.c) \
$(wildcard ./Library/inc/*.c) \
$(wildcard ./Start/*.c) \
$(wildcard ./User/*.c)
# ASM sources
#如果更换芯片,这里需要更换对应的芯片类型
ASM_SOURCES = \
startup_stm32f103xb.s
# ASM sources
ASMM_SOURCES =
#######################################
# 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 = \
-DSTM32F10X_MD\
-DUSE_STDPERIPH_DRIVER
# AS includes
AS_INCLUDES =
# C includes
#第三处需要修改的地方
C_INCLUDES = \
-ICMSIS\
-ILibrary/inc\
-ILibrary/src\
-IStart\
-IUser
# 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)))
OBJECTS += $(addprefix $(BUILD_DIR)/,$(notdir $(ASMM_SOURCES:.S=.o)))
vpath %.S $(sort $(dir $(ASMM_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)/%.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
#######################################
#第四处需要修改的地方
ifeq ($(OS),Windows_NT)
RM = rmdir /S /Q
else
RM = rm -rf
endif
clean:
-$(RM) $(BUILD_DIR)
#######################################
# download
#######################################
download:
openocd -f "/usr/share/openocd/scripts/interface/stlink-v2.cfg" -f "/usr/share/openocd/scripts/target/stm32f1x.cfg" -c init -c halt -c "program $(BUILD_DIR)/$(TARGET).hex verify reset" -c shutdown
#######################################
# dependencies
#######################################
-include $(wildcard $(BUILD_DIR)/*.d)
# *** EOF ***
环境安装
我们需要在Linux环境中安装三个主要的环境:
arm-none-eabi-gcc —- 编译STM32的必要编译器
openocd —- 使用Stlink烧入的工具
make —- 批量编译文件的工具
在这里介绍Stlink驱动如何在Linux环境下编译安装
stlink驱动与make安装
这里stlink驱动与make同时安装是因为,在安装stlink要使用make或者cmake工具,所以这里一起下载。闲言到此,我们开始吧!这里使用的是ubantu环境。
编译
首先我们简单安装一下必要的依赖。按照下面顺序开始复制粘贴,如果提示某些软件并没有安装,那么就apt install xxx安装它。
sudo apt update
sudo apt install git cmake make gcc
sudo apt install libusb-1.0-0-dev libgtk-3-dev build-essential
然后爬取stlink官方的源码,编译安装。当然如果自己有源码,那么你可以上传到ubantu上面然后编译安装,本质都是一样的。
git clone https://github.com/stlink-org/stlink
爬完之后,简单看一下里面有什么。并且我们为什么要这样操作。 cd进去
cd stlink
ls -1
看到没,这里有一个Makefile文件哦,这里也就意味着,我们在本机使用make编译,然后生成stlink驱动,然后安装这个生成的驱动。如果有能力,你甚至可以自己去自定义自己的stlink驱动,这就是开源软件的魅力!好了,闲话少说,开始下一步,编译。
cmake .
make
编译完成之后,得看情况。有些正在这里会生成bin文件,有些人会生成build文件。这要根据你编译的文件有关,不过共同点是,在这个新生成的文件里面一直进去,一定有下面的文件
这里面的bin有我们需要的东西。这些st开头的可执行文件。
安装
这里应该有两个安装方式,两个方法都可以试试。
第一种方式:回到bin的目录中安装
因为在生成的文件夹里面,也有一个Makefile文件,我们可以利用这个文件来操作。
sudo make install
检验是否安装成功,在ubantu主机中插入stlink,然后执行
lsusb
如果显示如下,则代表安装成功。
第二种方式:将执行文件手动复制到指定路径
cd bin
sudo cp st-* /usr/local/bin
cd ../lib
#这里个人认为,得看文件目录里面有没有lib64,如果没有,复制到lib路径试试
sudo cp *.so* /lib64
观察上面,它把*.so*文件复制到如下路径:
-- Up-to-date: /usr/local/lib/libstlink.so.1.8.0
-- Up-to-date: /usr/local/lib/libstlink.so.1
-- Up-to-date: /usr/local/lib/libstlink.so
具体怎么解读,各位如果有知道的,可以告诉我。
最后判断是否安装成功的逻辑是一样的。
lsusb
到达这里,我们完成了stlink驱动的安装,还有make等工具安装。
arm-none-eabi-gcc安装
arm-none-eabi-gcc有两种安装方式,apt指令安装,根据自己的情况,选择其中一个即可。
apt指令安装
如果直接输入
apt install arm-none-eabi-gcc
,可能系统或者软件源的关系,可能不能马上安装。
可以按照下面流程来安装:
apt search arm-gcc
这个命令可以找到对应本系统可以安装的软件,所以输入之后,找到对应的软件。然后安装
apt install arm-none-eabi-gcc
除了这个还要安装对应的库,建议直接执行下面的指令。一般就不会少东西了。
sudo apt update
sudo apt install gcc-arm-none-eabi libnewlib-arm-none-eabi
这是卸载指令
sudo apt remove --purge gcc-arm-none-eabi
sudo rm -rf /usr/lib/arm-none-eabi /usr/lib/gcc/arm-none-eabi
离线安装
(1) 下载离线包
从其他设备访问 Arm GNU Toolchain Downloads,选择适合的版本:
Linux 64-bit: gcc-arm-none-eabi-<版本>-x86_64-linux.tar.bz2
Linux ARM 32-bit: gcc-arm-none-eabi-<版本>-aarch64-linux.tar.bz2
(需要根据实际架构选择)
(2) 解压并安装
将下载的包复制到目标设备,解压并安装:
# 解压到 /opt
sudo tar -xjf gcc-arm-none-eabi-*.tar.bz2 -C /opt
# 创建符号链接
sudo ln -s /opt/gcc-arm-none-eabi-*/bin/* /usr/local/bin/
# 复制库文件到系统路径
sudo cp -r /opt/gcc-arm-none-eabi-*/arm-none-eabi/lib /usr/lib/arm-none-eabi/
(3) 验证安装
arm-none-eabi-gcc --version
# 输出应显示版本信息
ls /usr/lib/arm-none-eabi/lib/libc.a /usr/lib/arm-none-eabi/lib/crt0.o
# 确认标准库和启动文件存在
(4). 配置环境变量
将工具链路径添加到 PATH 中(如果未自动配置):
echo 'export PATH="/opt/gcc-arm-none-eabi/bin:$PATH"' >> ~/.bashrc
source ~/.bashrc
(5). 验证工具链完整性
检查关键文件
/usr/lib/arm-none-eabi/lib/libc.a # C 标准库
/usr/lib/arm-none-eabi/lib/libm.a # 数学库
/usr/lib/arm-none-eabi/lib/libnosys.a # 裸机系统调用库
/usr/lib/arm-none-eabi/lib/crt0.o # 启动文件
编译测试代码
创建一个简单的测试程序 test.c
:
int main()
{
return 0;
}
编译并验证:
arm-none-eabi-gcc -mcpu=cortex-m3 -mthumb -specs=nosys.specs -TSTM32F103C8Tx_FLASH.ld test.c -o test.elf
如果编译成功且无报错,说明工具链安装完整。
openocd安装
1. 通过包管理器安装(推荐)
Ubuntu/Debian
sudo apt update
sudo apt install openocd
Fedora
sudo dnf install openocd
Arch Linux
sudo pacman -S openocd
2. 从源码编译安装(适合自定义功能或最新版本)
(1) 安装依赖
# Ubuntu/Debian
sudo apt install build-essential autoconf libtool pkg-config libusb-1.0-0-dev git
# Fedora
sudo dnf install gcc automake autoconf libtool pkgconfig libusb1-devel git
# Arch Linux
sudo pacman -S base-devel autoconf automake pkgconf libusb git
(2) 下载源码
git clone https://git.code.sf.net/p/openocd/code openocd
cd openocd
./bootstrap # 生成配置脚本
(3) 配置和编译
./configure --enable-stlink --enable-jlink --enable-cmsis-dap
make -j$(nproc)
(4) 安装到系统
sudo make install
3. 配置 udev 规则(解决权限问题)
创建文件 /etc/udev/rules.d/90-openocd.rules
,添加以下内容:
# ST-Link
ATTRS{idVendor}=="0483", ATTRS{idProduct}=="3748", MODE="0666", GROUP="plugdev"
# J-Link
ATTRS{idVendor}=="1366", ATTRS{idProduct}=="0101", MODE="0666", GROUP="plugdev"
# CMSIS-DAP(如 Raspberry Pi Pico)
ATTRS{idVendor}=="2e8a", MODE="0666", GROUP="plugdev"
重新加载规则:
sudo udevadm control --reload-rules
sudo udevadm trigger
sudo usermod -aG plugdev $USER # 将当前用户加入 plugdev 组
4. 验证安装
(1) 检查版本
openocd --version
# 输出示例:Open On-Chip Debugger 0.12.0
(2) 测试连接(以 ST-Link 和 STM32F1 为例)
openocd -f interface/stlink-v2.cfg -f target/stm32f1x.cfg
成功连接后输出类似:
Info : stm32f1x.cpu: hardware has 6 breakpoints, 4 watchpoints
5. 常见问题解决
Q1: 报错 No device found
或 Permission denied
检查权限:
lsusb | grep "ST-Link\|J-Link" # 确认设备识别
groups # 确认用户是否在 plugdev 组
重新加载 udev 规则:
sudo udevadm control --reload
sudo udevadm trigger
Q2: 配置文件路径错误
查找配置文件路径:
find /usr -name "stlink-v2.cfg" # 包管理器安装的路径
find /usr/local -name "stlink-v2.cfg" # 源码安装的路径
指定完整路径:
openocd -f /usr/share/openocd/scripts/interface/stlink-v2.cfg -f target/stm32f1x.cfg
Q3: 驱动冲突
禁用 ModemManager(部分系统会占用 USB 设备):
sudo systemctl stop ModemManager
sudo systemctl disable ModemManager
6. 使用 OpenOCD 烧录/调试
(1) 烧录固件
openocd -f interface/stlink-v2.cfg -f target/stm32f1x.cfg \
-c "program firmware.bin exit 0x08000000"
(2) 启动 GDB 调试
arm-none-eabi-gdb firmware.elf
(gdb) target extended-remote :3333
(gdb) monitor reset halt
(gdb) load
(gdb) continue
7. 扩展配置
自定义配置文件
创建自定义配置文件(如 my_board.cfg
),定义接口和目标:
# my_board.cfg
source [find interface/stlink-v2.cfg]
source [find target/stm32f1x.cfg]
运行:
openocd -f my_board.cfg
启用更多调试选项
在配置命令中添加参数:
# 启用详细日志
openocd -d3 -f interface/stlink-v2.cfg -f target/stm32f1x.cfg
# 指定自定义端口
openocd -c "gdb_port 3334" -c "telnet_port 4445" -f ...
通过以上步骤,你可以在 Linux 上完成 OpenOCD 的安装和基础配置,支持 STM32 等设备的调试与烧录。
二、标准库文件修改
这里的情况与前文在Window下的环境遇到的问题类似,
Windows环境中,脱离Keil,使用Makefile来编译标准库STM32工程 —- STM32F103C8T6-CSDN博客这里依然需要采用换函数的办法。因为我目前除了把那两个函数删掉,就是换函数。
找到你的STM32的工程模板,然后找到core_cm3。然后再大概730多行的地方,把这两个函数换掉。
//换完之后
uint32_t __STREXB(uint8_t value, uint8_t *addr)
{
uint32_t result;
register uint8_t *tmp_addr asm("r1") = addr;
register uint8_t tmp_value asm("r2") = value;
__ASM volatile (
"strexb %0, %2, [%1]"
: "=r" (result)
: "r" (tmp_addr), "r" (tmp_value)
: // No clobbered registers
);
return result;
}
uint32_t __STREXH(uint16_t value, uint16_t *addr)
{
uint32_t result;
register uint16_t *tmp_addr asm("r1") = addr;
register uint16_t tmp_value asm("r2") = value;
__ASM volatile (
"strexh %0, %2, [%1]"
: "=r" (result)
: "r" (tmp_addr), "r" (tmp_value)
: // No clobbered registers
);
return result;
}
换掉之后,这里的任务就完成了。
三、Makefile文件修改
Makefile文件,修改。这里有些细节还是必须修改的。这里主要有7处必须改的地方,我会一一指出。其中4个与前文是类似的。Windows环境中,脱离Keil,使用Makefile来编译标准库STM32工程 —- STM32F103C8T6-CSDN博客
那么开始吧!
如果文件结构与我一样,就按照我的规则来。改成我们模式,这里可以以点带面,你可以模仿我来改自己的makefile文件!
第一处—-C源文件
全部路径加入,不过里面有没有.C文件。两个字:省事!
# C sources
C_SOURCES = \
$(wildcard ./CMSIS/*.c) \
$(wildcard ./Library/src/*.c) \
$(wildcard ./Library/inc/*.c) \
$(wildcard ./Start/*.c) \
$(wildcard ./User/*.c)
第二处—-启动汇编文件
这个没有技巧,只能去找自己芯片适配的启动文件。这里这个启动文件刚好适配STM32F103C8T6.
链接脚本文件 启动文件 芯片类型 Flash大小 RAM大小 STM32F100XB_FLASH.ld
startup_stm32f100xb.s
STM32F100xB 系列(如 STM32F100C4, STM32F100R6) 16KB – 128KB 4KB – 8KB STM32F100XE_FLASH.ld
startup_stm32f100xe.s
STM32F100xE 系列(如 STM32F100RC, STM32F100ZE) 256KB – 512KB 24KB – 32KB STM32F101X6_FLASH.ld
startup_stm32f101x6.s
STM32F101x6 系列(如 STM32F101C4, STM32F101R6) 16KB – 32KB 4KB – 6KB STM32F101XB_FLASH.ld
startup_stm32f101xb.s
STM32F101xB 系列(如 STM32F101C8, STM32F101RB) 64KB – 128KB 10KB – 16KB STM32F101XE_FLASH.ld
startup_stm32f101xe.s
STM32F101xE 系列(如 STM32F101RC, STM32F101RE) 256KB – 512KB 32KB – 48KB STM32F101XG_FLASH.ld
startup_stm32f101xg.s
STM32F101xG 系列(如 STM32F101RG, STM32F101VG) 512KB – 1MB 48KB – 80KB STM32F102X6_FLASH.ld
startup_stm32f102x6.s
STM32F102x6 系列(如 STM32F102C4, STM32F102R6) 16KB – 32KB 4KB – 6KB STM32F102XB_FLASH.ld
startup_stm32f102xb.s
STM32F102xB 系列(如 STM32F102C8, STM32F102RB) 64KB – 128KB 10KB – 16KB STM32F103X6_FLASH.ld
startup_stm32f103x6.s
STM32F103x6 系列(如 STM32F103C6, STM32F103R6) 32KB 6KB STM32F103XB_FLASH.ld
startup_stm32f103xb.s
STM32F103xB 系列(如 STM32F103C8, STM32F103RB)
(包含 STM32F103C8T6)64KB – 128KB 20KB STM32F103XE_FLASH.ld
startup_stm32f103xe.s
STM32F103xE 系列(如 STM32F103RC, STM32F103RE) 256KB – 512KB 48KB – 64KB STM32F103XG_FLASH.ld
startup_stm32f103xg.s
STM32F103xG 系列(如 STM32F103RG, STM32F103VG) 512KB – 1MB 64KB – 96KB STM32F105XC_FLASH.ld
startup_stm32f105xc.s
STM32F105xC 系列(如 STM32F105R8, STM32F105VC)
(互联型,带 USB OTG)64KB – 256KB 64KB STM32F107XC_FLASH.ld
startup_stm32f107xc.s
STM32F107xC 系列(如 STM32F107RB, STM32F107VC)
(互联型,带以太网)256KB 64KB
所以这里选择startup_stm32f103xb.s,如果你的文件不在User、CMSIS外层,那么你也应该加入对应的路径,比如:它再User里面的话,这里就要改成:
./User/startup_stm32f103xb.s
这里其实可以以点带面去找到其它芯片对应的文件,进而再理论上来说,所有的STM32应该都可以通过这种方式去编译!
# ASM sources
ASM_SOURCES = \
startup_stm32f103xb.s
第三处—-宏定义
编译STM32修改定义对应的宏,这里定义了两个宏。如果是其它系列的芯片,这里也是要更改的。这里务必注意。
STM32F10X_MD 表明本次使用的是F10X系列的芯片,中等规格
USE_STDPERIPH_DRIVER 表明使用标准库函数来编译
# C defines
#第二处需要修改的地方
C_DEFS = \
-DSTM32F10X_MD\
-DUSE_STDPERIPH_DRIVER
第四处—-头文件路径
全部路径加入,不过里面有没有.H文件。两个字:省事!
# C includes
#第三处需要修改的地方
C_INCLUDES = \
-ICMSIS\
-ILibrary/inc\
-ILibrary/src\
-IStart\
-IUser
第五处—-链接文件
这个没有技巧,只能去找自己芯片适配的链接文件。这里这个启动文件刚好适配STM32F103C8T6.这个与启动文件是息息相关的,相互存在。至少再gcc环境下编译,这两个文件缺一不可。
#######################################
# LDFLAGS
#######################################
# link script
LDSCRIPT = STM32F103C8Tx_FLASH.ld
第六处—-清除指令
封装一下清除指令,提高一下再Window与Linux系统的兼容性。
执行时,只需要:
make clean
#######################################
# clean up
#######################################
#第四处需要修改的地方
ifeq ($(OS),Windows_NT)
RM = rmdir /S /Q
else
RM = rm -rf
endif
clean:
-$(RM) $(BUILD_DIR)
第七处—-下载指令
每次执行下载,都要输入长长的一段openocd的指令,那么我们封装起来,不是更好。
执行命令:
make download
这是烧录二进制文件,要指定起始地址烧录,一般地址是0x08000000
#######################################
# download
#######################################
download:
openocd -f "/usr/share/openocd/scripts/interface/stlink-v2.cfg" -f "/usr/share/openocd/scripts/target/stm32f1x.cfg" -c init -c halt -c "program $(BUILD_DIR)/$(TARGET).bin 0x08000000 verify reset" -c shutdown
下面为烧录十六进制文件,不用指定起始地址。
#######################################
# download
#######################################
download:
openocd -f "/usr/share/openocd/scripts/interface/stlink-v2.cfg" -f "/usr/share/openocd/scripts/target/stm32f1x.cfg" -c init -c halt -c "program $(BUILD_DIR)/$(TARGET).hex verify reset" -c shutdown
这里也是贴出完整的配置的Make file文件,这个和前面那个基本差不多。
##########################################################################################################################
# File automatically-generated by tool: [projectgenerator] version: [4.3.0-B58] date: [Fri Mar 14 19:48:43 CST 2025]
##########################################################################################################################
# ------------------------------------------------
# Generic Makefile (based on gcc)
#
# ChangeLog :
# 2017-02-10 - Several enhancements + project update mode
# 2015-07-22 - first version
# ------------------------------------------------
######################################
# target
######################################
TARGET = make_again
######################################
# building variables
######################################
# debug build?
DEBUG = 1
# optimization
OPT = -Og
#######################################
# paths
#######################################
# Build path
BUILD_DIR = build
######################################
# source
######################################
#第一处需要修改的地方
# C sources
C_SOURCES = \
$(wildcard ./CMSIS/*.c) \
$(wildcard ./Library/src/*.c) \
$(wildcard ./Library/inc/*.c) \
$(wildcard ./Start/*.c) \
$(wildcard ./User/*.c)
# ASM sources
ASM_SOURCES = \
startup_stm32f103xb.s
# ASM sources
ASMM_SOURCES =
#######################################
# 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 = \
-DSTM32F10X_MD\
-DUSE_STDPERIPH_DRIVER
# AS includes
AS_INCLUDES =
# C includes
#第三处需要修改的地方
C_INCLUDES = \
-ICMSIS\
-ILibrary/inc\
-ILibrary/src\
-IStart\
-IUser
# 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)))
OBJECTS += $(addprefix $(BUILD_DIR)/,$(notdir $(ASMM_SOURCES:.S=.o)))
vpath %.S $(sort $(dir $(ASMM_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)/%.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
#######################################
#第四处需要修改的地方
ifeq ($(OS),Windows_NT)
RM = rmdir /S /Q
else
RM = rm -rf
endif
clean:
-$(RM) $(BUILD_DIR)
#######################################
# download
#######################################
download:
openocd -f "/usr/share/openocd/scripts/interface/stlink-v2.cfg" -f "/usr/share/openocd/scripts/target/stm32f1x.cfg" -c init -c halt -c "program $(BUILD_DIR)/$(TARGET).hex verify reset" -c shutdown
#######################################
# dependencies
#######################################
-include $(wildcard $(BUILD_DIR)/*.d)
# *** EOF ***
注意事项
1.对应的芯片,对应的启动文件与链接文件。不能弄混,不然跑的程序即便烧录也可能无法显示出理想的状况。不过貌似同系列更高规格的程序兼容低规格的程序,比如:STM32F103C8T6兼容STM32F103C6T6的程序,不过低规格无法兼容高规格。
2.用apt安装arm-none-eabi-gcc时,一定要把对应的库也安装到。工具链一定要完整,否则会出现各种问题让你无法通过编译。
3.目前只在STM32F103C8T6与STM32F103C6T6上实现,不过理论上,这套方法应该可以兼容全系列的芯片。受限于环境,各位可以勇敢的去尝试。
作者:timing994