3. 开发环境搭建:交叉编译工具链与调试工具

做嵌入式移植,第一件事就是把开发环境搭起来。这事看着简单,但我在项目里见过太多人卡在这一步——工具链版本不对、调试器连不上、串口乱码,一折腾就是半天。说白了,环境搭好了,后面的事就顺了。

这一章,我把 ARM 和 RISC-V 两套工具链的安装配置、三种常用调试器(OpenOCD、JLink、ST-Link)的使用方法,还有串口终端工具的选择,一次性讲清楚。都是实战里摸爬滚打出来的经验,你照着做就行。

开发环境搭建知识体系 嵌入式开发环境 交叉编译工具链 调试工具 串口终端工具 ARM GCC (arm-none-eabi) RISC-V GCC (riscv64-unknown-elf) OpenOCD JLink / ST-Link Minicom PuTTY 核心思路 在宿主机(x86)上编译目标架构(ARM/RISC-V)的代码,通过调试器下载到板子,用串口观察输出。

3.1 交叉编译工具链:为什么需要它?

你想想看,你的电脑是 x86 架构,但嵌入式板子通常是 ARM 或 RISC-V。x86 编译出来的二进制,ARM 芯片根本跑不了。所以我们需要交叉编译——在宿主机上生成目标架构的可执行文件。

我个人习惯用 GNU Arm Embedded Toolchain 和 RISC-V GNU Toolchain。这两个都是社区广泛使用的,稳定可靠。

3.1.1 ARM GCC 安装

以 Ubuntu 20.04/22.04 为例,我推荐直接从 ARM 官网下载预编译包,而不是用 apt 安装——apt 里的版本往往比较老。

# 下载 ARM GCC 10.3-2021.10 版本(64位)
wget https://developer.arm.com/-/media/Files/downloads/gnu-rm/10.3-2021.10/gcc-arm-none-eabi-10.3-2021.10-x86_64-linux.tar.bz2

# 解压到 /opt 目录
sudo tar -xjf gcc-arm-none-eabi-10.3-2021.10-x86_64-linux.tar.bz2 -C /opt/

# 添加环境变量(写入 ~/.bashrc 或 ~/.zshrc)
export PATH=$PATH:/opt/gcc-arm-none-eabi-10.3-2021.10/bin

# 验证安装
arm-none-eabi-gcc --version
小提示: 我建议把环境变量写到 ~/.bashrc 里,而不是 /etc/profile。这样每个用户独立配置,不会互相影响。之前有个同事把路径写到了系统级配置里,结果另一个项目用了不同版本的工具链,冲突了。

3.1.2 RISC-V GCC 安装

RISC-V 的工具链稍微复杂一点。你可以选择预编译包,也可以自己从源码编译。我个人建议用预编译的,省时间。

# 下载 RISC-V GCC 预编译包(SiFive 官方提供)
wget https://static.dev.sifive.com/dev-tools/riscv64-unknown-elf-gcc-8.3.0-2020.04.1-x86_64-linux-ubuntu14.tar.gz

# 解压
sudo tar -xzf riscv64-unknown-elf-gcc-8.3.0-2020.04.1-x86_64-linux-ubuntu14.tar.gz -C /opt/

# 环境变量
export PATH=$PATH:/opt/riscv64-unknown-elf-gcc-8.3.0-2020.04.1/bin

# 验证
riscv64-unknown-elf-gcc --version
注意: RISC-V 工具链有 riscv64-unknown-elf 和 riscv64-unknown-linux-gnu 两种。前者用于裸机或 RTOS 开发,后者用于带 Linux 内核的系统。别搞混了。我曾经在裸机项目里用了 linux-gnu 版本,链接时一堆莫名其妙的错误。

3.2 调试工具:OpenOCD、JLink、ST-Link

工具链装好了,代码能编译了。但怎么把程序烧到板子上?怎么调试?这就轮到调试工具上场了。

这三种调试器,我基本都用过。简单说:JLink 最贵也最稳,ST-Link 是 STM32 的标配,OpenOCD 是开源万金油。

调试器 接口协议 支持架构 速度 价格 适用场景
JLink SWD / JTAG ARM (Cortex-M/A/R) 最高 50 MHz 高(几百到几千) 商业项目、高频调试
ST-Link SWD / JTAG ARM (STM32 系列) 最高 4 MHz 低(几十元) STM32 开发、学习
OpenOCD SWD / JTAG ARM / RISC-V 取决于硬件 免费(软件) 多架构、自定义调试

3.2.1 OpenOCD 安装与配置

OpenOCD 是个好东西。它本身是个软件,配合 FT2232、CMSIS-DAP 等硬件调试器使用。我经常用它调试 RISC-V 的板子。

