3. STM32CubeMX集成TFLite

任务目标

在STM32CubeMX中完成一个面向TFLite部署的基础工程配置:使能所需外设(UART、GPIO、时钟),生成CMake或Makefile工程,并将TFLite运行时头文件与静态库正确接入构建系统,最终得到一个可编译通过的裸机工程骨架。

环境与依赖

  • STM32CubeMX 6.x(含STM32CubeFW包,如F4/F7/L4系列)
  • 交叉编译器:arm-none-eabi-gcc(或Keil/IAR,本案例以CMake+GCC为例)
  • TFLite Micro运行时源码(从tflite-micro获取,版本建议与CubeMX生成的CMSIS版本兼容)
  • 本案例以STM32F407VET6 + 外部HSE 8MHz为例,其他型号操作相同

CubeMX工程配置步骤

  1. 新建工程:选择MCU型号,配置时钟树(HSE→PLL→168MHz主频)。
  2. 使能外设:UART1(用于日志输出,115200-8-N-1)、PA5(LED,用于状态指示)、SWD调试口。
  3. 生成方式:Project Manager → Project → Toolchain选择CMake,生成初始工程。
  4. 调整链接脚本:TFLite运行时需要较大RAM/Flash,确认_Min_Heap_Size与_Min_Stack_Size至少为0x800(2KB),建议在CubeMX中直接修改链接脚本或生成后手动调整。

集成TFLite运行时

将tflite-micro源码中的tensorflow目录整体复制到工程根目录下third_party/tflite中。需要保留的头文件路径为:

third_party/tflite/tensorflow/lite/micro
third_party/tflite/tensorflow/lite/micro/compiler
third_party/tflite/tensorflow/lite/c
third_party/tflite/tensorflow/lite/core/api
third_party/tflite/tensorflow/lite/schema
third_party/tflite/third_party/flatbuffers/include
third_party/tflite/third_party/gemmlowp
third_party/tflite/third_party/ruy

在CubeMX生成的CMakeLists.txt中追加以下内容(位置在add_executable之前):

# TFLite Micro 运行时源文件(按需裁剪,此处为最小推理所需)
set(TFLITE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/third_party/tflite)
set(TFLITE_SRCS
    ${TFLITE_DIR}/tensorflow/lite/micro/all_ops_resolver.cc
    ${TFLITE_DIR}/tensorflow/lite/micro/micro_interpreter.cc
    ${TFLITE_DIR}/tensorflow/lite/micro/micro_mutable_op_resolver.cc
    ${TFLITE_DIR}/tensorflow/lite/micro/micro_profiler.cc
    ${TFLITE_DIR}/tensorflow/lite/micro/recording_micro_allocator.cc
    ${TFLITE_DIR}/tensorflow/lite/micro/micro_allocator.cc
    ${TFLITE_DIR}/tensorflow/lite/micro/micro_error_reporter.cc
    ${TFLITE_DIR}/tensorflow/lite/micro/micro_time.cc
    ${TFLITE_DIR}/tensorflow/lite/micro/micro_utils.cc
    ${TFLITE_DIR}/tensorflow/lite/micro/system_setup.cc
    ${TFLITE_DIR}/tensorflow/lite/micro/debug_log.cc
    ${TFLITE_DIR}/tensorflow/lite/micro/memory_helpers.cc
    ${TFLITE_DIR}/tensorflow/lite/micro/kernels/conv.cc
    ${TFLITE_DIR}/tensorflow/lite/micro/kernels/fully_connected.cc
    ${TFLITE_DIR}/tensorflow/lite/micro/kernels/softmax.cc
    ${TFLITE_DIR}/tensorflow/lite/micro/kernels/reshape.cc
    ${TFLITE_DIR}/tensorflow/lite/micro/kernels/pad.cc
    ${TFLITE_DIR}/tensorflow/lite/micro/kernels/add.cc
    ${TFLITE_DIR}/tensorflow/lite/micro/kernels/mul.cc
    ${TFLITE_DIR}/tensorflow/lite/micro/kernels/quantize.cc
    ${TFLITE_DIR}/tensorflow/lite/micro/kernels/dequantize.cc
    ${TFLITE_DIR}/tensorflow/lite/micro/kernels/logistic.cc
    ${TFLITE_DIR}/tensorflow/lite/micro/kernels/activations.cc
    ${TFLITE_DIR}/tensorflow/lite/micro/kernels/circular_buffer.cc
    ${TFLITE_DIR}/tensorflow/lite/micro/kernels/ethosu.cc
    ${TFLITE_DIR}/tensorflow/lite/micro/kernels/transpose_conv.cc
    ${TFLITE_DIR}/tensorflow/lite/micro/kernels/unidirectional_sequence_lstm.cc
    ${TFLITE_DIR}/tensorflow/lite/micro/kernels/svdf.cc
    ${TFLITE_DIR}/tensorflow/lite/micro/kernels/cmsis_nn/conv.cc
    ${TFLITE_DIR}/tensorflow/lite/micro/kernels/cmsis_nn/fully_connected.cc
    ${TFLITE_DIR}/tensorflow/lite/micro/kernels/cmsis_nn/pooling.cc
    ${TFLITE_DIR}/tensorflow/lite/micro/kernels/cmsis_nn/softmax.cc
    ${TFLITE_DIR}/tensorflow/lite/micro/kernels/cmsis_nn/svdf.cc
)

