打印
[数据传输]

当GET_REPORT请求时,数据未准备好,以NAK回应拖时间!最长多久PC端会认为超时!

[复制链接]
3940|18
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
sxslyy|  楼主 | 2015-6-11 20:39 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
根据香主的贴子用了!在数据未准备好时!
else if((Type_Recipient == (CLASS_REQUEST | INTERFACE_RECIPIENT))
        && RequestNo == GET_REPORT)
{
        if (数据未准备好)
            return USB_NOT_READY;
         CopyRoutine = CustomHID_GetReport;
  }
STM32将以NAK回应PC端的IN请求.
请教!
1。PC端收回NAK,应该用不断重试请求数据吧!多久重试一次!
2。STM32如长时间未准备好数据,一直回应NAK,一般多久PC会认应超时。

香主的:
pInformation->Ctrl_Info.CopyData = CustomHID_GetReport;
    pInformation->Ctrl_Info.Usb_wOffset = 0;
    CustomHID_GetReport(0);
    pInformation->Ctrl_Info.PacketSize = pProperty->MaxPacketSize;
    DataStageIn();
添加那几行代码,可以在Get Report命令到来时,如果数据未准备好,给你多一些时间准备数据(根据PC端驱动的情况,估计可以有20~100ms的时间),而不必让PC端做超时处理。

实测好象不起什么做用!在几MS或十几ms数据未准备好!PC端就认为超时了!

特别上位机使用:HidD_GetInputReport() 一超时这个函数就等时5秒。

相关帖子

沙发
insignal| | 2015-6-12 08:01 | 只看该作者
CustomHID设备,在windows上,最多等待5s

使用特权

评论回复
板凳
sxslyy|  楼主 | 2015-6-12 08:34 | 只看该作者
HidD_GetInputReport()函数等时5秒,但GET_REPORT,以NAK回应,实测可不是5秒。如果数据未准备好!不断回NAK,很快就超时状态了!然后HidD_GetInputReport就傻等5秒。我想知道,回NAK,是不是有时间或次数的限制!另:PC端认为NAK超时后,好象同时认为设备不可用了!再发SET_REPORT,设备也不响应了!

使用特权

评论回复
地板
insignal| | 2015-6-12 17:35 | 只看该作者
“但GET_REPORT,以NAK回应,实测可不是5秒。如果数据未准备好!不断回NAK,很快就超时状态了!”  这句话怎么理解?难道你认为那5s是没有nak的?

使用特权

评论回复
5
insignal| | 2015-6-12 17:36 | 只看该作者
pc认为设备已经异常,当然就断开了,除非你自己写驱动,即便超时也还能继续操作

使用特权

评论回复
6
insignal| | 2015-6-12 17:41 | 只看该作者
你所说的超时状态是指fw还是pc程序?

使用特权

评论回复
7
315013856| | 2015-6-13 09:47 | 只看该作者
上位机程序时你自己写吗?

使用特权

评论回复
8
insignal| | 2015-6-13 15:19 | 只看该作者
其实你是要解决pc程序超时的问题
这个很简单 做个应用层的协议增加延时等待就可以
不用太关心5s
你可以看看我们的产品 都是hid通讯
5s超时的问题 就是通过应用层解决

使用特权

评论回复
9
sxslyy|  楼主 | 2015-6-16 13:06 | 只看该作者
insignal 发表于 2015-6-12 17:35
“但GET_REPORT,以NAK回应,实测可不是5秒。如果数据未准备好!不断回NAK,很快就超时状态了!”  这句话 ...

实测:最少是在windows xp下,使用“HidD_GetInputReport”这个函数发出GET_REPORT请求
使用
  if (数据未准备好)
            return USB_NOT_READY;
返回一次NAK

PC驱动,对收到NAK的回复不重请求,也不累计!直接就使“HidD_GetInputReport”函超时,HidD_GetInputReport会等上5S,然后返回错误超时状态。


stm32这边仿真跟踪就是:在使用“HidD_GetInputReport”这个函数发出GET_REPORT请求

else if((Type_Recipient == (CLASS_REQUEST | INTERFACE_RECIPIENT))
        && RequestNo == GET_REPORT)
{
        if (数据未准备好)
            return USB_NOT_READY;
         CopyRoutine = CustomHID_GetReport;
  }
这个条件分支去进入一次(注意只有一次),然后因为数据未准备好标识,返回了USB_NOT_READY;然后再也不进入这个条件分支了!直到5S后HidD_GetInputRepor 超时。

