
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 workflowUSB 事务通过统一事件回调分发而不是阻塞式状态机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_driverstruct 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_ADDRFSTSTATUS_OUT 前设置地址、USBD_HW_BCBC1.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形式注入编译例如DEFINESSTM32F4 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.SSTM32L4x2 / 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.SSTM32F102 / F103 / F302 / F303 / F373双缓冲[2]、外部 DP 上拉、8[1] 个端点usbd_devfsusbd_stm32f103_devfs.c同上汇编版同上usbd_devfs_asmusbd_stm32f103_devfs_asm.SSTM32WB55双缓冲[2]、外部 DP 上拉、8[1] 个端点usbd_devfsusbd_stm32wb55_devfs.cSTM32L4x5 / L4x6双缓冲、6 个端点、BC1.2、VBUS 检测usbd_otgfsusbd_stm32l476_otgfs.cSTM32F401 / F411双缓冲、4 个端点、VBUS 检测、SOF 输出usbd_otgfsusbd_stm32f429_otgfs.cSTM32F4x5 / F4x7 / F4x9双缓冲、4 个端点FS6 个端点HSVBUS 检测、SOF 输出usbd_otgfs/usbd_otghsusbd_stm32f429_otgfs.c/usbd_stm32f429_otghs.cSTM32F105 / F107双缓冲、4 个端点、VBUS 检测、SOF 输出usbd_otgfsusbd_stm32f105_otgfs.cSTM32F4x6 / F7双缓冲、6 个端点FS9 个端点HSVBUS 检测、SOF 输出usbd_otgfs/usbd_otghsusbd_stm32f446_otgfs.c/usbd_stm32f446_otghs.cSTM32H743双缓冲、6 个端点、VBUS 检测、SOF 输出usbd_otgfsusbd_stm32h743_otgfs.c脚注与原 README 一致单个物理端点可以实现一个双向/单缓冲逻辑端点CONTROL或一个单向/双缓冲逻辑端点BULK 或 ISOCHRONOUS或两个单向/单缓冲逻辑端点BULK 或 INTERRUPT。当前 BULK IN 端点虽可使用两个缓冲区但并非“真正”的双缓冲。已实测芯片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 官方规范USB HID—— Device Class Definition for Human Interface Devices (HID) Version 1.11USB DFU—— USB Device Firmware Upgrade Specification Revision 1.1USB CDC—— Class Definitions for Communication Devices 1.2USB TMC—— USB Device Test and Measurement Class Specification Revision 1.0。在仓库中这些类以协议头文件形式位于 lib/libusb_stm32/incusb_hid.h、usb_dfu.h、usb_cdc.h以及usb_cdca/cdce/cdci/cdcp/cdcw.h等 CDC 子协议细分头、usb_tmc.h、usb_ccid.h、usb_std.h标准请求/描述符定义此外还有一整套 HID Usage Tables 头文件hid_usage_keyboard.h、hid_usage_led.h、hid_usage_button.h等 13 个可直接用于构造 HID 报告描述符。Flipper 固件正是基于这些类头实现了furi_hal_usb_cdc.c虚拟串口、furi_hal_usb_hid.cHID 键盘/鼠标、furi_hal_usb_u2f.cU2F 安全密钥等 USB 接口。六、依赖与获取原 README 声明的运行/构建依赖CMSIS V4 或 CMSIS V5ARM 核心头文件与内核兼容层stm32.hSTM32 通用设备头文件。两者都可以通过 Makefile 内置的cmsis目标一键下载目标目录由环境变量CMSIS指定make cmsis # 克隆 CMSIS_5 到 $(CMSIS) # 并克隆 dmitrystu/stm32h 到 $(CMSIS)/Device对应 Makefile 规则见 lib/libusb_stm32/Makefilecmsis: $(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 MODULEpath/module.a DEFINESmcu specified defines CFLAGScpu specified compiler flagsMakefile 中module目标先执行clean再按$(MODULE)名称打包src/*.c、src/*.S的全部目标文件DEFINES会自动加-D前缀、INCLUDES会展开为-I路径。7.2 构建并烧录 demodemo 是 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下载依赖与docDoxygen 文档目标。7.3 烧录方式Makefile 提供三种烧录路径均依赖先构建出cdc_loop.hex/cdc_loop.bin目标工具命令形态programst-flashST-Link$(FLASH) --reset --format ihex write $(DOUT).hexprogram_dfudfu-util$(DFU_UTIL) -d 0483:DF11 -a 0 -D $(DOUT).bin -s 0x08000000program_stcubeSTM32CubeProgrammer CLI$(STPROG_CLI) -c portSWD resetHWrst -d $(DOUT).hex -hardRst7.4 Makefile 默认变量一览原 README 的默认值表如下与 Makefile 实际定义相互印证README 中MCU/CFLAGS/DEFINES列为 demo 工程默认值当前 Makefile 中CFLAGS ? -mcpucortex-m3、DEFINES ? STM32F1 STM32F103x6即以 F103 为默认 demo 目标变量默认值含义CMSIS./CMSISCMSIS 根目录路径CMSISDEV$(CMSIS)/DeviceCMSIS 设备目录路径CMSISCORE$(CMSIS)/CMSIS/Include $(CMSIS)/CMSIS/Core/IncludeCMSIS 核心头文件路径MCUstm32l100xcdemo 工程的 MCU 选择CFLAGS-mcpucortex-m3 -mfloat-abisoftMCU 相关编译选项DEFINESSTM32L1 STM32L100xCMCU 相关宏定义STPROG_CLI~/STMicroelectronics/STM32Cube/STM32CubeProgrammer/bin/STM32_Programmer_CLIST Cube Programmer CLI 路径OPTFLAGS-Os代码优化级别此外 Makefile 还定义了FLASH ? st-flash、TOOLSET ? arm-none-eabi-工具链前缀、MODULE ? libusb.a模块输出名、LDSCRIPT/STARTUP由每个 demo 目标分别指定各自的链接脚本与启动文件如demo/stm32wb55xg.ldstartup_stm32wb55xx_cm4.s。每个 demo 目标的完整参数组合都显式写在 Makefile 中例如stm32wb55xg: clean $(MAKE) demo STARTUP$(CMSISDEV)/ST/STM32WBxx/Source/Templates/gcc/startup_stm32wb55xx_cm4.s \ LDSCRIPTdemo/stm32wb55xg.ld \ DEFINESSTM32WB STM32WB55xx USBD_SOF_DISABLED \ CFLAGS-mcpucortex-m4这段配置对 Flipper 用户尤其有参考价值——它演示了为具体 MCU 选择启动文件、链接脚本、系列宏与裁剪宏的标准做法。八、Flipper Zero 固件中的实际应用Flipper Zerof7 目标使用的正是本文第四表中的STM32WB55驱动 lib/libusb_stm32/src/usbd_stm32wb55_devfs.cusbd_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、控制缓冲ubuf与usbd_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.cCDC 回环示例在 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),仅供参考