# 头文件搜索路径
target_include_directories(${PROJECT_NAME} PRIVATE
    ${TFLITE_DIR}
    ${TFLITE_DIR}/tensorflow/lite/micro
    ${TFLITE_DIR}/tensorflow/lite/micro/compiler
    ${TFLITE_DIR}/tensorflow/lite/c
    ${TFLITE_DIR}/tensorflow/lite/core/api
    ${TFLITE_DIR}/tensorflow/lite/schema
    ${TFLITE_DIR}/third_party/flatbuffers/include
    ${TFLITE_DIR}/third_party/gemmlowp
    ${TFLITE_DIR}/third_party/ruy
)

# 将TFLite源文件加入编译
target_sources(${PROJECT_NAME} PRIVATE ${TFLITE_SRCS})

# 若使用CMSIS-NN优化内核,需额外链接CMSIS库(CubeMX已生成)
# target_link_libraries(${PROJECT_NAME} PRIVATE cmsis_nn)

若实际模型只用少量算子,可大幅裁剪上述源文件列表,仅保留对应算子内核,以减小Flash占用。

最小验证代码

在main.c的main()函数中,MX_Init()之后加入以下代码,验证TFLite头文件可正常包含、链接无误:

#include "tensorflow/lite/micro/micro_interpreter.h"
#include "tensorflow/lite/micro/micro_mutable_op_resolver.h"
#include "tensorflow/lite/micro/system_setup.h"
#include "tensorflow/lite/schema/schema_generated.h"

// 在main()中,外设初始化之后:
tflite::InitializeTarget();
printf("TFLite runtime headers OK\r\n");

// 验证MicroInterpreter类型可用(不实例化,仅编译期验证)
tflite::MicroInterpreter* interpreter_ptr = nullptr;
(void)interpreter_ptr;
printf("MicroInterpreter type OK\r\n");

while (1) {
    HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5);
    HAL_Delay(500);
}

编译与运行

  1. 在CubeMX生成目录下执行:
cmake -B build -DCMAKE_TOOLCHAIN_FILE=arm-none-eabi-gcc.cmake
cmake --build build
  1. 将生成的.elf或.bin通过ST-Link烧录至开发板。
  2. 打开串口助手(115200),复位开发板。

验证判定标准

  • 编译无错误、无未定义引用,链接通过。
  • 串口输出两行日志:TFLite runtime headers OK与MicroInterpreter type OK。
  • LED以500ms间隔闪烁,表明系统未因TFLite集成而进入HardFault。

满足以上三点即判定CubeMX集成TFLite运行时成功。后续案例将在此工程骨架上添加具体模型与推理逻辑。