本文主要介绍了如何移植TinyUSB并实现CDC+MSC(虚拟串口和大容量存储设)例程
1. TinyUSB库导入
tinyusb库的导入有两种方式,可以下载源码后只复制相关核心源码到自己得工程中,也可以使用git submodule得方式直接添加到子模块。本例使用第二种方式。
我们得工程是使用STM32CubeMX生成得工程,直接在工程目录下增加子模块:
1 | git submodule add https://gitee.com/mirrors/TinyUSB.git TinyUSB |
检出版本0.14.0,TinyUSB的目录结构中如下:
- TinyUSB/src 为源码目录以及公共源码
- TinyUSB/example 为例程目录
- TinyUSB/src/device 为设备相关源码
- TinyUSB/src/common 为公共源码
- TinyUSB/src/class 为设备类相关源码
- TinyUSB/src/portable 为不同平台的底层驱动文件
其中列出了与本例相关的核心文件,将这些文件以库或者源码的形式添加到CmakeList.txt中:
1 | Add library tinyusb |
唯一需要注意的是,如果使用到了cdc功能,STM32G系列的USB属于全速设备,port文件使用dcd_stm32_fsdev.c文件
2. 实现CDC和MSC设备关键回调函数
2.1 USB设备的回调函数
与Device设备的几个重要回调函数如下:
- tud_mount_cb 设备挂载成功回调
- tud_umount_cb 设备卸载回调
- tud_suspend_cb 设备挂起回调
- tud_resume_cb 设备恢复回调
以上我们在任意位置视情况实现功能,本例中默认回调函数为空
1 | void tud_mount_cb(void) {} |
2.2 CDC设备的回调函数
与CDC功能有关的回调函数如下:
- tud_cdc_line_state_cb 状态变化回调
- tud_cdc_rx_cb 接收到数据回调
以上我们在任意位置视情况实现功能,本例中默认回调函数为空
1 | void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts) { |
2.3 MSC设备的回调函数
与MSC相关的回调函数如下:
- tud_msc_inquiry_cb 请求磁盘信息的回调,决定了PC端显示U盘名称等信息
- tud_msc_test_unit_ready_cb 测试单元读的回调
- tud_msc_capacity_cb 获取磁盘块大小和数量回调,决定了PC端显示U盘的存储空间
- tud_msc_start_stop_cb PC端Star/Stop命令回调
- tud_msc_read10_cb 读数回调,PC端读取文件的处理
- tud_msc_is_writable_cb 可写属性回调,决定磁盘是否可写
- tud_msc_write10_cb 写数据回调,PC端写入文件处理
- tud_msc_scsi_cb 其他SCSI命令回调
关于这部分的实现,我们拷贝TinyUSB->example->device->cdc_msc->src目录下msc_disk.c、usb_descriptors.c、tusb_config.h三个文件到自己的工程文件下,并加载到工程CmakeList.txt
1 | Add sources to executable |
在tusb_config.h文件中,暂时不更改任何内容,注释掉msc_disk.c中的头文件
1 | // #include "bsp/board.h" |
可以在头文件中指定MCU类型,也可以在CmakeList.txt中指定
1 | {CMAKE_PROJECT_NAME} PRIVATE |
以上相关移植和配置工作完成,最后只需要在主程序中初始化并循环执行即可,如果在编译遇到报错,请检查上述内容是否有遗漏
1 | void Main() { |
3. 实现效果
烧录成功后,插入USB,PC端会自动弹出U盘,显示默认README.txt文件。