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

【经验分享】OTG主机库在不同传输类型上对NAK的处理

[复制链接]
STMCU小助手 发布时间:2022-2-11 18:28
问题:某客户使用 STM32F4 的 OTG 库做 USB 主机控制 Wifi 网卡。使用 BULK 传输类型时,从数据读取数据时,如果设备返回需要把设备返回的 NAK 状态告知上层应用,该如何修改 OTG 库。
调研:
先来看看 OTG 库当前对 BULK 类型传输,IN 和 OUT 方向上的 NAK 的处理方式:
  1. @ BULK IN 通道
  2. If (nak)
  3. 重新使能该通道: CHENA=1, CHDIS=0
  4. 记录通道状态: Pdev->hostHC_Status[num] = HC_NAK
  5. 清零 NAK 位
  6. 退出该中断处理程序(ISR)
复制代码


一旦重新使能该通道,主机硬件又自动发送 IN 令牌来企图从设备获取数据,直到设备准备好数据后,不再回复 NAK 握手,而是回复主机要获取的数据,然后主机硬件回复 ACK 来结束本次 transfer。
BULK IN 通道对 NAK 的处理和 CTRL IN 通道对 NAK 的处理,在 ISR 中是一样的;但是在驱动库里,对 CTRL IN 有超时限制,而对 BULK IN 没有。就是说对于常用来做枚举传输的 CTRL 传输,当启动从设备获取信息,但是久久未得的情况下,会走到 Timeout 的处理分支。从代码里我们可以看到
  1. <usbh_core.c>
  2. USBH_HandleControl()
  3. {
  4. case CTRL_DATA_IN : 发出 IN 令牌
  5. case CTRL_DATA_IN_WAIT :
  6. get_urb_state
  7. if (done)
  8. if (stall)
  9. if (error)
  10. if (超时) USBH Fail
复制代码


但是 BULK IN 通道对 NAK 的接收没有超时控制,因为 BULK 传输本身的性质就是不保证带宽的,即如果主机上有很多其他优先级更高的周期类型的传输(同步 ISO 传输和中断 INT 传输),则在 BULK传输有可能无限延迟。
CTRL IN 对 NAK 有超时处理,那么 CTRL OUT 对 NAK 是如何处理的呢?
从代码里可以看到 CTRL OUT 收到 NAK 后会把该状态上传 APP,如图
  1. @ CTRL OUT 通道
  2. If (nak)
  3. 打开通道 halt 中断: CHMM @ OTG_FS_HCINTMSK
  4. Halt 该通道: CHENA=0, CHDIS=1
  5. 记录通道状态:Pdev->hostHC_Status[num] = HC_NAK
  6. 错误计数清零
  7. 清零 NAK 标志:@HCINTx
  8. 退出该中断处理程序(ISR),又进入通道 halt 中断
  9. If (halt)
  10. 关闭通道 halt 中断
  11. 记录通道状态以上传 APP:Pdev->host.URB_State[num] = URB_NOTREADY
复制代码
然后在库代码处理控制传输时,如果检测到这个状态,就会重新发送 OUT 令牌和数据包,如图
  1. <usbh_core.c>
  2. USBH_HandleControl()
  3. {
  4. case CTRL_DATA_OUT : 发出 OUT 令牌和数据包
  5. case CTRL_DATA_OUT_WAIT :
  6. get_urb_state
  7. if (done)
  8. if (stall)
  9. if (error)
  10. if (URB_NOTREADY) 回到之前的 case CTRL_DATA_OUT
复制代码

因此,当 CTRL IN 收到 NAK 后,如果想把状态上传给 App,则可以模仿 CTRL OUT 对 NAK 的处理。首先, ISR 中的处理可以模仿 CTRL OUT,在 BULK 传输的处理中,对每次发送 IN 令牌的地方(USBH_BulkReceiveData)查询传输状态,如果 URB_NOTREADY 就由 App 来决定如何处理。

处理:
基于 U 盘读写的例程,在每次 USBH_BulkReceiveData 之后检查状态,如果是 URB_NOTREADY 就重新发送 IN 令牌。于是全项目搜索 USBH_BulkReceiveData,有三个地方,且都在USBH_HandleBOTXfer()中调用,即在 BOT 传输中若干次读数据阶段(多次数据包整数长度读取和最后一次的尾巴数据读取)和 CSW 阶段的读取,如图:
  1. <usbh_core.c>
  2. USBH_MSC_HandleBOTXfer()
  3. {
  4. case USBH_MSC_BOT_DATAIN_STATE:
  5. if (URB_DONE)
  6. {
  7. if (剩余数据大于端点的 MPZ) USBH_BulkReceiveData(MPZ)
  8. if (剩余数据小于端点的 MPZ) USBH_BulkReceiveData(剩余数据量)
  9. }
  10. case USBH_MSC_RECEIVE_CSW_STATE :
  11. USBH_BulkReceiveData(13)
复制代码
需要对每次 BULK IN 传输后检测状态,如果收到 NAK 则重新发起刚才的那次 BULK IN 传输,如图:
  1. <usbh_core.c>
  2. USBH_MSC_HandleBOTXfer()
  3. {
  4. case USBH_MSC_BOT_DATAIN_STATE:
  5. if (URB_DONE)
  6. {
  7. if (剩余数据大于端点的 MPZ) USBH_BulkReceiveData(MPZ)
  8. if (剩余数据小于端点的 MPZ) USBH_BulkReceiveData(剩余数据量)
  9. }
  10. If (URB_NOTREADY)
  11. {重新发起刚才的 BULK IN 传输}
  12. case USBH_MSC_RECEIVE_CSW_STATE :
  13. USBH_BulkReceiveData(13)
  14. If (URB_NOTREADY)
  15. {重新发起刚才的 BULK IN 传输}
复制代码
经过以上修改,以 FS 和 HS 都能对 U 盘正确读取。
修改后的固件代码,请参看附件压缩包。


收藏 评论0 发布时间:2022-2-11 18:28

举报

0个回答

所属标签

相似技术帖

官网相关资源

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