news 2026/9/14 15:57:59

libusb_stm32 轻量 USB 设备栈:Flipper Zero 固件中的架构、硬件支持与构建实践

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
libusb_stm32 轻量 USB 设备栈:Flipper Zero 固件中的架构、硬件支持与构建实践

libusb_stm32 轻量 USB 设备栈:Flipper Zero 固件中的架构、硬件支持与构建实践

【免费下载链接】flipperzero-firmwareFlipper Zero firmware source code项目地址: https://gitcode.com/GitHub_Trending/fl/flipperzero-firmware

本文基于 Flipper Zero 固件仓库中 lib/libusb_stm32/readme.md 展开,系统讲解这套“轻量级 STM32 USB 设备协议栈”的设计思想、API 架构、支持的 MCU 硬件范围与 USB 类规范,并结合仓库内 Makefile、核心头文件与 Flipper 自身的 USB HAL 实现,给出可直接复制运行的构建命令与参数说明,帮助读者理解固件 USB 通信(CDC 串口、HID、U2F 等)的底层支撑。

一、定位与设计特点

libusb_stm32 是一个面向 STM32 微控制器的轻量级 USB设备端(Device)协议栈,被 Flipper Zero 固件作为 USB 底层通信栈引入(源码位于 lib/libusb_stm32 目录)。原 README 将其特点概括为四点:

  • 轻量且快速(Lightweight and fast):纯 C(含少量汇编 ISR),无运行时依赖,适合资源受限的 MCU;
  • 事件驱动的处理流程(Event-driven process workflow):USB 事务通过统一事件回调分发,而不是阻塞式状态机;
  • USB 硬件驱动与 USB 核心完全分离(Completely separated USB hardware driver and usb core):更换 MCU 只需替换硬件驱动层,核心逻辑与 USB 类实现无需改动;
  • 易用(Easy to use):以少量初始化函数和回调注册函数暴露完整 API。

这种“硬件驱动 / 核心分离”的分层可以从核心头文件 lib/libusb_stm32/inc/usbd_core.h 中直接验证:核心层通过函数指针表struct usbd_driver调用硬件层,两者之间只有回调接口,没有头文件级耦合。

二、核心架构:usbd_core 的 API 与状态机

2.1 硬件能力抽象与事件模型

核心层定义了一组 USB 设备事件(usbd_evt_*),硬件驱动的中断/轮询最终都归并到这些事件,再由usbd_poll()统一分发给用户注册的回调:

事件宏含义
usbd_evt_resetUSB 总线复位
usbd_evt_sofStart of Frame(每帧开始)
usbd_evt_susp/usbd_evt_wkup挂起 / 唤醒
usbd_evt_eptx/usbd_evt_eprx某端点数据包发出 / 收到
usbd_evt_epsetup收到 SETUP 包(控制事务)
usbd_evt_error数据错误

同时定义了 USB 设备状态机(usbd_state_disabled → disconnected → default → addressed → configured)、控制端点事务阶段(usbd_ctl_idle / rxdata / txdata / ztxdata / lastdata / statusin / statusout)以及响应枚举usbd_respondusbd_fail触发 STALL、usbd_ack接受、usbd_nak表示忙碌)。BC 1.2 充电端口检测能力则通过usbd_lane_*(dsc/sdp/cdp/dcp)状态暴露。

2.2 硬件驱动接口表(usbd_driver)

struct usbd_driver是一张函数指针表,是硬件层必须实现的完整契约:

