在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系统,刚刚好拿来做这个实验。

本次使用的材料:

  1. Stlink-v2
  2. 香橙派orangepiPC
  3. 一台笔记本
  4. STM32F103C8T6
  5. 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

    物联沃分享整理
    物联沃-IOTWORD物联网 » 在Linux环境下,使用Makefile编译STM32标准库工程:针对STM32F103C8T6的指南

    发表回复