2、开发环境搭建:Keil MDK安装与配置、STM32CubeMX生成基础工程、GCC工具链与Makefile入门、调试器(J-Link/ST-Link)配置

说实话,做嵌入式开发这么多年,我见过太多人在环境搭建这一步就卡住了。工具链没配好,后面写再多代码也是白搭。今天咱们就把这四块内容一次性捋清楚——Keil MDK、STM32CubeMX、GCC+Makefile、还有调试器配置。嗯,都是实打实的干货。

2.1 Keil MDK 安装与配置

Keil MDK 是 ARM 生态里最常用的 IDE 之一。我个人习惯用它来做快速原型验证,尤其是 STM32 系列。安装其实不复杂,但有几个坑我得提前说。

安装步骤

  1. 下载安装包:去 Keil 官网下载 MDK-ARM 最新版。注意版本号,我建议用 5.38 或更新版本,对 Cortex-M 系列支持更全。
  2. 运行安装程序:一路 Next 就行。但安装路径别带中文,也别有空格。我曾经因为路径里有个空格,折腾了一下午找不到编译器。
  3. 激活 License:如果你有正版 License,直接输入。没有的话,可以用评估版,代码限制 32KB。嗯,做小项目够用了。
  4. 安装器件包:打开 Pack Installer,找到你用的芯片型号。比如 STM32F103C8T6,勾上对应的 Device Family Pack。这一步很多人会忘,结果编译时报错找不到芯片定义。
注意:Keil MDK 安装后默认编译器是 ARMCC V5 或 V6。如果你要用 GCC,需要额外配置。这个后面会讲。

配置技巧

  • 编码设置:Edit → Configuration → Editor → Encoding,选 UTF-8。不然中文注释会乱码。
  • 语法高亮:我个人喜欢把关键字颜色调成深蓝色,背景用浅灰。眼睛舒服点。
  • 工程模板:建一个空的模板工程,包含启动文件、链接脚本、系统时钟配置。以后新项目直接复制,省时间。

2.2 STM32CubeMX 生成基础工程

STM32CubeMX 是 ST 官方出的图形化配置工具。说白了,就是帮你自动生成初始化代码。你想想看,以前配个时钟树要翻半天参考手册,现在点几下鼠标就搞定了。

生成步骤

  1. 新建工程:选择芯片型号,比如 STM32F407VGT6。或者直接搜开发板名字,像 STM32F4-Discovery。
  2. 配置时钟:在 Clock Configuration 页面,把 HSE 和 PLL 配好。我建议先选外部晶振,再倍频到目标频率。比如 8MHz 晶振,PLL 倍频到 168MHz。
  3. 配置外设:比如你要用 USART1,就在 Pinout 页面点一下 PA9、PA10,选 USART1_TX 和 USART1_RX。然后去 Configuration 页面设波特率、数据位这些。
  4. 生成代码:Project Manager 页面,选 Toolchain / IDE 为 MDK-ARM。然后点 GENERATE CODE。嗯,这里要注意,生成路径别太深,不然 Keil 打开会报错。
小技巧:生成代码后,别急着改 CubeMX 生成的 .c/.h 文件。你可以在 User Code Begin 和 User Code End 注释之间加自己的代码。这样下次重新生成时,你的代码不会被覆盖。我刚开始不知道,每次重新生成都要重写一遍,烦死了。

常见问题

  • 时钟配置失败:检查外部晶振是否起振。用示波器量一下,或者看 RCC 寄存器状态。
  • 引脚冲突:CubeMX 会高亮显示冲突引脚。比如你同时用了 PA0 做 ADC 和 GPIO,它会报错。这时候得重新分配。
  • 生成代码后编译报错:多半是 HAL 库版本不匹配。去 CubeMX 的 Help → Manage embedded software packages 里更新一下。

2.3 GCC 工具链与 Makefile 入门

Keil 虽然方便,但商业软件有版权问题。而且说实话,做产品级项目时,我更喜欢用 GCC + Makefile。为什么?因为可定制性强,而且 CI/CD 集成起来方便。

GCC 工具链安装

ARM 官方提供了 arm-none-eabi-gcc 工具链。下载地址是 ARM Developer 官网。安装后记得把 bin 目录加到系统 PATH 里。验证方法:打开终端,输入 arm-none-eabi-gcc --version,能看到版本信息就对了。

