This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] TM4C123GE6PM:端点0的 USB HID 处理程序存在问题

Guru**** 2468460 points


请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/656961/tm4c123ge6pm-issue-with-usb-hid-handler-for-endpoint-0

器件型号:TM4C123GE6PM

您好!

我最近升级到了 Tiva C 驱动程序库2.1.4.178、它似乎破坏了我的产品基于1.0.x USB 驱动程序库的 USB 接口。  我正在尝试调试此问题、找不到源文件 usbdevice.c  我来自

USBDHIDInit (0、&g_sHIDDataPipeDevice); 

它位于我的 main.c 文件(我的项目的主 c 代码文件)中、如下所示

//
//现在一切都很好,将描述符传递到底层并放置
//总线上的 HID 设备。
//
USBDCDInit (ui32Index、&psHIDDevice->sPrivateData.sDevInfo、
(void *) psHIDDevice); 

然后我尝试查看 USBDCDInit()函数、并停留在 usbdevice.h 头文件中、无法在驱动程序库的任何位置找到源文件。  有人知道这里发生了什么吗?

注意:我在尝试编辑时意外地将此标记为垃圾邮件。  请忽略、因为这不是垃圾邮件。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    USBDInit()的源文件为:C:\ti\TivaWare_C_Series-2.1.4.178\usblib\device\usbdenum.c
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    Robbie 你好!

    不确定具体的问题是什么、但如果它与 Windows 机器(尤其是 Windows 10)中的 USB 设备识别相关、则需要确保使用我们在主要 TivaWare 安装之外提供的补丁驱动程序。 可从 以下网址下载这些文件:software-dl.ti.com/.../SW-TM4C-2.1.4.178.PATCH-1.0.zip

    此外、您无法跟踪.h 文件之外的内容的原因是.lib 文件是如何用于驱动程序库的、因此 CCS 没有超过.h 文件的路由。 您必须在 C:\ti\TivaWare_C_Series-2.1.4.178\usblib 文件夹中导航、以查找用于读取源代码的各种文件、但您无法将断点等放入其中、除非您取消链接.lib 文件、然后将库的整个文件夹包含到您的项目中。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    大家好、

    感谢您的快速回答! 至于 usbdevice.c 文件的位置是 yes。 我将在今晚或本周末测试这些司机、然后返回给您。 我没有意识到我需要这个驱动程序补丁。

    这是否意味着我的所有客户也需要安装此修补程序? 我最初选择 HID 器件路由、因为它减少了对软件驱动程序 fidling 的任何需求。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    Robbie 您好!

    这可能取决于描述符的设置方式。 我们用于 TivaWare 的 TI 示例的默认方法在某些应用程序的 Windows 10中无法正常工作、因此补丁驱动程序修复了这种方法(在大多数情况下、复合示例具有单独的应用程序相关问题)。

    如果您的描述符是以 Windows 10正确接受的方式创建的、那么您不应该有任何问题。

    作为 HID 设备、我认为您受到 Windows 10更改的影响的风险很低、但如果 Windows 由于描述符等原因而实际识别该设备时出现问题、我会再次这样做 然后,我建议尝试更新的修补程序驱动程序,并确定它是否可以解决问题。

    即使确实如此、您也可以修改 HID 设备应用程序以正确输出 Windows 10所需的描述符、从而避免推送驱动程序更新。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Ralph、

    感谢您的回答。  我实际上在 Windows 10上枚举 OK。  我可以成功地将第一个 HIS 报告正确地发送到 MCU、并且可以通过在调试器中查看数据来看到数据已正确接收。   当我第二次或第三次重新发送此消息时、我看到 USB Rx 中断处理程序触发器、但我没有收到任何响应、最终链路断开。  如果我插入的产品未升级到2.0 TIvaware 库、但使用1.x 在不同的计算机上进行了编程(我不记得确切的数字) 、则此链接工作正常、 所有数据均已正确传输、无论我向设备发送了多少垃圾邮件、我的 USB 链接都不会锁定。

    因此、我将尝试跟踪驱动程序库 API、并弄清发生了哪些变化。  这似乎不是 Windows 问题、而是驱动程序库问题、因为我的旧产品构建在旧的驱动程序库上、效果很好。  

    我还注意到升级时、我的一些外设驱动程序调用发生了变化、我不得不修复它们、因此这让我相信、在该驱动程序库版本/升级中、USB 驱动程序代码中存在相同的问题(尽管更细微)。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    Robbie 您好!

    如果是这种情况、我同意问题超出 Windows 10驱动程序的限制。 我从未使用过 USB 库的早期版本、因此我无法评论所做的所有更改、但如果您尚未阅读我们的发行说明文档、我建议您阅读这些文档。

    它可以在 TivaWare 安装的 docs 文件夹中找到、标题为 SW-TM4C-RLN-2.1.4.178.pdf

    搜索"USB 库"将显示大部分(如果不是全部) USB 库更改。 这也许会帮助您跟踪解决问题所需的内容、因为我同意它似乎与 USB 库的修改相关。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    传递到 RX 和 TX USB hid 处理程序的代码是什么? 如何找到处理 USB 接收消息的代码。 我看到 RXHandler 每次都命中 USBD_HID_EVENT_GET_REPORT_BUFFER case、然后是 USBD_HID_EVENT_SET_REPORT case。 遗憾的是、在收到几条消息后、我的 RXHandler 仅命中 USBD_HID_EVENT_GET_REPORT_buffer、然后挂起。

    对于 HID 器件类、TI 的文档显示它应该使用 USBD_HID_EVENT_GET_REPORT_buffer 请求缓冲区、将数据存储在我返回的缓冲区中、然后调用 USBD_HID_EVENT_SET_REPORT 案例、该案例将告知我的主程序缓冲区中有数据可用。 我需要弄清楚为什么 USBD_HID_EVENT_SET_REPORT 案例被丢弃。

    我对源代码在何处处理所有这些内容感到困惑。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    Robbie 你好!

    我认为以下 usbdhid.c 文件中的注释块将有助于您了解 TX 和 RX 的架构以及您看到的状态的来源:

    //
    //
    //! 初始化给定 USB 控制器的 HID 设备操作。
    //!
    //! \param ui32Index 是 USB 控制器的索引
    、它是//! 针对 HID 器件操作进行了初始化。
    //! \param psHIDDevice 指向包含参数自定义
    //!的结构 HID 器件的操作。
    //!
    //! 希望为主机系统提供 USB HID 接口
    的应用//! 必须调用此函数来初始化 USB 控制器并连接
    //! USB 总线。 此函数执行所有必需的 USB
    //! 初始化。
    //!
    //! 成功完成后、此函数将返回\e psHIDDevice
    //! 指针传递给它。
    必须在//!的所有将来呼叫中传递此信息。 HID 器件类驱动程序。
    //!
    //! USB HID 器件类 API 为应用提供基于报告的传输
    //! 用于输入报告的接口。 输出报告可通过
    //! 控制端点或通过专用的中断输出端点。 如果使用
    //! 专用端点、报告数据按//
    ! 数据包。 如果应用程序使用的报告时间长于\b USBDHD_MAX_PACKE/
    ! 并且更愿意接收完整的报告、它可能会使用高于
    //的 USB 缓冲器! 允许读取完整报告的接收通道。
    //!
    //! 发送操作:
    //!
    //! 调用 USBDHIDReportWrite()将完整报告传递给驱动程序
    //! 传输。 这些数据将使用尽可能多的 USB
    //! 数据包完成传输所需的所有数据包。
    //!
    //! 一旦 USB 主机确认了完整输入报告、a
    //! b USB_EVENT_TX_COMPLETE 事件被发送到应用程序发送回调
    //! 通知委员会可转交另一份报告。
    //!
    //! 接收操作(使用专用中断输出端点时):
    //!
    //! 传入的 USB 数据包将导致对应用
    程序的调用//! 使用事件\b USB_EVENT_RX_Available 进行回调。 然后、应用程序必须
    //! 调用 USBDHIDPacketRad(),传递一个能够保持接收的//
    ! 数据包。 数据包的大小可通过调用函数
    //! USBDHIDRxPacketAvailable()之后再读取数据包。
    //!
    //! 接收操作(当不使用专用输出端点时):
    //!
    //! 如果未使用专用的输出端点、则发送输出和功能报告
    //! 控制端点、端点0从主机发出。 当这样的 a
    //! 接收到报告、\n USBD_HID_EVENT_GET_REPORT_BUFFER 被发送到
    //! 必须使用足够大的缓冲器进行响应以保持
    //! 报告。 然后、器件类驱动程序将收到的报告复制到
    //! 在发送\b USBD_HID_EVENT_SET_REPORT 以指示
    //!之前提供的缓冲区 报告现已提供。
    //!
    //! 注意应用程序不得对低级 USB 设备进行任何调用
    //! 通过 USB HID 器件类 API 与 USB 进行交互的接口。 正在进行
    //! 因此会导致不可预测(虽然几乎肯定不会让人感到不愉快)的行为。
    //!
    //! 返回失败时返回 NULL、成功时返回\e psHIDDevice 指针。
    ////
    ***************** 

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    很抱歉、事故导致太早就打过帖子、我打算添加更多详细信息:

    根据您用作的器件、您可能需要针对所述的所有情况制作自己的 RXHandler。 文档备注指导您了解需要什么、但并非所有这些都由 USB 堆栈处理。

    例如、我们有一个用于键盘应用程序的 RXHandler、它位于 API HIDKeyboardRxHandler 内。 这可能是供您参考的重要资源。 鼠标和游戏鼠标示例也有处理程序、但键盘一的肉最多。

    最后、usbdhid.c 中的 HandleRequest API 也使用 USBD_HID_EVENT_GET_REPORT_buffer 状态、尽管该 API 适用于非标准请求、因此可能不适用于您的用例。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Ralph、

    感谢您的回答。  我已经详细介绍了您的实际建议。  我的情况很奇怪、我的固件在 usbdriverlib 1.0中运行良好、但在升级到驱动程序库2.1时、它已损坏。  我已查看了版本说明、但没有发现任何可疑内容。

    我将通过控制端点0 (hid 设备)从软件应用程序向 Tiva 部件发送一条消息。  Tiva/固件应在端点1上响应该消息。

    我昨晚录制了流量,发现 当我现在发送消息时,驱动程序库会自动响应端点0上软件发出的消息。  固件随后也会以端点1上的有效数据进行响应。  当链路断开时、它看起来是因为端点0 (我不打算发送)上的响应耗时太长。  

    我想我的第一个问题是:我是否应该在这个问题上发表新的帖子?

    第二, 当我实际上没有在端点0上使用发送包或 usbwrite()函数时,为什么驱动程序库会响应 RXhandler()中的设置报告事件。  如果主机端点0上有一个设置报告缓冲区/set 报告、设备是否必须对端点0上的报告做出响应?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    Robbie 你好!

    嗯、有趣的是、你专门提出了端点0。 当我浏览代码时、我注意到了与此相关的一些内容、但我认为您专门处理端点0并不是一个公平的假设。

    查看 usbdhid.c 中的 HandleEP0DataReceived API、当涉及端点0上接收到的数据时、USB 堆栈会调用该 API。 在 API 末尾、它具有以下代码块:

    //
    //我们唯一通过端点0请求的是发送到的报告
    //我们通过 SET_Report 请求。 将新收到的报告传递给
    //客户端。
    //
    psHIDDevice->pfnRxCallback (psHIDDevice->pvRxCBData、
    USBD_HID_EVENT_SET_REPORT、
    psInst->ui16OutReportSize、
    psInst->pui8OutReportData); 

    也许这可能是导致您问题的原因?

    就线程而言... 我可以编辑此主题的主题标题、以更好地反映核心讨论。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    拉尔夫

    感谢您更新标题、感谢您的回复!  

    这是我要寻找的来源。  但这似乎是有道理的。  根据 TI 的文档、当我通过端点0发送消息时、我应该会在回调中看到一个中断、事件类型为 USBD_HID_EVENT_GET_REPORT_buffer。  一旦发生这种情况、我应该立即看到 RxHandler 再次被调用、并显示此事件 USBD_HID_EVENT_SET_REPORT。  我相信您找到的代码是第二次调用我的 RxHandler 以返回端点0中的数据的代码。  我将花更多时间深入了解 usbhid.c、看看我是否可以取得更多进展。

    在我在 USB 集线器上记录流量的平均时间内、Tiva 部件也被连接。  我有一个运行 USB 驱动程序库版本1.x 的 Tiva。  我有第二个版本是相同的硬件设计、但运行更新的驱动程序库2.1.4.178。  我已附上这两个日志、以防您想查看它们。  我不知道他们上传的是否正确。  我尝试了回形针链路、但它们插入了巨大的文件夹图像。

    Log4.pcap

    e2e.ti.com/.../log4.zip

    Log5.pcap

    e2e.ti.com/.../log5.zip

    不管怎样、您可以在铁鲨中打开这些日志文件并查看流量。  在筛选器部分中,您可以使用 usb.device_address =11 for log5去除所有其他通信,并查看来自工作设备的通信。  Log5是工作正常的设置、USB 链接永远不会崩溃。  设备不断地向软件/PC 发送一条0x3f08.....消息 数据包。  这是不相关的。  相关数据包以0x3f02开头。  该消息的工作方式如下:

    软件向 Tiva 部件发送一个0x3f02数据包。  Tiva 部件应该在端点1上用0x3f02 [数据字节]进行响应。  这是 EP1上 Tiva 部件中主软件循环的响应。  不过出于某种原因、Tiva 部件实际上用0x3f02fffff... 数据包、然后 EP1上预期的数据包0x3f02[DATA]。  对于旧的驱动程序库、这是一致的、并且全天都可以正常工作。  以下是日志中的一条消息的屏幕截图。

    我希望这是可读的:/

    对于 log4、请使用 usb.device_address == 17作为滤波器选项、如下面的屏幕截图所示:

    日志4显示了使用最新 USB 驱动程序库运行最新 driverlib 的器件。  在我连续发送几条(2-15)消息后、该器件具有 USB 链路超时。  这两个示例中的消息完全相同。  我注意到、ep0上没有自动响应、我认为这会导致 USB 链路锁定。  

    下面是一个屏幕快照、显示流量和缺少的 ep0响应。

    当查看使用旧 driverlib (v1.x)的流量时、它看起来是这样的-当我的软件应用在 ep0上发送 Tiva 消息时、Tiva 驱动程序会以回显或该端点上的某个内容进行响应、回调将按预期工作、从而允许我抛出 在我的 RxHandler 中标记、并告诉我的主循环通过 EP1发送数据包以响应消息。

    查看使用最新 driverlib (上面的版本号)的流量时、在收到几条消息后、Tiva 驱动程序不再在 ep0上响应、USB 链接超时。  

    这是我作为接收数据处理程序传递给驱动程序的 RxHandler()函数。

    //接收处理程序
    uint32_t
    RxHandler (void *pvCBData、uint32_t ui32Event、uint32_t ui32MsgData、
    void *pvMsgData)
    {//WTimer0_SET_Counter
    
    (/*counter*/ 800000/10);//尝试修复 DeepSleep ()模式的速率问题
    
    //调试信息
    static int countRXAvailable=0;
    //静态 int countTXAvailable=0;
    static int countIdleTimeout=0;
    static int countGetReportBuffer=0;
    static int countGetReport=0;
    static int countSetReport=0;
    static int countDefault=0;
    //static uint32_t EventList[20];
    静态 int eventListIdx=0;
    //结束调试变量
    uint32_t readPacketSize;
    //uint32_t writePacketSize;
    //uint32_t retCode;
    //tDataBuffer * MyData = pvCBData;
    
    //调试信息
    //EventList[eventListIdx+]=ui32Event;
    if (eventListIdx==20)
    {
    eventListIdx=0;
    }
    
    switch (ui32event)
    {
    案例 USB_EVENT_Connected:
    USBState|=1;
    
    //更改 USB 优先级,以便在运行时不会干扰 ADC
    IntPrioritySet (INT_USB0、0x60);
    USB_枚 举= 1;//显示 USB 连接或断开连接的标志
    
    中断;
    案例 USB_EVENT_DISCONNECTED:
    USBState&=0xFE;
    USB_枚 举= 0;//显示 USB 连接或断开连接的标志
    
    中断;
    案例 USB_EVENT_RX_Available:
    countRXAvailable++;
    //未经测试的代码
    #if 0
    //处理输出端点上的设置报告
    readPacketSize=USBDHIDRxPacketAvailable(&G_sHIDDataPipeDevice);
    if (readPacketSize=0)
    {
    _nop();//不应发生
    }
    writePacketSize=USBDHIDPacketRead (&G) sHIDDataPipeDevice、
    MyData->buffer、
    max_packet_size
    ,1);
    if (writePacketSize=0)
    {
    _nop();//不应该发生
    }如果(writePacketSize!= readPacketSize),则为其他值
    {
    _nop();//不应发生
    }
    // TODO、可能需要在这里等待 TX 可用。
    retCode=USBDHIDTxPacketAvailable(&g_sHIDDataPipeDevice);
    if (writePacketSize=0)
    {
    _nop();//不应发生
    }
    //回显出来
    retCode=USBDHIDReportWrite (&G) sHIDDataPipeDevice、MyData->buffer、writePacketSize、1);
    if (writePacketSize!=readPacketSize)
    {
    _nop();//不应发生
    }
    返回0;
    #endif
    中断;
    案例 USBD_HID_EVENT_IDLE_TIMEOUT:
    //未定义超时。
    countIdleTimeout++;
    中断;
    
    案例 USBD_HID_EVENT_GET_REPORT_BUFFER:
    //将 Rx 缓冲器返回到 USB driverlib、以此类推
    //可以存储报告
    countGetReportBuffer++;
    // TODO:检查报告 ID
    
    readPacketSize=(uint32_t) pvMsgData;
    if (readPacketSize>MAX_PACKE_SIZE)
    {
    _nop();//不应发生
    }
    
    return ((uint32_t) RXData.buffer);
    中断;
    案例 USBD_HID_EVENT_GET_REPORT:
    //主机正在请求特定报告
    countGetReport++;
    中断;
    案例 USBD_HID_EVENT_SET_REPORT:
    //报告接收缓冲区已准备就绪
    //读取。
    countSetReport++;
    //待办事项:检查报告标识
    //设置大小以让应用程序知道有数据。
    RXData.size=(uint16_t)(ui32MsgData&0xFFFF);
    RXData.state=1;
    
    if (RXData.buffer[1]= 0x03){
    
    BurstMode_Unlock = 1;
    
    }
    中断;
    
    //听起来新驱动程序需要这样的驱动程序
    案例 USB_EVENT_SUSPEND:
    中断;
    
    //听起来新驱动程序需要这样的驱动程序
    案例 USB_EVENT_RESUME:
    中断;
    
    //添加了此尝试调试新 USB 通信错误- 2018年1月15日
    案例 USB_EVENT_ERROR:
    while (1);
    
    中断;
    
    默认值:
    countDefault++;
    中断;
    }
    
    //很确定默认返回值应为0。 需要验证
    返回1;
    
    } 

    此问题在发送的消息数方面也不一致。  它会发生变化、因此有时会在2、5、7、11等之后失败...  似乎加快了它们的速度、这会使问题更快地解决、但我无法真正验证、因为这太不一致了。

    我已附上一张我插入的屏幕截图 zip 文件、以防质量不佳。

    e2e.ti.com/.../TrafficScreenShots.zip

    我将继续挖掘、但我想你们可能会从零件的流量和响应中挖掘出一些东西。

    再次感谢您对 Ralph 的支持、我真的很感激!

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    如果将来有人遇到同样的问题、我不知道如何通过 EP0发送数据、因此我必须支持3个端点。 用于配置的 EP0、EP1输入、EP2输出。