struct usbd_driver { usbd_hw_getinfo getinfo; // 获取硬件状态与能力位(USBD_HW_CAPS) usbd_hw_enable enable; // 使能/禁用 USB 硬件 usbd_hw_connect connect; // 连接/断开到主机(返回 lane 状态) usbd_hw_setaddr setaddr; // 设置 USB 地址 usbd_hw_ep_config ep_config; // 配置端点(ep / eptype / epsize) usbd_hw_ep_deconfig ep_deconfig; // 去配置端点 usbd_hw_ep_read ep_read; // 从 OUT/控制端点读数据 usbd_hw_ep_write ep_write; // 向 IN/控制端点写数据 usbd_hw_ep_setstall ep_setstall; // STALL/解除 STALL usbd_hw_ep_isstalled ep_isstalled; // 查询 STALL 状态 usbd_hw_poll poll; // 轮询硬件事件并派发回调 usbd_hw_get_frameno frame_no; // 获取当前帧号 usbd_hw_get_serialno get_serialno_desc; // 由硬件 ID 生成序列号字符串描述符 };

硬件能力通过USBD_HW_CAPS位域描述:USBD_HW_ADDRFST(STATUS_OUT 前设置地址)、USBD_HW_BC(BC1.2 充电检测)、USND_HW_HS(支持高速)、USBD_HW_ENABLED,以及USBD_HW_ENUMSPEED枚举速度(NC/LS/FS/HS)。

2.3 设备结构体与初始化

用户侧的核心对象是struct _usbd_device,内含驱动指针、控制/完成/配置/描述符四类回调、按事件类型索引的events[]与按端点索引的endpoint[8]回调数组,以及事务状态usbd_status(控制缓冲区、端点 0 包大小、当前配置号、设备/控制状态)。

初始化是一个内联函数,只需一个控制请求缓冲(要求 32 位对齐):

usbd_init(&udev, &usbd_hw, USB_EP0_SIZE, ubuf, sizeof(ubuf));

之后通过usbd_reg_control / usbd_reg_config / usbd_reg_descr / usbd_reg_event注册回调,并在主循环或中断中调用usbd_poll()驱动事件。端点操作则通过usbd_ep_config / usbd_ep_deconfig / usbd_ep_read / usbd_ep_write / usbd_ep_setstall等封装函数完成,端点方向通过USB_EPDIR_*宏表达。

三、编译期控制宏(驱动行为裁剪)

原 README 的make module说明中特别提示:DEFINES 需参考 “USB Device HW driver and core API” 一节的编译期控制宏。这些宏在 usbd_core.h 中声明,直接决定硬件驱动的编译形态:

作用
USBD_PINS_REMAP为引脚数少的封装重映射 USB 引脚
USBD_SOF_DISABLED禁用 SOF 事件处理(省中断开销)
USBD_VBUS_DETECTL4/F4 驱动启用 VBUS 检测
USBD_DP_PORT/USBD_DP_PINF103/F303 外部 DP 上拉引脚所在端口/引脚
USBD_SOF_OUTF4 OTGFS 的 SOF 输出引脚
USBD_PRIMARY_OTGHSF4 系列将 OTGHS 设为主接口
USBD_USE_EXT_ULPIOTGHS 使用外部 ULPI 接口
USB_PMA_SIZEPMA 内存大小(字节),USB 与 CAN 共享 PMA 时须调整以免数据损坏

这些宏通过 Makefile 的DEFINES变量以-D形式注入编译,例如DEFINES='STM32F4 STM32F429xx USBD_SOF_DISABLED'

四、支持的硬件与驱动映射

原 README 给出了完整的 MCU 系列 → 驱动 → 源文件映射表,本文完整保留并补充脚注:

MCU 系列特性驱动文件
STM32L0x2 / L0x3 / F070 / F0x2 / F0x8双缓冲[2]、8[1] 个端点、BC1.2usbd_devfsusbd_stm32l052_devfs.c
同上(汇编版)同上usbd_devfs_asmusbd_stm32l052_devfs_asm.S
STM32L4x2 / L4x3 / G4 系列双缓冲[2]、8[1] 个端点、BC1.2usbd_devfsusbd_stm32l433_devfs.c
同上(汇编版)同上usbd_devfs_asmusbd_stm32l052_devfs_asm.S*
STM32L1xx双缓冲[2]、8[1] 个端点usbd_devfsusbd_stm32l100_devfs.c
同上(汇编版)同上usbd_devfs_asmusbd_stm32l100_devfs_asm.S
STM32F102 / F103 / F302 / F303 / F373双缓冲[2]、外部 DP 上拉、8[1] 个端点usbd_devfsusbd_stm32f103_devfs.c
同上(汇编版)同上usbd_devfs_asmusbd_stm32f103_devfs_asm.S
STM32WB55双缓冲[2]、外部 DP 上拉、8[1] 个端点usbd_devfsusbd_stm32wb55_devfs.c
STM32L4x5 / L4x6双缓冲、6 个端点、BC1.2、VBUS 检测usbd_otgfsusbd_stm32l476_otgfs.c
STM32F401 / F411双缓冲、4 个端点、VBUS 检测、SOF 输出usbd_otgfsusbd_stm32f429_otgfs.c
STM32F4x5 / F4x7 / F4x9双缓冲、4 个端点(FS);6 个端点(HS);VBUS 检测、SOF 输出usbd_otgfs/usbd_otghsusbd_stm32f429_otgfs.c/usbd_stm32f429_otghs.c
STM32F105 / F107双缓冲、4 个端点、VBUS 检测、SOF 输出usbd_otgfsusbd_stm32f105_otgfs.c
STM32F4x6 / F7双缓冲、6 个端点(FS);9 个端点(HS);VBUS 检测、SOF 输出usbd_otgfs/usbd_otghsusbd_stm32f446_otgfs.c/usbd_stm32f446_otghs.c
STM32H743双缓冲、6 个端点、VBUS 检测、SOF 输出usbd_otgfsusbd_stm32h743_otgfs.c

脚注(与原 README 一致):

