STM32 USBx Device MSC standalone 移植示例 LAT1488
关键字:USBx, Device, MSC,standalone
1.设计目的
目前有关 USBx Device standalone 的官方示例较少,不过使用 CubeMX 可以快速地生成 USBx Device 相关类的示例工程,会很方便大家的开发。这里以 NUCLEO-H563 为例,实现 USBx Device MSC Standalone 类,这里以 MCU 内部的 RAM 为存储介质,大家可以拿来作为参考移植到其他的 USBx Device 类。
2.示例移植
参考官方示例代码(存储介质为 SD 卡):
……\STM32Cube\Repository\STM32Cube_FW_H5_V1.3.0\Projects\STM32H573I-DK\Applications\USBX\Ux_Device_MSC\EWARM
2.1.生成 CubeMX 工程
新建 CubeMX 工程 :STM32H563ZIT6U,选择 without TrustZone activated. 另外,CubeMX 中未作说明的配置保持默认.
2.1.1 System Core 相关配置
在 System Core 框架下,Cortex_M33 标签页面下默认使用的是 HCLK. 如下图:
RCC 的标签页下面:采用 BYPASS Clock Source MCO 引脚输出作为 MCU 的系统时钟源,如下图:
在 ICACHE 的标签页下的配置如下图:
另外,SYS 标签页下面的 Timebase Source 为 Systick
2.1.2 Connectivity 的相关配置
根据 NUCLEO-H563 的硬件原理图定义,这里选择 USART3 打印输出相关的 USB 操作信息。
不用开中断或者 DMA,波特率默认 115200.
注意修改 USART3 使用的端口引脚,这儿是 PD8 与 PD9,与默认 CubeMX 配置引脚不一样。
在 USB 下面的配置如下:选择 Device_Only,使能 USB 全局中断,中断优先等级设置为 6;
2.1.3 Middleware 的相关配置
在 USBx 下面, 由于是 standalone 的示例,所以这儿不用选择操作系统的中间件。
Device Class FS 选择 MSC,另外 Platform Settings 下面的 Found Solutions 选择 USB.
对于 USBx 的具体配置如下图,可以看出主要检查或修改了默认的如下框出来的几处地方,
UXDevice memory pool size 由默认的 1024 设置为 7K(7*1024Bytes),
UX_SLAVE_REQUEST_DATA_MAX_LENGTH 由默认的 2048 设置为 1024,
由于当前 MSC 例程的描述符中会使用到 1 个接口,所以 USBD_COMPOSITE_USE_IAD 设置为 false !!!
USBX Device System Stack Size 由默认的 512 设置为 5K(5*1024Bytes),
USBX Device Register Connection Callback 设置为 true ;
UX_SLAVE_CLASS_STORAGE_INCLUDE_MMC,在本例程存储介质非 MMC 卡,用不到,选择 Disabled.
其余的配置参考上图,可以修改 USB 端点相关的信息。
2.1.4 System Clock 相关配置
由于选择了 Bypass 模式的 8Mhz,这里注意要修改为一致(默认的是 25Mhz)。USB DeviceIP 的时钟需要 48Mhz,这里选择 HSI48=48Mhz ;
2.1.5 生成项目工程
为项目工程命名,生成项目工程,配置堆栈的大小:
然后生成项目工程代码。
2.2.添加运用代码
2.2.1 完善串口打印
可以参考《STM32 USBx Host HID standalone 示例移植》中的说明去完善串口打印信息。
由于是 USB Device,也可以通过 USB 协议分析仪去查看 log 调试。
2.2.2 添加 USBx 的初始化函数
添加初始化函数如下图,
该函数在 CubeMX 中已经生成,在 MX_USBX_Device_Init 函数的末尾去添加USBX_APP_Device_Init ();的初始化的调用;
添加相关函数的声明和定义;
其中,USBX_APP_Device_Init();的实现参考前面提及到的例程和 Cube 库中对应 MCU 系列的 USBx 例程这两个,稍作修改即可:
添加 PCD_HandleTypeDef hpcd_USB_DRD_FS 的申明;
添加 USBX_APP_Device_Init 函数中 MX_USB_PCD_Init 函数的定义,该函数由 CubeMX自动生成在 main.c 文件中,但是如果函数 static 属性,在其他文件不能调用,将 static 关键字去除即可,解决编译错误之后,运行,此时枚举不成功;
2.2.3 添加 USBx 的处理函数
在 main 函数的 while 循环中添加函数 USBX_Device_Process();
添加该函数 USBX_Device_Process 的定义和申明在 app_usbx_device.c 文件中实现,
编译无问题后,运行,实现枚举。
这时候枚举成功了,在电脑 PC 端会弹出盘符,但是没有容量等信息,而且选中该 U 盘,右击选择格式化也不能读出其容量,格式化操作也不行。
就需要实现其 MSC 的读写驱动函数了。
2.2.4 MSC 容量的实现
由于是 MSC 的 RAM 作为存储介质,所以需要对 MCU 内部的 RAM 做一个划分,根据不同的编译器去划分,这儿以 IAR 为例,抽取的是(0x2009FFFF-0x20060000)+1 = 256KB 的容量作为 USB MSC 的存储空间;
2.2.5 MSC 读写功能函数的实现
读函数:
写函数:
符合预期。
需要注意的是读写函数返回的状态均是 UX_STATE_NEXT,而不是 UX_SUCCESS。主要的原因如下图代码的说明:
本文只是简单的实现的少量数据的传输读写功能,如果要实现大量数据的通讯等,请根据相关逻辑自行实施。