当前位置: 首页 > news >正文

TeenyUSB MSC U盘开发指南:用FatFs打造你自己的闪存U盘设备

TeenyUSB MSC U盘开发指南:用FatFs打造你自己的闪存U盘设备

【免费下载链接】TeenyUSBLightweight USB device and host stack for STM32 and other MCUs. Ready for USB 3.0 device.项目地址: https://gitcode.com/gh_mirrors/te/TeenyUSB

TeenyUSB 是一个轻量级单片机 USB 协议栈,支持 STM32、CH565W 等主流 MCU 的 USB 设备与主机模式。本指南带你用 TeenyUSB 的 MSC(大容量存储类)功能,把 MCU 做成一台电脑即插即用的 U 盘,并配合项目内置的 FatFs 文件系统,直接在 U 盘上读写文件——无需任何驱动,Windows/macOS/Linux 全平台免驱识别。

1. 三分钟了解 MSC 设备架构 🧩

把 MCU 变成 U 盘,本质上就是让单片机应答标准的 SCSI 命令。TeenyUSB 在class/msc/目录下提供了完整的 MSC BOT(Bulk-Only Transport)协议实现:

模块路径作用
MSC 设备类tusbd_msc.cBOT 协议状态机、SCSI 命令解析
MSC 设备接口tusbd_msc.htusb_msc_device_t结构与回调定义
BOT 协议定义tusb_msc.hCBW/CSW 包格式
SCSI 命令定义tusb_scsi.hINQUIRY、READ(10)、WRITE(10) 等命令
复合设备示例composite_device.c含 MSC U 盘的完整可编译例程

USB 传输由底层 API 与中断回调完成,而应用层只需要关心三件事:

  1. 写三个块级回调函数get_cap(容量)、block_read(读块)、block_write(写块);
  2. 填一个结构体,把回调挂到tusb_msc_device_t上;
  3. 在主循环里调用tusb_msc_device_loop()处理命令。

这就是 TeenyUSB "teeny"(迷你)的精髓——MSC 设备类代码只有几百行,却能让电脑把你的 MCU 识别成标准可移动磁盘。

2. 用 TeenyDT 生成带 MSC 接口的描述符

USB 描述符不需要手写,项目自带基于 Lua 的描述符生成工具TeenyDT(源码见 TeenyDT/)。在 composite_desc.lua 中,MSC 接口只需 6 行配置:

Interface{ bInterfaceClass = 0x08, -- MSC bInterfaceSubClass = 0x06, -- SCSI bInterfaceProtocol = 0x50, -- BOT EndPoint(IN(4), BulkDouble, 64), EndPoint(OUT(4), BulkDouble, 64), }

生成后的teeny_usb_desc.c/h由脚本自动产出,其中BulkDouble表示按高速/全速自动调整端点包长。三个值0x08 / 0x06 / 0x50是 U 盘识别的"身份证",操作系统看到它们就会加载大容量存储驱动。

3. 实现块设备回调:告诉协议栈数据存哪里

MSC 层只操作 512 字节的"块",存储介质可以是 RAM、NOR Flash、SD 卡甚至 NAND。以 composite_device.c 中的 RAM 盘为例:

tusb_msc_device_t msc_dev = { .backend = &msc_device_backend, .ep_in = 4, .ep_out = 4, .max_lun = 0, // 1个逻辑单元 .get_cap = msc_get_cap, // 返回块数/块大小 .block_read = msc_block_read, .block_write = msc_block_write, };
  • RAM 盘(示例代码 L233-L272):START_ADDR指向 RAM 尾部的空闲区域,BLOCK_COUNT按芯片 RAM 计算,读写就是memcpy,速度最快,适合功能演示;
  • Flash 盘(示例代码 L275-L297):START_ADDR从 Flash 偏移 20KB 处开始,块大小取 Flash 扇区大小,写入调用flash_write(),适合做真正的"闪存 U 盘",但注意 Flash 擦写寿命有限。

两个回调的返回值约定很清晰:返回实际读写的字节数,出错返回 -1,协议栈会自动填充相应的 SCSI Sense 错误码(如MEDIUM_ERRORWRITE_FAULT),宿主机就能看到"读写失败"提示。

⚠️常见坑MSC_DATA_PACKET_LENGTH数据缓冲区必须 ≥ 512,否则 composite_device.c 末尾的编译期检查会直接报错。

配置好结构体后,只需在主循环中周期性调用tusb_msc_device_loop(&msc_dev);(示例代码 L229),电脑即可看到一块可移动磁盘。

4. 用 FatFs 让 U 盘支持文件读写 📁

裸盘只是一堆块数据,接上 FatFs 后电脑才能看到.txt.jpg这样的文件。项目已在 third_part/fatfs/ 内置完整的 FatFs 源码:

  • ff.c / ff.h:文件系统核心(FAT12/16/32 读写)
  • ffconf.h:功能裁剪配置
  • diskio.c:底层磁盘适配"胶水层"

FatFs 通过diskio.c与具体存储解耦,其中预留了 RAM/MMC/USB 三种物理盘的定义。接入自己的存储只需实现四个胶水函数(以 RAM 盘为例):

DRESULT RAM_disk_read(BYTE *buff, LBA_t sector, UINT count) { memcpy(buff, (void*)START_ADDR + sector*512, count*512); return RES_OK; }

然后挂载并验证:

f_mount(&fs, "", 1); // 挂载盘0 FRESULT res = f_open(&file, "hello.txt", FA_READ); f_read(&file, buf, sizeof(buf), &bytes); // 读出U盘里的文件

由于 TeenyUSB 的block_read/block_write回调与disk_read/disk_write参数几乎一致(起始块地址 + 块数 + 缓冲区),FatFs 层可以零拷贝地直接调用 MSC 的同一套存储函数,一套介质驱动同时服务于"USB 对外服务"和"自己读自己的盘"两个方向。

💡提示:FAT 的根目录表、FAT 表会频繁改写。若介质是 Flash,建议在diskio.c中加一层块缓存,或把 FAT 表映射到 RAM,可显著延长 Flash 寿命。

5. 一键编译验证

项目使用arm-none-eabi-gcc工具链编译,MSC 已集成在 composite 复合设备示例中(HID + CDC + WinUSB + MSC 四合一):

git clone https://gitcode.com/gh_mirrors/te/TeenyUSB cd TeenyUSB git submodule update --init # 拉取mcu_lib的STM32库 cd sample make comp

支持的验证板卡包括 STM32F072/F103/F107/F303/F407/F723/F767/H743 及 CH565W(USB 3.0 设备),各板卡配置见 sample/boards/。烧录后插线到电脑,设备管理器中应看到 "TeenyUSB" 厂商名的可移动磁盘(SCSI INQUIRY 回复默认是TeenyUSB / MSC BOT DEMO,可在 tusbd_msc.c 的msc_scsi_inquiry()中改成你自己的品牌名)。

6. 常见问题排查清单 ✅

现象原因与对策
电脑识别为未知设备描述符 MSC 三字节不对,确认0x08/0x06/0x50,并用 TeenyDT 重新生成
磁盘容量为 0 或异常get_cap返回的block_num计算错误,注意减去程序与栈占用的空间
读写偶发失败block_read/block_write返回了 -1,检查地址越界与 Flash 扇区对齐
FatFs 挂载失败(FR_NO_FILESYSTEM)裸盘无 FAT 表,先用电脑格式化一次或调用f_mkfs()初始化
编译报错 buffer 太小MSC_DATA_PACKET_LENGTH提到 ≥ 512

进阶方向tusb_msc_device_t支持max_lun多逻辑单元和可选的scsi_opsis_readyloadEjectinquiry),可以实现"可弹出"语义和自定义 INQUIRY 品牌信息;主机侧的 tusbh.c 同样实现了 MSC Host 类,同一块板还能反过来读取插入的 U 盘——设备与主机双角色,这正是 TeenyUSB 相比同类轻量栈的优势所在。