核心工具
  • arm-none-eabi-gcc:C 编译器
  • arm-none-eabi-g++:C++ 编译器
  • arm-none-eabi-ld:链接器
  • arm-none-eabi-objcopy:生成 .bin/.hex 文件
  • arm-none-eabi-gdb:调试器

Makefile 入门

Makefile 说白了就是一个自动化编译脚本。你想想看,每次改完代码都要手动敲一堆 gcc 命令,多累啊。用 Makefile 一键搞定。

下面是一个最简单的 Makefile 示例,适用于 STM32F103 系列:

# 编译器
CC = arm-none-eabi-gcc
OBJCOPY = arm-none-eabi-objcopy

# 编译选项
CFLAGS = -mcpu=cortex-m3 -mthumb -Wall -O2
LDFLAGS = -T stm32f103.ld -nostartfiles

# 源文件
SRCS = main.c startup_stm32f103.c syscalls.c
OBJS = $(SRCS:.c=.o)

# 目标
TARGET = firmware.elf

all: $(TARGET)
	$(OBJCOPY) -O binary $(TARGET) firmware.bin

$(TARGET): $(OBJS)
	$(CC) $(LDFLAGS) -o $@ $^

%.o: %.c
	$(CC) $(CFLAGS) -c -o $@ $<

clean:
	rm -f $(OBJS) $(TARGET) firmware.bin
个人经验:写 Makefile 时,链接脚本(.ld 文件)最容易出错。我建议直接从 STM32CubeMX 生成的工程里复制一份,然后根据你的芯片修改 FLASH 和 RAM 大小。别自己从头写,容易漏掉段定义。

GCC 与 Keil 的差异

特性 Keil MDK (ARMCC) GCC
编译器 ARMCC V5/V6 arm-none-eabi-gcc
代码大小 优化较好,但商业授权 开源,优化略差但免费
调试信息 默认 DWARF 2 默认 DWARF 4
链接脚本 .sct 文件 .ld 文件
启动文件 汇编 .s 文件 汇编 .s 文件,但语法略有不同

2.4 调试器配置(J-Link / ST-Link)

调试器是嵌入式开发的「眼睛」。没有它,你只能靠串口打印猜问题。我个人更偏爱 J-Link,速度快,功能强。但 ST-Link 胜在便宜,而且 STM32 开发板基本都自带。

J-Link 配置

  1. 安装驱动:去 Segger 官网下载 J-Link Software Pack。安装后会自动装好驱动。
  2. 连接硬件:J-Link 的 SWD 接口只需要 4 根线:SWDIO、SWCLK、GND、VCC(可选)。注意,VCC 是目标板供电检测,不是给 J-Link 供电的。我曾经接反过,烧了一个 J-Link,心疼啊。
  3. Keil 中配置:Project → Options for Target → Debug,选 J-Link/J-Trace Cortex。然后点 Settings,确认 SWD 模式,速度建议选 4MHz 以下,太高速容易不稳定。

ST-Link 配置

  1. 安装驱动:ST-Link 驱动通常集成在 STM32CubeProgrammer 里。或者去 ST 官网单独下载。
  2. 连接硬件:ST-Link V2 有 4 个引脚:SWDIO、SWCLK、GND、3.3V。注意,有些山寨版 ST-Link 的引脚顺序不一样,买的时候问清楚。
  3. Keil 中配置:Debug 选项里选 ST-Link Debugger。Settings 里同样选 SWD 模式。速度我一般设 1.8MHz,稳定第一。
避坑指南:我曾经遇到过一个诡异问题——J-Link 能识别芯片,但下载程序后不运行。查了半天,发现是复位引脚没接。J-Link 的 nRESET 引脚必须连到目标板的复位脚,不然下载后芯片不会自动复位运行。嗯,这个坑我踩过,你们别踩了。

调试技巧

  • 断点调试:硬件断点有限,Cortex-M3/M4 通常只有 6 个。别设太多,不然会降级成软件断点,影响实时性。
  • 变量查看:在 Watch 窗口添加变量时,注意作用域。局部变量只有在当前函数内才能看到值。
  • 寄存器查看:调试时多看看 RCC、GPIO 寄存器。有时候代码逻辑没错,但寄存器没配好,一样跑不起来。

好了,环境搭建这部分就到这里。工具链配好了,后面写代码才能顺风顺水。下一章咱们开始讲 RTOS 内核移植,到时候会用到今天配好的这些工具。有什么问题,欢迎随时交流。