linux环境下搭建stm32工程
·
一、核心步骤概览
- 准备工具链:安装交叉编译器 arm-none-eabi-gcc。
- 获取固件库:从 ST 官网下载 STM32F1xx 标准外设库。
- 创建工程结构:在你的工作目录下建立清晰的文件夹。
- 拷贝文件:从固件库中复制所需的核心文件到你的工程中。
- 编写代码:创建main.c和链接脚本等关键文件。
- 编译与链接:使用make命令自动构建生成.elf、.hex和.bin文件。
详细操作步骤
第 1 步:安装交叉编译工具链
打开终端,执行以下命令安装:
sudo apt update
sudo apt install gcc-arm-none-eabi binutils-arm-none-eabi gdb-arm-none-eabi
第 2 步:创建工程目录结构
假设你的工程名为 my_stm32_project,在你的工作目录下执行:
mkdir -p my_stm32_project/{src,inc,lib/{CMSIS,SPL},ld,build}
这会创建一个包含源文件 (src)、头文件 (inc)、库文件 (lib) 等的清晰结构。
第 3 步:拷贝固件库文件
假设你已下载并解压了固件库,解压后的路径为 STM32F10x_StdPeriph_Lib_V3.5.0。请按以下清单将文件从固件库拷贝到你的工程中:
- 拷贝 CMSIS 核心文件
# 内核核心头文件
cp STM32F10x_StdPeriph_Lib_V3.5.0/Libraries/CMSIS/CM3/CoreSupport/core_cm3.h my_stm32_project/lib/CMSIS/
cp STM32F10x_StdPeriph_Lib_V3.5.0/Libraries/CMSIS/CM3/CoreSupport/core_cm3.c my_stm32_project/lib/CMSIS/
# 设备特定文件 (选择你的芯片系列,这里以F10x为例)
cp STM32F10x_StdPeriph_Lib_V3.5.0/Libraries/CMSIS/CM3/DeviceSupport/ST/STM32F10x/stm32f10x.h my_stm32_project/lib/CMSIS/
cp STM32F10x_StdPeriph_Lib_V3.5.0/Libraries/CMSIS/CM3/DeviceSupport/ST/STM32F10x/system_stm32f10x.c my_stm32_project/lib/CMSIS/
# 启动文件 (根据你的芯片容量选择,这里以中容量(MD)为例)
cp STM32F10x_StdPeriph_Lib_V3.5.0/Libraries/CMSIS/CM3/DeviceSupport/ST/STM32F10x/startup/gcc_ride7/startup_stm32f10x_md.s my_stm32_project/lib/CMSIS/
- 拷贝 SPL 外设驱动文件
# SPL 核心头文件
cp STM32F10x_StdPeriph_Lib_V3.5.0/Libraries/STM32F10x_StdPeriph_Driver/inc/*.h my_stm32_project/lib/SPL/
# SPL 核心源文件
cp STM32F10x_StdPeriph_Lib_V3.5.0/Libraries/STM32F10x_StdPeriph_Driver/src/*.c my_stm32_project/lib/SPL/
- 拷贝用户配置模板
cp STM32F10x_StdPeriph_Lib_V3.5.0/Project/STM32F10x_StdPeriph_Template/stm32f10x_conf.h my_stm32_project/inc/
cp STM32F10x_StdPeriph_Lib_V3.5.0/Project/STM32F10x_StdPeriph_Template/stm32f10x_it.h my_stm32_project/inc/
cp STM32F10x_StdPeriph_Lib_V3.5.0/Project/STM32F10x_StdPeriph_Template/stm32f10x_it.c my_stm32_project/src/
第 4 步:创建关键工程文件
- 创建主程序文件 src/main.c
这是一个简单的 LED 闪烁示例:
#include "stm32f10x.h" // 包含所有外设头文件
// 假设LED连接在PC13引脚上
#define LED_PIN GPIO_Pin_13
#define LED_PORT GPIOC
void delay_ms(volatile uint32_t count) {
while(count--) { __NOP(); }
}
int main(void) {
// 1. 使能GPIOC时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
// 2. 配置PC13为推挽输出
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = LED_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; // 推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(LED_PORT, &GPIO_InitStructure);
while (1) {
// 3. 翻转LED状态
GPIO_WriteReverse(LED_PORT, LED_PIN);
delay_ms(500000); // 简单延时
}
}
- 创建链接脚本 ld/stm32f103.ld
这个文件定义了程序在 Flash 和 RAM 中的存储布局。
/* STM32F103C8T6链接脚本 (中低密度芯片) */
MEMORY
{
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 64K /* 64KB Flash */
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 20K /* 20KB RAM */
}
_estack = 0x20005000; /* 栈顶地址 (20KB RAM的结束地址) */
SECTIONS
{
/* 中断向量表 */
.isr_vector :
{
. = ALIGN(4);
KEEP(*(.isr_vector)) /* 保留中断向量表 */
. = ALIGN(4);
} >FLASH
/* 代码段 */
.text :
{
. = ALIGN(4);
*(.text) /* 程序代码 */
*(.text*) /* 函数模板实例化代码 */
*(.glue_7) /* ARM与Thumb代码混合胶水代码 */
*(.glue_7t) /* ARM与Thumb代码混合胶水代码 */
*(.eh_frame)
KEEP (*(.init))
KEEP (*(.fini))
. = ALIGN(4);
_etext = .; /* 代码段结束地址 */
} >FLASH
/* 初始化数据在Flash中的存储位置 */
.data_init :
{
_sidata = .; /* 初始化数据的起始地址 (关键符号,解决undefined reference错误) */
*(.data_init)
} >FLASH
/* 初始化数据段 (加载到RAM) */
.data : AT (_sidata)
{
. = ALIGN(4);
_sdata = .; /* 数据段起始地址 */
*(.data) /* 初始化数据 */
*(.data*) /* 初始化数据 */
. = ALIGN(4);
_edata = .; /* 数据段结束地址 */
} >RAM
/* 未初始化数据段 */
.bss :
{
. = ALIGN(4);
_sbss = .; /* BSS段起始地址 */
*(.bss) /* 未初始化数据 */
*(.bss*) /* 未初始化数据 */
*(COMMON) /* 公共未初始化数据 */
. = ALIGN(4);
_ebss = .; /* BSS段结束地址 */
} >RAM
/* 用户堆空间 */
.heap :
{
. = ALIGN(4);
_heap_start = .; /* 堆起始地址 */
. += 2048; /* 堆大小2KB,根据需要调整 */
_heap_end = .; /* 堆结束地址 */
. = ALIGN(4);
} >RAM
}
- 创建 Makefile
这是自动化编译的核心。将下面的内容保存为 my_stm32_project/Makefile。
# --- 项目配置 ---
PROJECT = my_stm32_app
BUILD_DIR = build
SRC_DIR = src
LIB_DIR = lib
INC_DIR = inc
LD_DIR = ld
# --- 工具链配置 ---
CC = /opt/arm-none-eabi/bin/arm-none-eabi-gcc
OBJCOPY = /opt/arm-none-eabi/bin/arm-none-eabi-objcopy
OBJDUMP = /opt/arm-none-eabi/bin/arm-none-eabi-objdump
SIZE = /opt/arm-none-eabi/bin/arm-none-eabi-size
# --- 芯片与编译选项 ---
# 根据你的芯片型号修改,这里是STM32F103C8T6
CFLAGS = -mcpu=cortex-m3 -mthumb -msoft-float
CFLAGS += -DSTM32F10X_MD -DUSE_STDPERIPH_DRIVER
CFLAGS += -Wall -Wextra -O2 -g
CFLAGS += -ffunction-sections -fdata-sections
# --- 头文件路径 ---
INCLUDES = -I$(INC_DIR)
INCLUDES += -I$(LIB_DIR)/CMSIS
INCLUDES += -I$(LIB_DIR)/SPL
# --- 源文件列表 ---
# 1. 用户源文件
SRCS += $(wildcard $(SRC_DIR)/*.c)
# 2. CMSIS源文件
SRCS += $(LIB_DIR)/CMSIS/system_stm32f10x.c
# 3. SPL源文件
SRCS += $(wildcard $(LIB_DIR)/SPL/*.c)
# --- 目标文件 ---
OBJS = $(SRCS:%.c=$(BUILD_DIR)/%.o)
# 4. 启动文件 (汇编)
STARTUP_SRC = $(LIB_DIR)/CMSIS/startup_stm32f10x_md.s
STARTUP_OBJ = $(BUILD_DIR)/$(STARTUP_SRC:.s=.o)
# --- 链接选项 ---
LDFLAGS = -T$(LD_DIR)/stm32f103c8.ld
LDFLAGS += -mcpu=cortex-m3 -mthumb -msoft-float
LDFLAGS += -Wl,--gc-sections # 链接时去除未使用的代码和数据
# --- 目标 ---
all: $(BUILD_DIR)/$(PROJECT).elf $(BUILD_DIR)/$(PROJECT).hex $(BUILD_DIR)/$(PROJECT).bin
# 链接生成.elf文件
$(BUILD_DIR)/$(PROJECT).elf: $(OBJS) $(STARTUP_OBJ)
@mkdir -p $(@D)
$(CC) $(LDFLAGS) $^ -o $@
$(SIZE) $@
# 生成.hex文件
$(BUILD_DIR)/$(PROJECT).hex: $(BUILD_DIR)/$(PROJECT).elf
$(OBJCOPY) -O ihex $< $@
# 生成.bin文件
$(BUILD_DIR)/$(PROJECT).bin: $(BUILD_DIR)/$(PROJECT).elf
$(OBJCOPY) -O binary $< $@
# 编译C文件
$(BUILD_DIR)/%.o: %.c
@mkdir -p $(@D)
$(CC) $(CFLAGS) $(INCLUDES) -c $< -o $@
# 编译汇编启动文件
$(BUILD_DIR)/%.o: %.s
@mkdir -p $(@D)
$(CC) $(CFLAGS) -c $< -o $@
# 清理
clean:
rm -rf $(BUILD_DIR)
# 伪目标
.PHONY: all clean
第 5 步:编译工程
进入你的工程根目录 my_stm32_project,执行 make 命令:
cd my_stm32_project
make
如果一切顺利,你将在 build/ 目录下看到生成的 my_stm32_app.elf, my_stm32_app.hex, 和 my_stm32_app.bin 文件。
更多推荐



所有评论(0)