祝你的第一块"MCU 自制 U 盘"点亮成功!🚀

【免费下载链接】TeenyUSBLightweight USB device and host stack for STM32 and other MCUs. Ready for USB 3.0 device.项目地址: https://gitcode.com/gh_mirrors/te/TeenyUSB

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

http://www.cnnetsun.cn/news/4248302.html

相关文章:

  • KKCE: 网站测速,ping检测,IP查询,路由追踪-快快测
  • AI情感陪伴的隐私风险:从上下文窗口到数据脱敏的技术拆解
  • FigmaCN:Figma界面汉化插件安装教程,4000+人工校验词条,3分钟装好
  • Hotfix API 参考:HotFix.patch() 方法完整用法与参数说明
  • ESAM 配置文件解读指南:decoder、merge_head 与 test_cfg 三大模块参数完整说明
  • 实时上报停留时长数据:TimeMe.js内置WebSocket通道3步集成教程
  • Cushy主题与样式实战:从暗色模式切换到OKLab色彩方案编辑器手把手教程
  • quicktime_video_hack如何建立屏幕流会话:15步USB握手协议逐步图解
  • 基于相似性推理的博弈论方法:多智能体协作中的理性合作策略
  • 【AI大模型实战】手把手教你基于Dify搭建RAG知识库,全程干货,零基础小白也能轻松学会!!
  • 【AI大模型教程】一文讲清支持 MCP 的七大 AI 框架有哪些!零基础小白收藏这一篇就够了!!
  • 从内存数据库走向云原生数据底座,深入理解 SAP HANA Cloud
  • SAR成像全链路解析:从点目标仿真到实测数据处理
  • bravado响应处理完全手册:HttpFuture、超时降级fallback_result与错误捕获最佳实践
  • MPDroid进阶功能:输出设备管理、网络电台与Sticker评分完整攻略
  • extended_text_field 渲染层揭秘:ExtendedRenderEditable 光标定位与桌面端拼音输入修复
  • LRU缓存淘汰机制全揭秘:SDURLCache如何守护你的磁盘容量上限
  • 悟空Agent实战:LLaMA-Factory高危0day漏洞挖掘与修复
  • 大模型推理为什么又长又啰嗦?更多thinking≠更好结果,精准thinking可砍掉一半长度
  • 收藏!小白也能学会!LangChain.js智能体开发指南:10大编排模式详解与实战应用
  • Jeff Dean押注AI4S:从分布式系统到科学发现的基础设施革命
  • IntelliJ IDEA快捷键
  • 【AI大模型】腾讯屠榜MTEB,嵌入模型告别BERT,拥抱LLM
  • 智能体Agent:怎样用自然语言重构数据开发?看完这一篇你就懂了!!
  • 水下鱼类实例分割实战:从COCO数据集到YOLOv8训练全流程
  • 【大模型必备】位置编码终极指南:收藏学习RoPE如何改变Transformer架构
  • 7B扩散LLM,居然能跟671B的DeepSeek V3掰手腕,扩散vs自回归,谁才是未来?
  • C指针进阶:Beej‘s Guide to C指针运算与数组本质完整指南
  • WinDiskWriter:macOS上3步做出Windows启动盘
  • UUIDv1秒变v6的位运算魔法:uuid-creator TimeOrderedCodec源码剖析