3. 开发环境搭建:ARM GCC工具链、OpenOCD调试器、VS Code工程配置
好,咱们正式开始动手了。这一章我带你搭开发环境。说实话,很多初学者把精力都花在写代码上,结果环境没配好,一编译全是红字,心态直接崩了。我当年刚入行时也踩过这个坑,折腾了一整天发现是路径配错了。
嵌入式开发的环境搭建,说白了就是三样东西:编译器(把C代码变成机器码)、调试器(把程序烧进去并跟踪运行)、编辑器(你写代码的地方)。咱们一个一个来。
3.1 ARM GCC工具链:从源码到二进制
ARM GCC,全称是 GNU Arm Embedded Toolchain。它是专门为ARM Cortex-M系列芯片准备的免费编译器。为什么不用Keil或IAR?因为咱们要做RTOS移植,需要完全掌控编译选项,而GCC是开源的,想怎么改都行。
我个人习惯用 gcc-arm-none-eabi 这个版本。注意名字里的「none」和「eabi」——「none」表示没有操作系统(bare-metal),「eabi」是嵌入式应用二进制接口标准。
3.1.1 下载与安装
去ARM官网下载最新版。我建议选 9.3.1 或 10.3-2021.10 这两个版本,稳定,踩坑少。下载后解压到一个没有中文和空格的路径,比如:
C:\arm-gcc\gcc-arm-none-eabi-10.3-2021.10
然后把 bin 目录加到系统环境变量 PATH 里。验证方法:打开命令行,输入:
arm-none-eabi-gcc --version
如果看到版本号,说明装好了。嗯,这里要注意:Windows用户记得用管理员权限打开命令行,否则环境变量可能不生效。我曾经因为这个浪费了半小时。
3.1.2 编译选项说明
咱们的牙刷主控是STM32F103系列,Cortex-M3内核。编译时常用的选项我列个表:
| 选项 | 说明 | 我的推荐值 |
|---|---|---|
-mcpu=cortex-m3 |
指定CPU内核 | 必须加,否则生成错误指令 |
-mthumb |
使用Thumb指令集 | Cortex-M只支持Thumb |
-O2 |
优化等级 | 调试用-Og,发布用-O2 |
-ffunction-sections |
每个函数独立段 | 配合链接器垃圾回收用 |
-fdata-sections |
每个数据独立段 | 同上 |
-Og 优化等级,它不会过度优化导致调试时变量值看不到。我刚开始用 -O2 调试,单步执行时变量全被优化掉了,查了半天才发现是优化等级的问题。
3.2 OpenOCD调试器:烧录与调试的瑞士军刀
OpenOCD(Open On-Chip Debugger)是一个开源调试工具。它支持各种调试器硬件(比如ST-Link、J-Link、CMSIS-DAP),也支持各种芯片。说白了,它就是你的电脑和芯片之间的翻译官。
3.2.1 安装OpenOCD
Windows用户建议直接下载预编译的二进制包。我常用的是 xpack-openocd 版本,更新及时,配置也简单。解压后同样把 bin 目录加到PATH。
验证方法:
openocd --version
3.2.2 配置文件编写
OpenOCD需要两个配置文件:一个是调试器接口配置,一个是目标芯片配置。咱们用ST-Link调试器,连接STM32F103,配置文件长这样:
# stlink.cfg
source [find interface/stlink.cfg]
transport select hla_swd
source [find target/stm32f1x.cfg]
启动OpenOCD的命令:
openocd -f stlink.cfg
如果看到 Info : Listening on port 3333 for gdb connections,说明连接成功了。这时候芯片已经通过SWD接口和电脑连上了。
3.3 VS Code工程配置:让写代码变成享受
VS Code本身只是一个编辑器,但配上插件后,它就是最强的嵌入式IDE。我个人觉得比Keil好用多了——免费、轻量、插件生态丰富。
3.3.1 必备插件
- C/C++(微软官方):语法高亮、智能提示、调试支持
- Cortex-Debug:专门调试ARM芯片,配合OpenOCD使用
- Makefile Tools:方便编译和构建
- Hex Editor:查看二进制文件,调试时很有用
3.3.2 工程目录结构
我习惯这样组织代码:
toothbrush_rtos/
├── .vscode/ # VS Code配置
│ ├── launch.json # 调试配置
│ ├── tasks.json # 构建任务
│ └── c_cpp_properties.json # 编译器路径
├── src/ # 源代码
│ ├── main.c
│ ├── rtos/ # RTOS内核源码
│ └── drivers/ # 外设驱动
├── startup/ # 启动文件
├── linker/ # 链接脚本
├── Makefile # 构建脚本
└── openocd.cfg # OpenOCD配置
3.3.3 launch.json配置
这是调试配置的核心。我直接贴一份能用的:
{
"version": "0.2.0",
"configurations": [
{
"name": "Cortex Debug",
"type": "cortex-debug",
"request": "launch",
"servertype": "openocd",
"cwd": "${workspaceRoot}",
"executable": "./build/toothbrush.elf",
"configFiles": [
"openocd.cfg"
],
"svdFile": "./STM32F103.svd"
}
]
}
这里有个关键点:svdFile 是芯片的寄存器描述文件,有了它,调试时可以直接看外设寄存器的值,不用翻手册。STM32的SVD文件可以从ST官网下载。
3.3.4 tasks.json配置
按 Ctrl+Shift+B 就能编译,配置如下:
{
"version": "2.0.0",
"tasks": [
{
"label": "build",
"type": "shell",
"command": "make",
"group": {
"kind": "build",
"isDefault": true
}
}
]
}
3.4 验证环境:点亮第一颗LED
环境搭好了,咱们写个最简单的程序验证一下。让牙刷上的LED闪烁:
#include "stm32f1xx.h"
void delay(void) {
for(int i = 0; i < 1000000; i++);
}
int main(void) {
// 使能GPIOC时钟
RCC->APB2ENR |= RCC_APB2ENR_IOPCEN;
// 配置PC13为推挽输出
GPIOC->CRH &= ~(0xF << 20);
GPIOC->CRH |= (0x2 << 20);
while(1) {
GPIOC->BSRR = GPIO_BSRR_BS13; // 亮
delay();
GPIOC->BSRR = GPIO_BSRR_BR13; // 灭
delay();
}
}
编译、烧录、运行。如果LED开始闪烁,恭喜你,环境搭建成功了!
你想想看,从零开始,到LED闪烁,其实就三步:装编译器、配调试器、写代码。但每一步都有细节,稍不注意就卡住。我当年第一次配OpenOCD,折腾了整整一个周末,最后发现是配置文件里少写了一个 source 命令。
好了,环境搭好了,下一章咱们开始真正移植RTOS内核。到时候你会看到,这些工具会发挥巨大的作用。