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

[复制链接]
3931|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抓一下,看看总线上出现了什么错误。设备因为不同的状态和错误或回复不同的应答信号,或者设备直接没有响应
 楼主| 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
 楼主| 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请求到达时,能等我把数据准备好!再去把缓存区的数据发上去。
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

粉丝
快速回复 在线客服 返回列表 返回顶部