  1. 单个物理端点可以实现:一个双向/单缓冲逻辑端点(CONTROL);或一个单向/双缓冲逻辑端点(BULK 或 ISOCHRONOUS);或两个单向/单缓冲逻辑端点(BULK 或 INTERRUPT)。
  2. 当前 BULK IN 端点虽可使用两个缓冲区,但并非“真正”的双缓冲。
  3. 已实测芯片:STM32L052K8、STM32L100RC、STM32L476RG、STM32F072C8、STM32F103C8/CB、STM32F303CC/RE、STM32F429ZI、STM32F105RBT6、STM32F107VCT6、STM32L433CCT6、STM32F070CBT6、STM32G431RB、STM32F411CEUx、STM32F405RG、STM32F446RE、STM32F373CC、STM32L053R8、GD32F103C8T6、STM32F745VE、STM32F401CE、STM32H743。

各驱动目标对应的开发板详情见 lib/libusb_stm32/hardware.md(如 bluepill、NUCLEO-L476RG、NUCLEO-F429ZI、Boring Tech STM32H743 等)。

说明:原 README 表中 STM32L4x2/L4x3/G4 的汇编版驱动文件写作usbd_stm32l052_devfs_asm.S;从仓库源码结构看,lib/libusb_stm32/src 目录下 L433 系列实际提供的是usbd_stm32l433_devfs.c(无独立 L433 汇编 ISR 文件),使用时建议以src/目录实际文件为准。

五、已实现的 USB 类规范

README 声明该栈内置了四类设备类(class)的定义与协议处理,全部依据 USB-IF 官方规范:

  1. USB HID—— Device Class Definition for Human Interface Devices (HID) Version 1.11;
  2. USB DFU—— USB Device Firmware Upgrade Specification Revision 1.1;
  3. USB CDC—— Class Definitions for Communication Devices 1.2;
  4. USB TMC—— USB Device Test and Measurement Class Specification Revision 1.0。

在仓库中,这些类以协议头文件形式位于 lib/libusb_stm32/inc:usb_hid.husb_dfu.husb_cdc.h(以及usb_cdca/cdce/cdci/cdcp/cdcw.h等 CDC 子协议细分头)、usb_tmc.husb_ccid.husb_std.h(标准请求/描述符定义),此外还有一整套 HID Usage Tables 头文件(hid_usage_keyboard.hhid_usage_led.hhid_usage_button.h等 13 个),可直接用于构造 HID 报告描述符。

Flipper 固件正是基于这些类头实现了furi_hal_usb_cdc.c(虚拟串口)、furi_hal_usb_hid.c(HID 键盘/鼠标)、furi_hal_usb_u2f.c(U2F 安全密钥)等 USB 接口。

六、依赖与获取

原 README 声明的运行/构建依赖:

