运行 Ux_Host_HUB_HID_MSC 通过 Hub 连接 U 盘读写不稳定问题分析 LAT1511

***关键字:*USB_OTG_HS,USB,HUB,FILEx,U 盘

1. 前言

客户使用 STM32U5 来开发一款外销型充电产品时,需要使用到 USB_OTG_HS 实现 HUB功能,并对 HUB 上的 U 盘进行高速写入操作。然而,客户在 NUCLEO-U5A5ZJ 板上运行 ST 官方例程 Ux_Host_HUB_HID_MSC 进行 U 盘性能读写测试时发现,在向 U 盘中写入小量数据是好的。但是,如果一次性连续写入大量数据如 1G 时会随机出现写入失败,返回值为 0x5C。

客户进一步反馈,如果直接将 U 盘连接到 NUCLEO 板,不通过 HUB 转接是 OK 的。且对U 盘有选择性,有些 U 盘出错概率小一些,有些概率 100%出现。希望知道 STM32U5 的 U 盘最快读写速度是多少。

2. 问题调研与复现

对客户板子及原理图进行检查后并未发现明显问题,笔者使用 STM32U5A9J-DK 板子对问题进行了验证。由于 FILEx 默认只支持 FAT32 格式的 U 盘,笔者使用的 U 盘容量是64G,需使能对 ExFAT 格式大容量 U 盘支持。

例程默认的 U 盘写入测试程序如下图所示:

显然例程默认数据单次写入长度是很小的,而且只写入了一次,频次远远不够。

修改测试程序大幅提高单次数据写入长度和数据吞吐量,测试代码如下所示。

笔者一共测试了 3 个不同品牌型号的 U 盘,测试结果如下:

所有 U 盘直连到板子都能成功写入,但是当通过 HUB 连接后,U 盘均会出现写入失败,只是各品牌的 U 盘出失败的概率不一样,还与 Hub 的口相关,有些 PORT 口概率低一些。

如下图所示:

将 UCHAR Write_buffer[64]单次写入数据长度改为 64/128/256/512 进行测试发现,可以成功(但是偶尔也会出错),但是速率无法接受。

3. 问题解决办法

通过上面对问题的复现,U 盘写入失败确实与 Hub 有关,通过对 FILEx 写入函数 fx_file_write 进行 debug,发现返回值 0x5C 并不属于 FILEx 模块里面定义的返回值,而是在 USBx/core 的头文件中定义的,0x5C 为 USB 传输请求超时。

进一步跟踪代码发现,出现传输超时由_ux_hcd_stm32_request_control_transfer 函数内部等待信号量时发生超时:

经过多次反复尝试,修改单次写入长度 Length 的大小(Write_buffer[Length])可以显著改善。因此,笔者大胆推测接 HUB 后,引发的 Timeout 原因极有可能与 MCU 处理性能密切相关,笔者查阅了 HUB 的相关资料,市面上大部分 HUB 主控芯片均采用高性能 ASIC 专用芯片,往往HUB 具有较高的数据吞吐量, 极低的响应延时时间。

既然,推测可能是与 MCU 处理性能相关,那么我们有没有什么办法提高 MCU 处理性能呢?经过检查代码发现在初始化 USB_OTG_HS 时内部 DMA 是没有使能的。于是使能USB_OTG_HS 内部专用 DMA。

重新编译后,再次下载运行,插上 HUB 重新测试写入超时现象消失,笔者分别将单次写入长度最大设置到 64K,即 Write_buffer[64*1024],并且交叉更换不同的 HUB 和 U 盘写入仍然正常。

如下图所示:

使能 USB_OTG_HS 的 DMA 本质是减小了 CPU 的负载,从而提升总线响应时间和效率。既然使能 DMA 可以解决此问题。这又令笔者想到了 STM32H5 的 ICache 支持 2 种配置模式,分别为 :

1-way(direct mapped mode) :每个缓存块只能存储在缓存中的一个固定位置。每个块只能存放在特定位置,容易导致冲突(即不同的数据可能映射到相同的位置,导致频繁替换。

2-way(set associative cache) : 缓存被分为多个组,每组可以容纳两个块。因为每个组可以存放两个块,减少了冲突的概率。

对于更详细和专业的 Cache 介绍读者可以查阅相关更专业的资料。

例程使用的 ICache 默认模式为 1-way(direct mapped mode) ,那么我们将其改为 2-way(set associative cache) 能否提升 USB 写入的性能呢,从而达到与使能 DMA 同样的效果呢。

修改代码使能 ICACHE_2WAYS 模式,将 hhcd_USB_OTG_HS.Init.dma_enable=DISABLE.

下载代码测试发现,问题不再出现,交叉更换不同的 HUB 和 U 盘写入仍然正常。

除了前面提到的使能 DMA,ICACHE_2WAYS 使能以外,我们还可以做如下配置,来进一步提升写入性能。

以下是笔者向 U 盘连续地写入 1GByte 文件时所获得的实测性能,供参考如下:

4. 总结

可见,使能 USB_OTG_HS 的 DMA 和配置 ICache 工作模式为 2-way(set associative cache) ,均可以解决此问题,但只能定性此问题确实与 CPU 的性能相关。而多级 HUB 传输它需要额外的数据进行数据的包装,从而导致时间的增加。

相关推荐
咸鱼嵌入式1 天前
【AutoSAR】详解CANIF模块
单片机·mcu·车载系统·autosar
EVERSPIN2 天前
高性能32位MCU在热敏打印机上的应用
单片机·嵌入式硬件·mcu·32位mcu
学嵌入式的小杨同学2 天前
STM32 进阶封神之路(四十一)FreeRTOS 中断管理、软件定时器、内存管理与低功耗模式|工业级实战完整版
vscode·stm32·单片机·嵌入式硬件·mcu·智能硬件·嵌入式实时数据库
学嵌入式的小杨同学2 天前
STM32 进阶封神之路(四十)FreeRTOS 队列、信号量、互斥锁精讲|任务通信、同步、资源保护(超详细图文版)
c++·stm32·单片机·嵌入式硬件·mcu·架构·硬件架构
电子科技圈3 天前
赋能高端音频功能促进多样化设备创新——XMOS USB Audio平台实现四大功能升级
人工智能·mcu·音视频·智能家居·边缘计算·语音识别·智能硬件
笨笨饿3 天前
42_C语言查找算法
linux·服务器·c语言·人工智能·mcu·学习方法·嵌入式软件
匿名了匿名了4 天前
直流无刷与直流有刷电机
stm32·嵌入式硬件·mcu
笨笨饿6 天前
29_Z变换在工程中的实际意义
c语言·开发语言·人工智能·单片机·mcu·算法·机器人
ZenasLDR6 天前
Type-C接口LDR多协议取电芯片
接口·芯片·usb
R6bandito_7 天前
自实现FLASH读取函数中的隐式类型转换bug踩坑记录
c语言·开发语言·经验分享·stm32·单片机·mcu·bug