我原来是这样认为的。发出GET_REPORT请求后,进行这个条件分支后,因为数据没准备好!返回NAK,然后过一段时间驱动会自动再次GET_REPORT。然后再NAK。。。。。。。。。循环N次这个过程后,数据还没准备好!就超时。

实测:这个过程却只有一次!只要第一次返回的是NAK,PC驱动就认为超时了!所以一点延时响应的效果都没有!。也就是说实际情况是发送了GET_REPORT 下位机必须是准备好数据的,然后要返回return USB_SUCCESS; 才能是不超时。

Device   Phase  Data                                    Description
  24.0   CTL     a1 01 03 01  00 00 14 00       GET REPORT     12US
  24.0   USTS   c0010000                             cancele             5S

使用特权

评论回复
10
sxslyy|  楼主 | 2015-6-16 13:09 | 只看该作者
insignal 发表于 2015-6-12 17:36
pc认为设备已经异常,当然就断开了,除非你自己写驱动,即便超时也还能继续操作 ...

实测:就是这样!好象PC认为设备异常了!当超时返回后。再次用HidD_SetOutputReport,发送SET_REPORT报告写数据。stm32下位机也不响应了!也是超时!主要是不明白为什么只回了一次NAK,驱动就认为设备挂了!

使用特权

评论回复
11
sxslyy|  楼主 | 2015-6-16 13:10 | 只看该作者
insignal 发表于 2015-6-12 17:41
你所说的超时状态是指fw还是pc程序?

是PC的“HidD_GetInputReport”这个函数,超时了!

使用特权

评论回复
12
sxslyy|  楼主 | 2015-6-16 13:29 | 只看该作者
本帖最后由 sxslyy 于 2015-6-16 13:32 编辑
insignal 发表于 2015-6-13 15:19
其实你是要解决pc程序超时的问题
这个很简单 做个应用层的协议增加延时等待就可以
不用太关心5s

上位机是我自己写的!

1)。使用writefile写控制指令,使用readfile导步方式,用wait等超时,是可以指定一定的超时时间的(在这段时间内下位机准备好要上传的数据)!但readfile只能用于读取中断方式的输入报告。这种操作流程已测试通过可以

2)我现在改用控制方式,使用端点0,上位机使用“HidD_GetInputReport”发送“GET_REPORT请求”来读输入报告。HidD_GetInputReport这个函是同步方式的,固定等时5S超时、因为存在请求读时数据未准备好的情况,根据香主延时响应GET_REPORT的方法,下位机使用 return USB_NOT_READY;发送NAK来拖时间。原以为数据没准备好!返回NAK,然后过一段时间驱动会自动再次GET_REPORT。然后再NAK。。。。。。。。。循环N次这个过程后,数据还没准备好的话!HidD_GetInputReport这个函数才超时。但实测只要返回一次NAK,PC驱动不会自动再次GET_REPORT,而是就认为错误了!然后HidD_GetInputReport函数会死等5S返回一个超时错误!

3.现在我在下位机使用了!只要“HidD_GetInputReport”发送“GET_REPORT请求”我下位机就返回数据,未准备好!就返回全0的数据,然后上位机软件抛弃它,返回有用的数据时再处理·!这样是可以的。

4.我主要是想知道为什么不是数据没准备好!返回NAK,然后过一段时间驱动自动再次GET_REPORT。然后再NAK。。。。。。。。。循环N次这个过程后,数据还没准备好的话!HidD_GetInputReport这个函数才超时。如果这样的话。才有机会收到GET_REPORT后。使用某种方式拖一段时间!直到数据准备好!而不是现在这种要发空数据回应!是不是下位机(STM32)我使用延迟HID的GET_REPORT请求的方法没用好!因为我是使用香水城版主博文中的方法。是不是我理解的不对!求指点!

使用特权

评论回复
13
insignal| | 2015-6-16 13:53 | 只看该作者
sxslyy 发表于 2015-6-16 13:09
实测:就是这样!好象PC认为设备异常了!当超时返回后。再次用HidD_SetOutputReport,发送SET_REPORT报告 ...

stm32肯定不止回了一个nak,你认为只是回了一个nak是因为你只return一次?
你可以用usb分析看看总线上的数据

使用特权

