Zig 工具链编译 STM32 开发指南
参考仓库 :ZigEmbeddedGroup/stmicro-stm32
本项目为 STM32 提供 Zig 嵌入式开发支持,全程使用 Zig 原生工具链,无需额外安装 ARM GCC 交叉编译器。
目录
- 环境准备
- [仓库与 build.zig 简介](#仓库与 build.zig 简介)
- 编译官方示例工程
- 固件烧录(ST-Link)
- [基于 build.zig 创建自定义工程](#基于 build.zig 创建自定义工程)
- [调试:OpenOCD + Zig GDB](#调试:OpenOCD + Zig GDB)
- 常见问题
- 参考资料
1. 环境准备
1.1 安装 Zig
访问 Zig 官网下载对应操作系统的 Zig 二进制包,推荐使用仓库兼容的稳定版本。
Zig 内置交叉编译能力,不需要单独安装 arm-none-eabi-gcc。
验证安装:
bash
zig version
1.2 克隆 stmicro-stm32 仓库
bash
git clone https://github.com/ZigEmbeddedGroup/stmicro-stm32.git
cd stmicro-stm32
仓库目录结构:
text
stmicro-stm32/
├── build.zig # 核心构建脚本
├── build.zig.zon # 依赖清单
├── src/ # 芯片寄存器定义、启动文件、底层支持
├── examples/ # 示例项目(blink 点灯等)
└── README.md
2. 仓库与 build.zig 简介
build.zig 是 Zig 的构建脚本,作用等同于 C/C++ 开发中的 CMakeLists.txt 或 Makefile。仓库内 build.zig 主要完成以下工作:
- 定义嵌入式目标架构 :ARM Cortex-M(
thumbv7m-none-eabi) - 加载链接脚本 :引入
.ld文件,配置 Flash、RAM 内存地址布局 - 引入底层文件:加载芯片启动汇编文件、寄存器定义
- 设置编译选项:配置无标准库(freestanding)、优化等级、链接垃圾回收
- 自动生成固件 :输出
.elf和.bin文件
注意:嵌入式环境为 freestanding,不依赖 libc。
3. 编译官方示例工程
3.1 编译点灯示例 blink
bash
# 指定示例 blink + 指定芯片 stm32f103c8t6
zig build -Dexample=blink -Dchip=stm32f103c8t6
参数说明:
-Dexample=xxx:选择examples/目录下的示例名称-Dchip=xxx:指定 STM32 芯片型号
3.2 编译产物说明
编译输出目录位于 zig-out/firmware/:
firmware.elf:带调试信息的 ELF 文件,用于 GDB 调试firmware.bin:纯二进制固件,用于烧录到芯片 Flash
查看产物命令:
bash
ls zig-out/firmware/
4. 固件烧录(ST-Link)
安装 stlink 工具集后,使用 st-flash 进行烧录。
bash
# 将 bin 固件烧录到 STM32 Flash 起始地址 0x08000000
st-flash write zig-out/firmware/firmware.bin 0x8000000
# 复位芯片,运行程序
st-flash reset
备选方案:也可以使用 OpenOCD 进行烧录。
5. 基于 build.zig 创建自定义工程
新建工程最简 build.zig 模板如下:
zig
const std = @import("std");
pub fn build(b: *std.Build) void {
// 嵌入式目标配置 Cortex-M3
const target = b.standardTargetOptions(.{
.default_target = .{
.cpu_arch = .thumb,
.cpu_model = .{ .explicit = &std.Target.arm.cpu.cortex_m3 },
.os = .freestanding,
.abi = .eabi,
},
});
const optimize = b.standardOptimizeOption(.{ .default = .ReleaseSmall });
// 创建可执行固件
const exe = b.addExecutable(.{
.name = "my_firmware",
.root_source_file = b.path("src/main.zig"),
.target = target,
.optimize = optimize,
.strip = false,
});
// 嵌入式关键配置
exe.setLinkerScript(b.path("stm32f103.ld"));
exe.addAssemblyFile(b.path("src/startup_stm32f103.s"));
exe.link_gc_sections = true;
exe.link_data_sections = true;
// 生成 .bin 文件
const bin = b.addObjCopy(exe, .{
.format = .bin,
});
bin.step.dependOn(&exe.step);
b.installArtifact(bin);
// 安装 ELF
b.installArtifact(exe);
}
6. 调试:OpenOCD + Zig GDB
第一步:启动 OpenOCD
在新终端中运行以下命令:
bash
openocd -f interface/stlink.cfg -f target/stm32f1x.cfg
第二步:启动 Zig GDB
在另一个终端中运行:
bash
zig gdb zig-out/firmware/firmware.elf
第三步:GDB 调试指令
进入 GDB 交互界面后,依次执行:
text
(gdb) target remote :3333
(gdb) monitor reset halt
(gdb) load
(gdb) continue
7. 常见问题
7.1 链接报错:找不到内存区域
原因 :检查链接脚本 .ld 中的 Flash/RAM 大小是否和你实际使用的芯片匹配。
7.2 烧录成功,芯片不运行
原因:
- 确认启动文件 startup 汇编、中断向量表配置是否正确。
- 确认 Flash 起始地址是否为
0x08000000。
7.3 编译提示无法使用 libc 函数
原因:嵌入式是 freestanding 环境,没有 libc,必须使用 Zig 无标准库写法。
8. 参考资料
- stmicro-stm32 仓库
- Zig 构建系统官方文档
- Zig Embedded Group:Zig 嵌入式社区