# 从源码编译安装(推荐,可以获得最新版本)
git clone https://github.com/openocd-org/openocd.git
cd openocd
./bootstrap
./configure --enable-ftdi --enable-stlink --enable-jlink
make -j4
sudo make install

# 验证
openocd --version

配置文件的写法,我举个例子。假设你用的是 STM32F4 开发板 + ST-Link 调试器:

# stm32f4.cfg
source [find interface/stlink.cfg]
source [find target/stm32f4x.cfg]

# 设置 SWD 模式
transport select hla_swd

# 设置工作频率
adapter speed 4000

启动 OpenOCD:

openocd -f stm32f4.cfg
实战经验: 我第一次用 OpenOCD 调试 RISC-V 板子时,发现连不上。折腾了半天,最后发现是配置文件里 target 选错了——RISC-V 的 target 是 riscv.cfg,不是 ARM 的。嗯,这种坑踩过一次就记住了。

3.2.2 JLink 使用要点

JLink 是 Segger 公司的产品,稳定性和速度都没得说。安装 JLink 软件包后,主要用两个工具:JLinkExe(命令行)和 JLinkGDBServer(GDB 服务器)。

# 启动 JLink GDB Server(监听端口 2331)
JLinkGDBServer -device STM32F407VG -if SWD -speed 4000 -port 2331

# 然后在另一个终端启动 GDB
arm-none-eabi-gdb
(gdb) target remote localhost:2331
(gdb) load my_program.elf
(gdb) continue
注意: JLink 的 -device 参数必须写对。写错了,轻则连不上,重则烧坏芯片。我见过有人把 STM32F103 写成了 STM32F407,结果 JTAG 时序不对,芯片直接锁死了。

3.2.3 ST-Link 快速上手

ST-Link 是 ST 官方调试器,买 STM32 开发板基本都送。用起来最简单:

# 安装 ST-Link 工具(Ubuntu)
sudo apt install stlink-tools

# 烧录程序
st-flash write my_program.bin 0x8000000

# 启动 GDB 服务器
st-util

# 另一个终端连接 GDB
arm-none-eabi-gdb
(gdb) target remote localhost:4242
(gdb) load my_program.elf

3.3 串口终端工具:Minicom 与 PuTTY

调试器负责烧录和单步调试,但板子跑起来之后,总得有个地方看打印信息吧?串口终端就是干这个的。

我个人在 Linux 下用 Minicom,Windows 下用 PuTTY。两个都够用,选你顺手的就行。

3.3.1 Minicom 配置(Linux)

# 安装
sudo apt install minicom

# 启动配置
sudo minicom -s

# 进入配置菜单后:
# 1. 选择 "Serial port setup"
# 2. 设置 A - Serial Device: /dev/ttyUSB0(根据实际设备修改)
# 3. 设置 E - Bps/Par/Bits: 115200 8N1
# 4. 设置 F - Hardware Flow Control: No
# 5. 设置 G - Software Flow Control: No
# 6. 退出配置,选择 "Save setup as dfl" 保存为默认配置

# 启动
minicom
小技巧: 如果不知道串口设备是哪个,先拔掉 USB 转串口,执行 ls /dev/ttyUSB*,再插上,多出来的那个就是。我每次接新板子都这么干。

3.3.2 PuTTY 配置(Windows)

PuTTY 不需要安装,下载 exe 直接运行。配置步骤:

  1. Connection type 选择 Serial
  2. Serial line 填写 COM3(在设备管理器里查看实际端口)
  3. Speed 填写 115200
  4. 点击左侧 Category 里的 Serial,确认 Flow control 为 None
  5. 点击 Open 连接
避坑指南: 串口连上了但全是乱码?别慌。先检查波特率对不对——板子用 115200,你设成 9600,肯定乱码。再检查数据位和校验位,大部分嵌入式设备都是 8N1。如果还不行,看看板子的串口 TX 和 RX 有没有接反。我曾经在调试一块新板子时,乱码折腾了半小时,最后发现是 TX 和 RX 焊反了。

3.4 环境验证:一个完整的测试流程

工具都装好了,怎么确认环境没问题?我建议你写一个最简单的程序,编译、烧录、看输出,走通全流程。

// test.c
#include <stdio.h>

int main() {
    printf("Hello, Embedded World!\n");
    return 0;
}

编译(以 ARM 为例):

arm-none-eabi-gcc -mcpu=cortex-m4 -mthumb -nostartfiles -T link.ld -o test.elf test.c
arm-none-eabi-objcopy -O binary test.elf test.bin

烧录(以 ST-Link 为例):

st-flash write test.bin 0x8000000

打开 Minicom 或 PuTTY,复位板子,你应该能看到:

Hello, Embedded World!

看到这行字,说明你的开发环境完全搭好了。后面的事,就是在这个基础上做移植和调试了。