评论回复
14
insignal| | 2015-6-16 13:54 | 只看该作者
sxslyy 发表于 2015-6-16 13:06
实测:最少是在windows xp下,使用“HidD_GetInputReport”这个函数发出GET_REPORT请求
使用
  if (数据 ...

“if (数据未准备好)
            return USB_NOT_READY;
返回一次NAK ”

这里理解成“返回一次NAK“ , 是对usb协议理解错误。

使用特权

评论回复
15
insignal| | 2015-6-16 13:56 | 只看该作者
sxslyy 发表于 2015-6-16 13:06
实测:最少是在windows xp下,使用“HidD_GetInputReport”这个函数发出GET_REPORT请求
使用
  if (数据 ...

” if (数据未准备好)
            return USB_NOT_READY;
返回一次NAK “

你把上面的代码改成
” if (数据未准备好)
            while(1);   //死循环  “
难道就不返回nak了?

实际上 stm32是一直在返回nak

使用特权

评论回复
16
insignal| | 2015-6-16 13:58 | 只看该作者
你没必要去纠结这个nak,总之,你的程序必须在5s内将数据返回去,否则pc就会认为usb设备异常
至于如何保证你的通讯顺畅,完全可以在应用层解决,很简单
换个思路

使用特权

评论回复
17
sxslyy|  楼主 | 2015-6-17 10:28 | 只看该作者
本帖最后由 sxslyy 于 2015-6-17 10:41 编辑
insignal 发表于 2015-6-16 13:58
你没必要去纠结这个nak,总之,你的程序必须在5s内将数据返回去,否则pc就会认为usb设备异常
至于如何保证 ...

兄弟分析的很透!很可能是我理解的问题!我一直认为return USB_NOT_READY; 就是返回一次NAK ”。现在的情况是当使用“HidD_GetInputReport”这个函数发出GET_REPORT请求时。stm32库使用下面的代码来处理这个请求:

RESULT CustomHID_Data_Setup(u8 RequestNo)
{
  u8 *(*CopyRoutine)(u16);

  CopyRoutine = NULL;
.
.//其它代码
.
if ((Type_Recipient == (CLASS_REQUEST | INTERFACE_RECIPIENT))
        && RequestNo == GET_REPORT)
  {
        if (!isReady)//数据未准备好
        {
            return USB_NOT_READY;
        }

    CopyRoutine = CustomHID_GetReport;
  }

  if (pInformation->USBbmRequestType == CLASS_REQUEST|INTERFACE_RECIPIENT
            && RequestNo == SET_REPORT)
  /**** SET_REPORT ****/
  {
    CopyRoutine = CustomHID_SetReport;
  }

  if (CopyRoutine == NULL)
  {
    return USB_UNSUPPORT;
  }

  pInformation->Ctrl_Info.CopyData = CopyRoutine;
  pInformation->Ctrl_Info.Usb_wOffset = 0;
  (*CopyRoutine)(0);
                                 
  return USB_SUCCESS;
}

这段代码,一定要返回一个USB状态。或着USB_NOT_READY 或着 USB_SUCCESS 但不论返回什么。这段代码都没有一个等待我把数据准备好的过程,其实我的数据是在GET_REPORT请求到达后,需20MS-50MS左右后就可以准备好!现在的情况是如果返回USB_NOT_READY,上位机就认为超时(注意是立即,这个立即指的是,上位机从不等我准备好数据后再读一次,我理解的是发了NAK,上位机隔一段时间会自动重新请求,而这时我的数据准备好了!上位机就把准备好的数据读上去。当然这个过程可能是有一定交互次数或时间限制的,就现在的情况我的感觉是这个过程极短,根本不给我准备好数据的机会)。如果返回 USB_SUCCESS stm32也是立即返回的就是当前缓存区的数据,而缓存区的数据还没准备好!所以返回的全是0000000.

if (数据未准备好)
            return USB_NOT_READY;
这段代码我用的是香水城 版主的**中的方法!以为可以让GET_REPORT请求到达后,stm32可以等我把数据准备好!再去把缓存区的数据发上去。结果没法实现!

应用层的方法,我现在用的是不断读,stm32这边不断上传,未准备好!就返回全0的数据,然后上位机软件抛弃它,返回有用的数据时再处理·!这样可以保证通讯顺畅,实现功能的。

但我觉着不断上传的没用的数据是占USB带宽的,效率差,所以求教兄弟!用什么方法可以使用STM32在GET_REPORT请求到达时,能等我把数据准备好!再去把缓存区的数据发上去。

使用特权

评论回复
18
insignal| | 2015-6-17 21:44 | 只看该作者
才几十ms
那干嘛不在那等待数据准备齐了
把数据就直接返回去

使用特权

评论回复
19
iamdair| | 2020-3-12 17:40 | 只看该作者
sxslyy 发表于 2015-6-17 10:28
兄弟分析的很透!很可能是我理解的问题!我一直认为return USB_NOT_READY; 就是返回一次NAK ”。现在的情 ...

通过 香主 的方法解决了你的问题了吗?

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

11

主题

31

帖子

0

粉丝