  • CMSIS V4 或 CMSIS V5(ARM 核心头文件与内核兼容层);
  • stm32.h:STM32 通用设备头文件。

两者都可以通过 Makefile 内置的cmsis目标一键下载,目标目录由环境变量CMSIS指定:

make cmsis # 克隆 CMSIS_5 到 $(CMSIS) # 并克隆 dmitrystu/stm32h 到 $(CMSIS)/Device

对应 Makefile 规则(见 lib/libusb_stm32/Makefile):

cmsis: $(CMSISDEV)/ST $(CMSISDEV)/ST: $(CMSIS) @git clone --recurse-submodules --depth 1 https://github.com/dmitrystu/stm32h.git $@ $(CMSIS): @git clone --depth 1 https://github.com/ARM-software/CMSIS_5.git $@

七、Makefile 构建实战

7.1 构建静态库模块

将栈编译为独立静态库,供自己的固件工程链接:

make module MODULE=path/module.a DEFINES="mcu specified defines" CFLAGS="cpu specified compiler flags"

Makefile 中module目标先执行clean,再按$(MODULE)名称打包src/*.csrc/*.S的全部目标文件;DEFINES会自动加-D前缀、INCLUDES会展开为-I路径。

7.2 构建并烧录 demo

demo 是 lib/libusb_stm32/demo/cdc_loop.c——一个 CDC 回环程序(收到什么发回什么),是验证 USB 连通性的最小示例:

make bluepill program # STM32F103 bluepill:构建 + st-flash 烧录 make stm32l052x8 # 仅构建 STM32L052x8 目标,产出 cdc_loop.hex/.bin make help # 查看全部目标与变量说明

make help列出的全部 demo 目标包括:bluepill / stm32f103x6 / 32l100c-disco / stm32l100xc / 32l476rg-nucleo / stm32l476rg / stm32l052x8 / 32f429zi-nucleo / stm32f429xi / stm32f401xc / stm32f401xe,另有cmsis(下载依赖)与doc(Doxygen 文档)目标。

7.3 烧录方式

Makefile 提供三种烧录路径,均依赖先构建出cdc_loop.hex/cdc_loop.bin

目标工具命令形态
programst-flash(ST-Link)$(FLASH) --reset --format ihex write $(DOUT).hex
program_dfudfu-util$(DFU_UTIL) -d 0483:DF11 -a 0 -D $(DOUT).bin -s 0x08000000
program_stcubeSTM32CubeProgrammer CLI$(STPROG_CLI) -c port=SWD reset=HWrst -d $(DOUT).hex -hardRst

7.4 Makefile 默认变量一览

原 README 的默认值表如下,与 Makefile 实际定义相互印证(README 中MCU/CFLAGS/DEFINES列为 demo 工程默认值;当前 Makefile 中CFLAGS ?= -mcpu=cortex-m3DEFINES ?= STM32F1 STM32F103x6,即以 F103 为默认 demo 目标):

变量默认值含义
CMSIS./CMSISCMSIS 根目录路径
CMSISDEV$(CMSIS)/DeviceCMSIS 设备目录路径
CMSISCORE$(CMSIS)/CMSIS/Include $(CMSIS)/CMSIS/Core/IncludeCMSIS 核心头文件路径
MCUstm32l100xcdemo 工程的 MCU 选择
CFLAGS-mcpu=cortex-m3 -mfloat-abi=softMCU 相关编译选项
DEFINESSTM32L1 STM32L100xCMCU 相关宏定义
STPROG_CLI~/STMicroelectronics/STM32Cube/STM32CubeProgrammer/bin/STM32_Programmer_CLIST Cube Programmer CLI 路径
OPTFLAGS-Os代码优化级别

此外 Makefile 还定义了FLASH ?= st-flashTOOLSET ?= arm-none-eabi-(工具链前缀)、MODULE ?= libusb.a(模块输出名)、LDSCRIPT/STARTUP(由每个 demo 目标分别指定各自的链接脚本与启动文件,如demo/stm32wb55xg.ld+startup_stm32wb55xx_cm4.s)。每个 demo 目标的完整参数组合都显式写在 Makefile 中,例如:

stm32wb55xg: clean @$(MAKE) demo STARTUP='$(CMSISDEV)/ST/STM32WBxx/Source/Templates/gcc/startup_stm32wb55xx_cm4.s' \ LDSCRIPT='demo/stm32wb55xg.ld' \ DEFINES='STM32WB STM32WB55xx USBD_SOF_DISABLED' \ CFLAGS='-mcpu=cortex-m4'

这段配置对 Flipper 用户尤其有参考价值——它演示了为具体 MCU 选择启动文件、链接脚本、系列宏与裁剪宏的标准做法。

八、Flipper Zero 固件中的实际应用

Flipper Zero(f7 目标)使用的正是本文第四表中的STM32WB55驱动 lib/libusb_stm32/src/usbd_stm32wb55_devfs.c(usbd_devfs系,外部 DP 上拉、8 个端点)。固件侧封装见 targets/f7/furi_hal/furi_hal_usb.c,关键调用链为:

// 1) 时钟/GPIO/VDDUSB 准备后,用 usbd_devfs 驱动的 usbd_hw 初始化设备 usbd_init(&udev, &usbd_hw, USB_EP0_SIZE, ubuf, sizeof(ubuf)); // 2) 使能硬件,注册描述符回调与挂起/唤醒事件回调 usbd_enable(&udev, true); usbd_reg_descr(&udev, usb_descriptor_get); usbd_reg_event(&udev, usbd_evt_susp, susp_evt); usbd_reg_event(&udev, usbd_evt_wkup, wkup_evt); // 3) 开启 USB_LP/USB_HP 双中断,启动 UsbDriver 服务线程轮询事件 NVIC_EnableIRQ(USB_LP_IRQn); NVIC_EnableIRQ(USB_HP_IRQn);

其中控制端点包大小由 targets/f7/furi_hal/furi_hal_usb_i.h 中的#define USB_EP0_SIZE 8指定,并在 CDC/HID/U2F 三个接口的设备描述符bMaxPacketSize0中复用——这正是 README 强调的“核心与硬件驱动分离、端点 0 大小可配置”设计的实际体现。设备状态结构UsbSrv、控制缓冲ubufusbd_device udev通过PLACE_IN_SECTION("MB_MEM2")放入指定内存段,配合消息队列 + 服务线程实现线程安全的 USB 接口切换(furi_hal_usb_set_config在 CDC/HID/U2F 等接口之间切换)。

构建层面,该库的源码被纳入 lib/SConscript 的源文件清单("libusb_stm32"一项),由 SCons 统一编译进固件,而非走 README 描述的独立 Makefile 流程——独立 Makefile 保留用于库的独立开发、demo 验证与第三方项目集成。

九、小结与延伸阅读

  • 本文主体内容全部来自 lib/libusb_stm32/readme.md,配套资料包括:Makefile(构建规则)、hardware.md(目标板清单)、inc/usbd_core.h(核心 API 与编译期宏)、demo/cdc_loop.c(CDC 回环示例);
  • 在 Flipper 固件中追踪 USB 底层:从 targets/f7/furi_hal/furi_hal_usb.c 出发,可看到usbd_init→ 事件回调 → CDC/HID/U2F 接口的完整链路;
  • 该栈遵循 Apache License 2.0(见 lib/libusb_stm32/LICENSE),类规范依据均为 USB-IF 官方文档(HID 1.11、DFU 1.1、CDC 1.2、TMC 1.0),可作为在任意 STM32 设备上实现标准 USB 设备类的完整参考实现。

【免费下载链接】flipperzero-firmwareFlipper Zero firmware source code项目地址: https://gitcode.com/GitHub_Trending/fl/flipperzero-firmware

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/14 15:57:26

Unity资源寻址机制深度解析:从GUID到Addressables的七层原理

1. 什么是Unity资源寻址机制&#xff1a;它不是“找文件”&#xff0c;而是构建运行时的资源身份系统你刚在Unity里拖进一个Texture2D&#xff0c;给它起名叫“PlayerIcon”&#xff0c;然后在脚本里写Resources.Load<Texture2D>("PlayerIcon")——看起来很简单…

作者头像 李华
网站建设 2026/9/14 15:57:18

PHP图书馆管理系统源码部署与二次开发实践

简介&#xff1a;基于PHP开发的新翔图书馆管理系统源码&#xff0c;是一份面向Web开发初学者与进阶者的完整实战项目&#xff0c;覆盖图书借阅、归还、查询、统计等业务场景&#xff0c;可帮助理解MVC分层架构及PHP与MySQL的协作方式。压缩包共164个文件&#xff0c;以84个php源…

作者头像 李华
网站建设 2026/9/14 15:57:13

静态网页30页实战:统一目录与脚本实现产品图一键替换

简介&#xff1a;这是一套由30个静态网页组成的汽车新闻资讯类网站模板&#xff0c;整体基于DIVCSSjQuery开发&#xff0c;适合前端初学者在真实站点结构中练习页面布局、导航交互与样式调试&#xff0c;也能直接作为毕业设计或企业宣传网站的底稿。模板中的汽车图片和资讯文案…

作者头像 李华
网站建设 2026/9/14 15:56:26

Dify vs 讯飞星辰Agent:开源私有化与云端托管智能体平台选型指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/14 15:55:00

DeepSeek桌面端技术解析:告别WebUI的架构跃迁

1. 项目概述&#xff1a;为什么“跟 WebUI 说再见”不是口号&#xff0c;而是真实的技术跃迁 “跟 WebUI 说再见了&#xff0c;最强 DeepSeek 桌面端来了&#xff01;”——这句话乍看像营销话术&#xff0c;但如果你过去半年里反复折腾过 Open WebUI、Ollama UI、Text Generat…

作者头像 李华
网站建设 2026/9/14 15:52:15

Android医药助手源码实战:从药箱管理到精准用药提醒

简介&#xff1a;面向Android初、中级开发者的医药助手项目源码&#xff0c;适合研究医疗健康类App的药品查询、用药提醒、健康资讯等典型业务模块。压缩包共113个文件&#xff0c;仅1.09MB&#xff0c;以Java源码、XML界面、SQLite数据库脚本为主&#xff0c;并含class/apk/de…

作者头像 李华