2. 环境搭建:安装TensorFlow Lite Micro、CMSIS-NN、STM32CubeIDE,配置交叉编译工具链

说实话,嵌入式AI开发最让人头疼的往往不是算法本身,而是环境搭建。我见过太多人卡在这一步,工具链没配好,连个Hello World都跑不起来。今天咱们就把这事彻底搞定。

这一章的目标很明确:让你的电脑能编译出能在STM32上跑的AI模型推理代码。我们会装三个核心东西——TensorFlow Lite Micro、CMSIS-NN、STM32CubeIDE,再把交叉编译工具链配通。

核心思路:PC端训练模型 → 交叉编译成MCU能跑的二进制 → 烧录到STM32上推理。环境搭建就是打通这条链路。

2.1 整体架构

先看一张图,搞清楚我们今天要搭的东西之间的关系。

嵌入式AI开发环境架构 主机开发环境(PC/Linux) TensorFlow Lite Micro 模型转换 + 推理引擎 CMSIS-NN ARM Cortex-M 优化算子库 交叉编译工具链 ARM GCC + Make/CMake STM32CubeIDE 项目管理 · 编译 · 调试 · 烧录 STM32 目标板(Cortex-M4/M7) 运行剪枝后的TFLite模型

从上往下看:你在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 下载与安装

  1. 去ST官网下载STM32CubeIDE(需要注册账号,免费)
  2. 选择对应操作系统的版本(Windows/Linux/macOS)
  3. 安装时注意:安装路径不要有中文和空格,我吃过这个亏
  4. 安装完成后,打开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在板子上运行