2. 环境搭建:安装TensorFlow Lite Micro、CMSIS-NN、STM32CubeIDE,配置交叉编译工具链
说实话,嵌入式AI开发最让人头疼的往往不是算法本身,而是环境搭建。我见过太多人卡在这一步,工具链没配好,连个Hello World都跑不起来。今天咱们就把这事彻底搞定。
这一章的目标很明确:让你的电脑能编译出能在STM32上跑的AI模型推理代码。我们会装三个核心东西——TensorFlow Lite Micro、CMSIS-NN、STM32CubeIDE,再把交叉编译工具链配通。
核心思路:PC端训练模型 → 交叉编译成MCU能跑的二进制 → 烧录到STM32上推理。环境搭建就是打通这条链路。
2.1 整体架构
先看一张图,搞清楚我们今天要搭的东西之间的关系。
从上往下看:你在PC上装好TFLite Micro和CMSIS-NN,用交叉编译工具链把代码编译成ARM指令,再通过STM32CubeIDE烧到板子上。每一层都依赖下一层,缺一个都跑不通。
2.2 安装TensorFlow Lite Micro
TFLite Micro是Google专门为MCU设计的推理引擎。它不依赖操作系统,纯C++实现,内存占用极小。我最早接触它是在一个手势识别项目里,当时被它的轻量级震惊了——整个引擎才几十KB。
2.2.1 获取源码
我建议直接从GitHub拉取,不要用pip装的那个TensorFlow,那个是给服务器用的。我们要的是嵌入式版本。
# 克隆TensorFlow仓库(包含TFLite Micro)
git clone https://github.com/tensorflow/tensorflow.git
cd tensorflow
# 切到稳定版本(我用的是2.12.0,兼容性最好)
git checkout v2.12.0
# 验证目录结构
ls tensorflow/lite/micro/
# 你应该看到:examples/, kernels/, tools/, ...
我的习惯:不要用master分支,经常有API变动。固定一个release版本,项目做到一半升级版本太痛苦了。
2.2.2 验证编译
拉下来之后先跑个测试,确认环境没问题。
# 编译hello world示例(针对x86,先验证代码没问题)
make -f tensorflow/lite/micro/tools/make/Makefile hello_world
# 运行
./tensorflow/lite/micro/tools/make/gen/linux_x86_64/bin/hello_world
如果看到一串正弦波数据输出,说明TFLite Micro源码没问题。这一步很多人跳过,结果后面交叉编译出错了都不知道是源码问题还是工具链问题。
2.3 安装CMSIS-NN
CMSIS-NN是ARM官方的神经网络优化库。它利用Cortex-M内核的DSP指令和SIMD指令,把卷积、池化这些操作加速好几倍。说白了,没有它,你的模型在MCU上可能跑不动。
2.3.1 下载CMSIS-5
CMSIS-NN是CMSIS-5的一部分。我们只需要其中的NN和DSP两个子目录。
# 克隆CMSIS-5
git clone https://github.com/ARM-software/CMSIS_5.git
cd CMSIS_5
# 切到稳定版本(我用的5.9.0)
git checkout v5.9.0
# 我们只需要这两个目录
# CMSIS_5/CMSIS/NN/
# CMSIS_5/CMSIS/DSP/
注意:CMSIS-NN的API在不同版本间有变化。如果你用的TFLite Micro版本比较新,可能需要对应较新的CMSIS版本。我曾经因为版本不匹配,编译报了一堆undefined reference,查了两天才发现是CMSIS版本太老。
2.3.2 目录结构说明
| 目录 | 内容 | 是否必需 |
|---|---|---|
| CMSIS/NN/Include | NN函数头文件(arm_convolve_s8等) | 必需 |
| CMSIS/NN/Source | NN函数源码 | 必需 |
| CMSIS/DSP/Include | DSP指令头文件 | 必需 |
| CMSIS/Core | Cortex-M内核定义 | 可选(STM32CubeIDE自带) |
2.4 安装STM32CubeIDE
STM32CubeIDE是ST官方的集成开发环境,基于Eclipse。它集成了编译器、调试器、烧录工具,一站式搞定。
2.4.1 下载与安装
- 去ST官网下载STM32CubeIDE(需要注册账号,免费)
- 选择对应操作系统的版本(Windows/Linux/macOS)
- 安装时注意:安装路径不要有中文和空格,我吃过这个亏
- 安装完成后,打开IDE,它会自动检测GCC工具链
避坑指南:Linux用户别用snap安装,权限问题一堆。直接下载.tar.gz解压到/opt目录下,然后创建软链接到/usr/local/bin。
2.4.2 验证安装
新建一个STM32项目,选一块开发板(比如STM32F746G-DISCO),编译一下空工程。如果能生成.elf和.bin文件,说明IDE和工具链都正常。
# 检查编译器版本(在IDE的Terminal里运行)
arm-none-eabi-gcc --version
# 应该输出类似:arm-none-eabi-gcc (GNU Tools for Arm Embedded Processors) 10.3.1
2.5 配置交叉编译工具链
这是最核心的一步。我们要让TFLite Micro和CMSIS-NN能编译成ARM Cortex-M的机器码。
2.5.1 安装ARM GCC
STM32CubeIDE自带了一个ARM GCC,但版本可能比较旧。我习惯自己装一个最新的。
# 下载ARM GCC(以Linux为例)
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
# 验证
arm-none-eabi-gcc --version
2.5.2 编写交叉编译Makefile
有了工具链,还得告诉TFLite Micro怎么用它。我写了一个通用的Makefile片段,你们可以直接用。
# 交叉编译配置
CROSS_COMPILE = arm-none-eabi-
CC = $(CROSS_COMPILE)gcc
CXX = $(CROSS_COMPILE)g++
AR = $(CROSS_COMPILE)ar
LD = $(CROSS_COMPILE)ld
# 目标架构(以Cortex-M7为例)
ARCH_FLAGS = -mcpu=cortex-m7 -mthumb -mfpu=fpv5-d16 -mfloat-abi=hard
# 如果是Cortex-M4,用:
# ARCH_FLAGS = -mcpu=cortex-m4 -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=hard
# 优化选项
OPT_FLAGS = -O3 -DNDEBUG
# CMSIS-NN路径
CMSIS_PATH = /path/to/CMSIS_5
NN_INCLUDE = -I$(CMSIS_PATH)/CMSIS/NN/Include
DSP_INCLUDE = -I$(CMSIS_PATH)/CMSIS/DSP/Include
# TFLite Micro路径
TFLM_PATH = /path/to/tensorflow
TFLM_INCLUDE = -I$(TFLM_PATH)
# 编译标志
CFLAGS = $(ARCH_FLAGS) $(OPT_FLAGS) $(NN_INCLUDE) $(DSP_INCLUDE) $(TFLM_INCLUDE) -Wall
关键点:-mcpu和-mfloat-abi必须和你用的STM32芯片一致。我见过有人用Cortex-M4的芯片,却配了Cortex-M7的编译参数,烧进去直接跑飞。
2.5.3 编译TFLite Micro for ARM
配置好之后,编译一个针对ARM的测试程序。
# 使用TFLite Micro的Makefile,指定目标架构
make -f tensorflow/lite/micro/tools/make/Makefile \
TARGET= cortex_m_generic \
TARGET_ARCH= cortex-m7 \
OPTIMIZED_KERNEL_DIR= cmsis_nn \
CMSIS_PATH= /path/to/CMSIS_5 \
hello_world
# 编译成功后,检查生成的二进制
file ./gen/cortex_m_generic_cortex-m7/bin/hello_world
# 应该输出:ELF 32-bit LSB executable, ARM, version 1 (SYSV)
看到"ARM"字样,说明交叉编译成功了。这个二进制文件就是能在STM32上跑的。
2.6 验证整个链路
环境搭好了,得跑个完整的例子确认一切正常。我推荐用TFLite Micro自带的person_detection示例,它用到了CMSIS-NN优化,能充分验证我们的工具链。
# 编译person_detection(针对ARM)
make -f tensorflow/lite/micro/tools/make/Makefile \
TARGET= cortex_m_generic \
TARGET_ARCH= cortex-m7 \
OPTIMIZED_KERNEL_DIR= cmsis_nn \
CMSIS_PATH= /path/to/CMSIS_5 \
person_detection
# 生成的文件在:
# ./gen/cortex_m_generic_cortex-m7/bin/person_detection.bin
把这个.bin文件通过STM32CubeIDE烧到板子上,如果板子上的LED能根据摄像头画面亮灭,说明整个环境搭建成功了。
常见问题:如果编译报错"undefined reference to `arm_convolve_s8'",说明CMSIS-NN的源码没有正确链接。检查Makefile里有没有把CMSIS/NN/Source下的所有.c文件加入编译列表。
2.7 环境检查清单
最后,我列一个检查清单。每完成一项就打勾,确保万无一失。
| 序号 | 检查项 | 验证方法 |
|---|---|---|
| 1 | TFLite Micro源码可用 | x86下能编译运行hello_world |
| 2 | CMSIS-NN目录完整 | NN/Include和NN/Source都存在 |
| 3 | ARM GCC工具链正常 | arm-none-eabi-gcc --version 输出正确 |
| 4 | 交叉编译TFLite Micro | 生成ARM ELF文件 |
| 5 | STM32CubeIDE能烧录 | 空工程编译烧录成功 |
| 6 | 完整链路测试 | person_detection在板子上运行 |