4、开发环境搭建(下):ARM交叉编译链安装、OpenOCD调试工具安装、STM32CubeProgrammer安装
好,咱们接着上一章继续聊。上回我们把基础工具链和NuttX源码拉下来了,但说实话,那只是万里长征第一步。你想想看,没有交叉编译链,你写的代码怎么变成ARM芯片能跑的东西?没有调试器,出了问题你拿什么去抓?
这一章,我就带你把这几个关键环节一一搞定。我个人习惯是把这三样东西装好之后,才算真正有了「干活的感觉」。
本章核心三件套:
- ARM交叉编译链 —— 把x86上的代码翻译成ARM能懂的机器码
- OpenOCD调试工具 —— 用GDB远程调试你的目标板
- STM32CubeProgrammer —— 烧录固件、查看Flash、做量产
4.1 ARM交叉编译链安装
先说说交叉编译链。这东西说白了就是一套工具,让你在PC上写好代码,然后编译成ARM芯片能执行的二进制文件。我刚开始接触嵌入式时,总觉得「交叉编译」这个词很玄乎,其实没那么复杂——你想想看,你的电脑是x86架构,STM32是ARM Cortex-M架构,CPU指令集都不一样,当然需要专门的编译器来翻译。
我个人推荐用ARM官方维护的 gcc-arm-none-eabi 工具链。为什么选它?因为它是开源的、免费的,而且NuttX官方也是用它来编译的,兼容性最好。
4.1.1 下载与安装
去ARM官网下载最新版本。我写这篇文章时,稳定版是 10.3-2021.10。你如果看到更新的版本,直接用新的就行。
Linux下的安装步骤:
# 下载(以Ubuntu 20.04为例)
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/
# 添加环境变量
echo 'export PATH=$PATH:/opt/gcc-arm-none-eabi-10.3-2021.10/bin' >> ~/.bashrc
source ~/.bashrc
小提示: 我习惯把工具链装到 /opt 下,而不是 /usr/local。原因很简单——/opt 专门放第三方软件包,方便管理和卸载。你如果装多个版本,直接在 /opt 下建不同文件夹就行。
4.1.2 验证安装
装完之后,一定要验证一下。别等到编译时才发现路径没配好,那就尴尬了。
arm-none-eabi-gcc --version
# 你应该看到类似输出:
# arm-none-eabi-gcc (GNU Arm Embedded Toolchain 10.3-2021.10) 10.3.1 20210824 (release)
# Copyright (C) 2020 Free Software Foundation, Inc.
# This is free software; see the source for copying conditions. There is NO
# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
嗯,看到版本号就说明装好了。如果提示 command not found,别慌——检查一下环境变量有没有生效,或者直接重启终端试试。
注意: 千万不要用系统自带的 gcc 去编译ARM代码!我曾经见过有人直接用 gcc -o test test.c 然后往STM32里烧,结果芯片完全不跑。原因很简单——你编译出来的是x86的机器码,ARM芯片根本看不懂。
4.2 OpenOCD调试工具安装
接下来是OpenOCD。这个工具是干嘛的?简单说,它就是一个「翻译官」——把你的GDB调试命令,转换成JTAG或SWD协议信号,发给目标芯片。
我在项目中遇到过好几次这种情况:代码编译通过了,烧录也成功了,但芯片就是跑飞了。这时候如果没有调试器,你只能靠串口打印猜问题,效率极低。有了OpenOCD + GDB,你可以单步执行、看寄存器值、设断点,问题定位快得多。
4.2.1 安装OpenOCD
Ubuntu下可以直接用apt安装,但我建议你从源码编译——这样能获得最新版本,而且可以自定义配置。
# 安装依赖
sudo apt-get install libtool autoconf automake texinfo libusb-1.0-0-dev
# 克隆源码
git clone https://github.com/openocd-org/openocd.git
cd openocd
# 配置(启用ST-Link支持)
./bootstrap
./configure --enable-stlink
# 编译安装
make -j$(nproc)
sudo make install
小提示: --enable-stlink 这个选项很重要。因为STM32开发板大多自带ST-Link调试器,如果不启用这个选项,OpenOCD就没法跟你的板子通信。我刚开始就踩过这个坑,编译完发现连不上板子,折腾了半天才发现是配置参数漏了。
4.2.2 配置ST-Link驱动(Linux)
Linux下需要配置udev规则,否则普通用户没有权限访问USB设备。
# 创建udev规则文件
sudo nano /etc/udev/rules.d/99-stlink.rules
# 写入以下内容:
# ST-Link V2
SUBSYSTEM=="usb", ATTRS{idVendor}=="0483", ATTRS{idProduct}=="3748", MODE="0666"
# ST-Link V2.1
SUBSYSTEM=="usb", ATTRS{idVendor}=="0483", ATTRS{idProduct}=="374b", MODE="0666"
# 重新加载udev规则
sudo udevadm control --reload-rules
sudo udevadm trigger
插上你的STM32开发板,然后运行 lsusb,你应该能看到类似 STMicroelectronics ST-LINK/V2 的设备。
4.2.3 测试OpenOCD连接
写一个简单的配置文件,比如 stm32f4.cfg:
# 选择调试器接口
source [find interface/stlink.cfg]
transport select hla_swd
# 选择目标芯片
source [find target/stm32f4x.cfg]
# 设置工作频率
adapter speed 1000
然后运行:
openocd -f stm32f4.cfg
如果一切正常,你会看到类似这样的输出:
Info : STLINK V2J29M27 (API v2) VID:PID 0483:3748
Info : Target voltage: 3.28 V
Info : stm32f4x.cpu: hardware has 6 breakpoints, 4 watchpoints
看到这个输出,说明你的调试环境已经通了! 硬件断点6个、观察点4个——这些数字后面调试时会用到。
4.3 STM32CubeProgrammer安装
最后一个是STM32CubeProgrammer。这个工具是ST官方出的,功能很全——烧录固件、查看Flash内容、配置选项字节、读写保护等等。
我个人觉得,如果你只是做开发调试,OpenOCD + GDB就够用了。但如果你要做量产、或者需要图形化界面操作,CubeProgrammer会更方便。
4.3.1 下载与安装
去ST官网下载 STM32CubeProgrammer,选择Linux版本。下载下来是一个 .AppImage 文件,直接给执行权限就能运行。
# 给执行权限
chmod +x STM32CubeProgrammer-2.12.0.AppImage
# 运行
./STM32CubeProgrammer-2.12.0.AppImage
嗯,就这么简单。AppImage的好处是免安装,一个文件搞定所有依赖。
4.3.2 命令行模式
CubeProgrammer也支持命令行模式,这个在自动化烧录时特别有用。比如你要在产线上批量烧录固件,总不能每台机器都点鼠标吧?
# 烧录固件
STM32_Programmer_CLI -c port=SWD -w firmware.hex -v
# 参数说明:
# -c port=SWD : 使用SWD接口连接
# -w firmware.hex : 写入固件
# -v : 烧录后校验
小提示: 命令行模式下,-v 参数建议每次都加上。我吃过一次亏——烧录时没加校验,结果有一批板子的Flash有坏块,固件没写进去,产线测试时才发现,返工成本很高。
4.3.3 选项字节配置
有时候你需要配置芯片的选项字节,比如设置读保护、修改启动模式等。CubeProgrammer的图形界面里有个 Option Bytes 标签页,点几下鼠标就能搞定。
命令行下也可以操作:
# 设置读保护等级1(RDP Level 1)
STM32_Programmer_CLI -c port=SWD -ob RDP=0xBB
# 解除读保护
STM32_Programmer_CLI -c port=SWD -ob RDP=0xAA
注意: 设置读保护后,芯片的Flash内容就不能通过调试器读取了。但要注意——解除读保护(RDP=0xAA)会擦除整个Flash!我曾经在客户现场演示时,不小心执行了这条命令,结果芯片里的固件全没了...嗯,从那以后我每次操作选项字节前都会先备份固件。
4.4 本章小结
好,到这里,我们的开发环境就基本搭完了。来回顾一下这章的内容:
- ARM交叉编译链:装好了
gcc-arm-none-eabi,验证了编译器的版本 - OpenOCD:从源码编译安装,配置了ST-Link驱动,测试了与目标板的连接
- STM32CubeProgrammer:安装了图形化工具,学会了命令行烧录和选项字节配置
这三样东西装好之后,你就可以开始真正的嵌入式开发了。下一章,我们会用NuttX的配置工具生成一个工程,然后编译、烧录、运行——到时候你会看到自己写的代码在STM32上跑起来,那种感觉还是挺爽的。
嗯,今天就到这儿。如果你在安装过程中遇到什么问题,欢迎随时交流。记住,环境搭建是基础,基础打牢了,后面才能走得稳。