【MCU应用笔记】NXP LPC5516 USB 代码流程讲解(下)
LPC5516 是 NXP LPC55XX 系列的一款 General MCU,具有 HighSpeed USB 功能,能够实现最高 8K Report Rate。在高端的电竞外设市场中有着巨大的优势。在上一篇的博文中我们探讨了如果切换 HighSpeed 以及 FullSpeed USB 代码的文件结构说明。接下来我们继续探讨 USB 代码中其他部分。
在键鼠的开发过程中,客户产品现在都不会只是单一的描述符,即鼠标产品中描述符不单单只有鼠标,会有键盘,consumer 甚至其他 vendor define 的描述符。那这样的话,就需要你的 USB interface 通道不单单只有一个了,就可能需要两个或者三个 interface 来进行额外的数据传输。对此,在 SDK 中的 USB example有一个对应的例程:usb_device_composite_hid_mouse_hid_keyboard,在该代码中是集合了 mouse 以及 keyboard 这两个功能,并且分成了两个 interface 来传输数据。接下来我们就简单的来讲解代码中的文件结构。 从 source 文件中进行分析,如下图所示:
其中 composite C 文件跟头文件是例程中的 main 函数的所在文件,以及运行时 USB 初始化函数,在 USB 进行常规的配置如 USB config 回调函数,USB IRQ 的中断回调函数都是在这个里面。而 hid_mouse、hid_keyboard 头文件跟 C 文件就是对应到 Mouse 以及 keyboard 这两个 interface 中的处理函数以及发送函数,当 USB 连接完成设备描述符通讯完成后,主机根据描述符的内容对不同设备进行 set report 以及 get report 的操作时的回调函数就是在这两个对应的函数中进行处理,如下图所示:
如果说我们除了鼠标跟键盘的功能之外,客户还想再加一个 interface 来传输 vendor define 数据的话,需要怎么做? 对此,我们首先是要像上面那种添加对应的头文件跟 C 文件来预留出对应的回调函数接口。然后要在 usb_device_descriptior 的头文件以及C文件中添加对应的各种描述符配置,如下图,这个具体相关配置由于数量比较多这就不展开细聊,详细可以参考 SDK 中 mouse 或者 keyboard 的添加配置内容来模仿或者可以联系我们公司的技术支持窗口。
在添加完相关的配置之后,我们就来简单了解一下 set report 以及 get report 的数据流程。 首先从最根本的地方开始看起来:USB IRQ,如下图:
在该函数中,会根据中断标志位以及 USB 状态来调用对应的函数,这里由于是 set report 以及 get report 的数据,所以会调用下图函数:
在该函数中会读取 USB 中的数据并存储到 buffer 中,当接收完成后就会调用函数发送 notify。
在这个函数中会调用我们在 pipeinit 函数中配置到的回调函数epCallback来处理对应的数据。
在本质上就是一步步地对 USB 数据进行分析后再一步步上报上一层的回调函数。例如在本文中的 set report 以及 get report 数据会调用到 USB_DeviceClassCallback 函数中继续进行分析,在该函数中就会采用轮询的方法将数据发送到不同的 interface 中进行处理,然后根据回调状态来判断是否为对应的 interface 通道,如下图:
其中这个 classIndex 参数就是我们定义的 interface 数目,在 g_UsbDeviceCompositeConfigList 这个结构体中,并且是我们在一开始的 USB 初始化中通过 USB_DeviceClassInit 定义好的,详细的结构体定义数据这边就不展开详聊。而调用的处理函数 classEventCallback 实际为 USB_DeviceHidEvent,具体可以在 s_UsbDeviceClassInterfaceMap 数组中找到。其中 USB_DeviceHidEvent 函数也会对数据进行分析,具体这一部分的数据协议可以查看 USB 官方文档《Device Class Definition for Human Interface Devices (HID)》,在函数里面我们找到关于 set report 以及 get report 的内容:
可以看到在这里面是会调用到结构体中的 classCallback 来进行处理,而这一个实际上就是我们上文说的 hid_mouse 跟 hid_keyboard C 文件中说的回调函数,这两者是通过 g_CompositeClassConfig 这一个结构体 link 起来的,具体如下:
到这里我们就简单的将 set report 跟 get report 的数据流程由中断处理到实际上 APP 中调用到的回调函数梳理了一遍,具体细节数据可以自行参考代码。
在经过了上下篇的讨论中,我们基本把 USB 代码中经常修改的内容及地方都进行了解析,并说明了如何按照自己的需要来进行修改。相信大家也对 USB 的代码有一定的了解,如果想要更深入的了解 USB 功能可以建议配合 USB 官方文档以及 LPC5516 的 UserManual 进行查看。
[1]《Device Class Definition for Human Interface Devices (HID)》 [2]《SDK_2_11_0_LPCXpresso55S16》 [3]《LPC55S1x/LPC551x User manual》 |