你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【经验分享】OTG 做 U 盘主机的兼容性提高

[复制链接]
STMCU小助手 发布时间:2022-2-19 17:54
问题:
某客户使用 STM32F2 的 OTG 库中的 U 盘主机例程在连接 U 盘时,有些 U 盘不能识别,甚至出现操作死机的情况。现就针对版本 V2.1.0 的 USB 主机库中的 MSC Host 例程做一些修改,以能够兼容更多 U 盘。
X8O(E)K2_FOKZ%Y22ZDB5EX.png

调研:
1.有些 U 盘在收到 BOT_RESET 这个 MSC 类相关命令时,就不再有反应了:设备一直对后续主机发来的 IN 令牌回复 NAK。通过对 BOT_RESET 命令的调查得知,USB 规范为大容量设备定义了两种类型的复位:USB 端口复位和大容量设备 BOT 复位。USB 规范并未规定这两种复位对应到 SCSI命令中是做什么操作,因此也没有规定在收到这些命令后 SCSI 的操作。通常设备把 USB 端口复位映射成 SCSI 的硬复位;有些设备把 BOT 复位映射到 hard reset,有的仅是映射成逻辑单元复位。该条命令通常用于主机对在 BOT 通信中出错的设备进行复位恢复。但是需要指出的是,有些 U 盘并没有完全遵守大容量规范,比如就不实现对 BOT_RESET 命令的支持。在这种情况下,
设备一般会回复 STALL,那么主机需要发送 Set Port Feature(PORT_RESET)来复位设备所连的 Hub 端口。但是这个 U 盘并没有回复 STALL,且 U 盘是直接连在 STM32 USB 主机上的,直接并没有 Hub。于是,参照该 U 盘在 Window 下的连接操作的过程文件(tracer file),发现在枚举完成后,Windows 并没有发送 BOT_RESET 命令,而是直接就发送 GET_Max_Lun 命令来获取 U盘的逻辑盘符个数。于是在 STM32 的 USB Host 例程中注释掉 BOT_RESET 命令,果然就可以正确操作了。修改代码如下:
  1. <usbh_msc_core.c>
  2. USBH_MSC_Handle()
  3. {
  4. switch(USBH_MSC_BOTXferParam.MSCState)
  5. {
  6. case USBH_MSC_BOT_INIT_STATE:
  7. USBH_MSC_Init(pdev);
  8. //USBH_MSC_BOTXferParam.MSCState = USBH_MSC_BOT_RESET;
  9. USBH_MSC_BOTXferParam.MSCState = USBH_MSC_GET_MAX_LUN;
  10. break;
  11. case …
复制代码


2.还有些 U 盘在收到 Get_Max_Lun 命令返回 STALL,但是 U 盘主机就走不下去了。抓到的 tracer文件如图:

4G}{[[I}[CUV8FQLK5$C`0E.png

经查阅,有些只包含唯一一个逻辑盘符的 U 盘可以对该命令回复数值 0 或者直接回复 STALL。那么对于 USB 主机来说,在收到了该条命令的 STALL 回复后就应该第一:认为该 U 盘仅包含一个逻辑盘符;第二:对 STALL 应答进行处理,然后继续下面的命令流程。通过 USB2.0 协议规范(章节 9.2.7),我们得知在控制传输(Control Transfer)过程中,当设备收到的命令自己不支持或者不适合设备当前的设置,就认为是命令出错。那么设备通过在接下来的数据阶段或者状态阶段回复 STALL 应答来告知主机这个错误。这种“协议 STALL”是控制传输特有的;这样 STALL 的状态,会在下一个控制传输(Setup 令牌)的到来而解除。我们看看 Window 对 U 盘这样的回复是怎么处理,tracer 文件抓图如下:主机通过 Clear Feature 命令,参数 EP_Halt(这是一个控制传输)来把设备方端点的 Halt feature 清除掉。

$J$PS0OF?R7K`835)B0WP.png

从代码里可以看到,例程是有做这方面的处理的:如果主机发送的 Get_Max_Lun 命令不被设备支持,则将 MSCState 状态设定成 CTRL_ERROR_STATE,发送 Clear Feature 的命令,以及随后的 Test_Unit_Ready 命令。
  1. <usbh_msc_core.c>
  2. USBH_MSC_Handle()
  3. {
  4. switch(USBH_MSC_BOTXferParam.MSCState)
  5. {
  6. case USBH_MSC_GET_MAX_LUN:
  7. status = USBH_MSC_GETMaxLUN(pdev, phost);
  8. if(status == USBH_OK )
  9. { ……,
  10. USBH_MSC_BOTXferParam.MSCState = USBH_MSC_TEST_UNIT_READY;
  11. }
  12. if(status == USBH_NOT_SUPPORTED )
  13. { ……,
  14. USBH_MSC_BOTXferParam.MSCStateBkp = USBH_MSC_TEST_UNIT_READY;
  15. USBH_MSC_BOTXferParam.MSCState = USBH_MSC_CTRL_ERROR_STATE;}
  16. break ;
  17. case USBH_MSC_CTRL_ERROR_STATE:
  18. USBH_ClrFeature(pdev, phost, 0x00, pphost->Control.hc_num_out);
  19. ……
  20. USBH_MSC_BOTXferParam.MSCState = USBH_MSC_BOTXferParam.MSCStateBkp;
  21. ……
复制代码

但是从抓到的 tracer 文件却看不到主机走到了发送 Test_Unit_Ready 的命令。经过调试、代码跟踪,终于定位在 USBH_HandleControl()中。对 CTRL_DATA_IN_WAIT 的处理,当收到URB_STALL 的应答后,没有给 phost 的 Control.state 赋值成 CTRL_STALLED!

I7BKJAFSACS6T1PH]@HA@[K.png

补上以上状态语句赋值后,主机 Host 在收到 Get_Max_Lun 命令返回的 STALL 后,可正常运行。
3.还有一点需要注意的是:本版的 U 盘主机例程,暂时不支持多盘符 U 盘。

收藏 评论0 发布时间:2022-2-19 17:54

举报

0个回答

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版