找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 5006|回复: 1
打印 上一主题 下一主题
收起左侧

STM32 OTG主机库U盘应用中的NAK处理

[复制链接]
跳转到指定楼层
楼主
ID:98618 发表于 2016-1-29 02:49 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本文作者Miler Shao
 经常碰到有人在利用USB OTGU盘的应用过程中遇到一些识别或读取问题。这里分享一篇STM32芯片的OTG模块做U盘应用过程中关于NAK处理的解析过程供参考。文章源于ST官方FAE技术应用文档,本文底部有网站地址介绍,可供原文及参考代码下载

 

问题:

        某客户使用STM32F4的OTG库做USB主机控制Wifi网卡。使用BULK传输时,从设备读取数时,如果设备需要返回把设备返回的NAK状态告知上层应用,该如何修改OTG库。

 

调研:

先来看看OTG库当前对BULK类型传输,IN和OUT方向上的NAK的处理方式:

 

@BULK IN 通道

 

If(nak)

重新使能该通道: CHENA=1, CHDIS=0

记录通道状态: Pdev->hostHC_Status[num]= HC_NAK

清零NAK

退出该中断处理程序(ISR)

 

 

        一旦重新使能该通道,主机硬件又自动发送IN令牌企图从设备获取数据,直到设备准备好数据不再回复NAK,而回复主机要获取的数据,然后主机硬件回复ACK结束本次transfer

 

        BULK IN通道对NAK的处理和CTRL IN通道对NAK的处理,在ISR中是一样的;但是在驱动库里,对CTRL IN有超时限制,而对BULK IN没有。就是说对于常用来做枚举传输的CTRL传输,当启动从设备获取信息,但是久久未得的情况下,会走到Timeout的处理分支。从代码里我们可以看到:

 

<usbh_core.c>

USBH_HandleControl()

{

case CTRL_DATA_IN : 发出IN令牌

caseCTRL_DATA_IN_WAIT :get_urb_state

if(done)

if(stall)

if(error)

if (超时) USBH Fail 。。。。。。

 

 

但是BULK IN通道对NAK的接收没有超时控制,因为BULK传输本身的性质就是不保证带宽的,即如果主机上有很多其他优先级更高的周期类型的传输(同步ISO传输和中断INT输),则在BULK传输有可能无限延迟。

 

CTRL INNAK有超时处理,那么CTRL OUTNAK是如何处理的呢?

从代码里可以看到CTRL OUT收到NAK后会把该状态上传APP

 

@CTRL OUT 通道

If(nak)

打开通道halt中断: CHMM @ OTG_FS_HCINTMSK

Halt该通道: CHENA=0,CHDIS=1

记录通道状态:Pdev->hostHC_Status[num] = HC_NAK

错误计数清零

清零NAK标志:@HCINTx

退出该中断处理程序(ISR),又进入通道halt中断

If(halt)

关闭通道halt中断

记录通道状态以上传APPPdev->host.URB_State[num]= URB_NOTREADY

 

然后在库代码处理控制传输时,如果检测到这个状态,就会重新发送OUT令牌和数据包。

<usbh_core.c>

USBH_HandleControl()

{

case CTRL_DATA_OUT : 发出OUT令牌和数据包

caseCTRL_DATA_OUT_WAIT :

get_urb_state

if(done)

if(stall)

if(error)

if (URB_NOTREADY)回到之前的case CTRL_DATA_OUT

 

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

 

处理:

基于U盘读写的例程,在每次USBH_BulkReceiveData之后检查状态,如果是URB_NOTREADY就重新发送IN令牌。全项目USBH_BulkReceiveData有三个地方,且都在USBH_HandleBOTXfer()中调用,即在BOT传输中若干次读数据阶段(多次数据包整数长度读取和最后一次的尾巴数据读取)和CSW阶段的读取。

 

<usbh_core.c>

USBH_MSC_HandleBOTXfer()

{

caseUSBH_MSC_BOT_DATAIN_STATE:

if (URB_DONE)

{

if (剩余数据大于端点的MPZ)USBH_BulkReceiveData(MPZ)

if(剩余数据小于端点的MPZ) USBH_BulkReceiveData(剩余数据量)

}

caseUSBH_MSC_RECEIVE_CSW_STATE :

USBH_BulkReceiveData(13)

 

需要对每次BULK IN传输后检测状态,如果收到NAK则重新发起刚才的那次BULK IN传输:

<usbh_core.c>

USBH_MSC_HandleBOTXfer()

{

caseUSBH_MSC_BOT_DATAIN_STATE:

if (URB_DONE)

{

if (剩余数据大于端点的MPZ)USBH_BulkReceiveData(MPZ)

if(剩余数据小于端点的MPZ) USBH_BulkReceiveData(剩余数据量)

}

If(URB_NOTREADY)

{重新发起刚才的BULKIN传输}

caseUSBH_MSC_RECEIVE_CSW_STATE :

USBH_BulkReceiveData(13)

If(URB_NOTREADY)

{重新发起刚才的BULK IN传输}

 

经过以上修改,以FSHS都能对U盘正确读取。

 

修改后的参考固件代码,请去STMCU官网实战经验处下载。

   

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:279058 发表于 2019-11-19 15:15 | 只看该作者
这什么也没说呀?怎么用文件系统
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表