打印
[STM32F1]

数据未准备好,以NAK 延迟HID的GET_REPORT请求!最长延迟多久PC端会认为超时!

[复制链接]
3138|6
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
sxslyy|  楼主 | 2015-6-11 20:53 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
根据香主的贴子用了!在数据未准备好时!
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会认应超时。

3。香主的: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端就认为超时了!

4。为什么一但GET_REPORT请求超时后,再发SET REPORT请求,STM32也不响应了!也是超时。

stm代码用的是:
“以HID的SET REPORT为例说明如何使用STM32的USB库支持控制端点0”
“如何使用STM32的USB库支持延迟HID的GET_REPORT请求”

这两个**中的代码。


上位机使用:
HidD_SetInputReport发出SET REPORT.
HidD_GetInputReport() 发出GET_REPORT.

流程是:循环-》先HidD_SetInputRepor写 再HidD_GetInputReport()读。一但GET_REPORT超时了!再发的SET REPORT也超时了!好象GET_REPORT超时后,设备就挂了!重新拔插才行。一超时函数就等时5秒。
沙发
香水城| | 2015-6-15 15:51 | 只看该作者
本帖最后由 香水城 于 2015-6-15 15:52 编辑

1。PC端收到NAK,应该会不断重试请求数据吧!多久重试一次!

>> 在USB设备的断点描述符里,有一个域叫做bInterval,它在USB规范里的定义如下:

bInterval 1 Number Interval for polling endpoint for data transfers.
Expressed in frames or microframes depending on the
device operating speed (i.e., either 1 millisecond or
125 µs units).

假设bInterval=8,则主机一般来说会每8个ms(假设全速通信)发一个IN令牌来请求设备的数据。如果设备因为没有准备好数据而回复主机NAK,主机也是在下一个8ms再发起下一次transfer(IN传输令牌)。

2。STM32 长时间未准备好数据,一直回应NAK,一般拖多久PC会认应超时。

>> 收到多少次NAK,主机会认为“超时”,取决于主机的驱动程序

使用特权

评论回复
板凳
香水城| | 2015-6-15 16:42 | 只看该作者
香水城 发表于 2015-6-15 15:51
1。PC端收到NAK,应该会不断重试请求数据吧!多久重试一次!

>> 在USB设备的断点描述符里,有一个域叫做bI ...

以上描述是基于主机通过INTERRUPT传输来polling设备数据的情况。

刚才看到LZ似乎是在用GET_REPORT这样的CONTROl传输来获得设备的数据,那么“控制传输”在主机端对收到NAK的回复是会累计,累计到一定个数,会下主机的上层应用程序报告“超时”。这个超时的定义,由主机USB驱动决定。



使用特权

评论回复
地板
香水城| | 2015-6-15 16:58 | 只看该作者
4. 为什么一但GET_REPORT请求超时后,再发SET REPORT请求,STM32也不响应了!也是超时。

>> 最好能够有一个PC和设备之间通信的tracer文件,比如那Bushound抓一下,看看总线上出现了什么错误。设备因为不同的状态和错误或回复不同的应答信号,或者设备直接没有响应

使用特权

评论回复
5
sxslyy|  楼主 | 2015-6-16 13:04 | 只看该作者
实测:最少是在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

使用特权

评论回复
6
sxslyy|  楼主 | 2015-6-17 10:43 | 只看该作者
现在的情况是当使用“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请求到达时,能等我把数据准备好!再去把缓存区的数据发上去。

使用特权

评论回复
7
emocc| | 2018-3-26 17:16 | 只看该作者
你好,我现在想用windows的库发送一个特征报文,请问下怎么发送?    如何实现一次就发送下面2个报文,实现SETREPORT功能?

  32.0  CTL    21 09 02 03  00 00 08 00                            SET REPORT             105.1.0        
  32.0  OUT    02 aa 00 80  00 00 00 00                            ........               105.2.0   

使用特权

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

本版积分规则

11

主题

31

帖子

0

粉丝