ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

RT-Thread 中 Microchip SAMD51 的 USB Device Core:枚举协议处理与设备类驱动管理

RT-Thread 中 Microchip SAMD51 的 USB Device Core:枚举协议处理与设备类驱动管理 操作系统嵌入式物联网嵌入式OSRTOS【免费下载链接】rt-threadRT-Thread is an open source IoT Real-Time Operating System (RTOS). https://rt-thread.github.io/rt-thread/项目地址https://gitcode.com/gh_mirrors/rt/rt-thread点击查看免费下载USB Device Coreusbdc是 Microchip USB Device Stack 库中的核心层位于 USB 设备类驱动与底层 USB Device DriverHAL之间负责处理 USB 主机枚举期间产生的全部标准控制请求并确保上层类驱动如 CDC ACM 虚拟串口在描述符配置正确的前提下被成功安装。本文以 bsp/microchip/samd51-adafruit-metro-m4/bsp/documentation/usb_device_core.rst 为主干结合该 BSP 中 USB 栈的源码实现逐层拆解 usbdc 的状态机、标准请求分发、回调管理、数据传输与类驱动注册机制帮助读者掌握如何在 RT-Thread 工程中配置和使用这套 USB 设备栈。USB Device Core 的定位与分层USB Device Core 是 USB Device Stack 库的组成部分它自身不实现任何具体设备功能如串口、存储、HID而是承担两类职责枚举期请求处理响应 USB 主机在枚举阶段发出的全部标准请求GetDescriptor、SetAddress、SetConfiguration 等使设备能被主机正确识别类驱动托管为上层 Class Driver即 Function Driver提供注册、启用、禁用和查询接口的服务框架。其依赖关系在文档中明确给出USB Device Driver底层硬件驱动对应本 BSP 中的 HAL 层见 hal_usb_device.h 与 hal_usb_device.cUSB Protocol CoreUSB 协议常量和描述符解析工具见 usb_protocol.h 与 usb_protocol.c。从整体 USB 栈结构看bsp/usb 目录分层关系为Class Driver如 CDC ACM→ USB Device Coreusbdc→ USB Device DriverHALhpl_usb→ USB 控制器硬件。core 层通过usbdc_xfer()等接口向上层屏蔽端点传输细节向下调用usb_d_ep_transfer()完成实际硬件交互。核心特性一览文档列出的 USB Device Core 特性如下均可在源码中找到对应实现特性源码落点初始化 / 反初始化usbdc_init()/usbdc_deinit()usbdc.c使能 / 禁用设备类组件usbdc_register_function()/usbdc_unregister_function()以及USBDF_ENABLE/USBDF_DISABLE控制码数据传输usbdc_xfer(ep, buf, size, zlp)usbdc.c连接 / 断开控制usbdc_attach()/usbdc_detach()usbdc.c主机唤醒远程唤醒usbdc_remotewakeup()usbdc.c回调管理SOF 事件、设备状态变化、设备请求三类回调的注册与注销设备状态机从 OFF 到 CONFIGcore 层维护一个完整的 USB 设备状态机状态定义见 usbdc.henum usbd_state { USBD_S_OFF 0, /* 设备关闭 */ USBD_S_POWER 1, /* 上电usbdc_start 后进入 */ USBD_S_DEFAULT 2, /* 默认态收到复位后 */ USBD_S_ADDRESS 3, /* 已分配地址SetAddress 完成 */ USBD_S_CONFIG 4, /* 已配置SetConfiguration 完成 */ USBD_S_SUSPEND 0x10 /* 挂起 */ };状态迁移的关键路径usbdc_start(desces)校验描述符后设置state USBD_S_POWER并调用usb_d_enable()usbdc.c总线复位事件USB_EV_RESET触发usbdc_reset()把状态重置为USBD_S_DEFAULT并重新初始化端点 0EP0usbdc.c控制传输状态阶段完成后usbdc_ctrl_status_end()根据SET_CONFIG/SET_ADDRESS请求更新cfg_value与state并向所有已注册的 Change 回调发出USBDC_C_STATE通知usbdc.c。usbdc_get_state()会特殊处理挂起标志若状态带有USBD_S_SUSPEND位则返回挂起态否则返回当前基本状态usbdc.c。标准请求处理枚举协议的核心实现枚举期间 USB 主机通过控制端点发送标准请求core 层在 EP0 的 SETUP 回调usbdc_cb_ctl_req()中按“先类请求、后标准请求”的顺序处理usbdc.c先遍历请求回调链usbdc_request_handler()让类驱动有机会优先响应未被类驱动处理且bmRequestType为标准类型时分派到usbdc_set_req()OUT 方向或usbdc_get_req()IN 方向。GET_DESCRIPTOR 分发usbdc_get_desc_req()依据wValue高字节描述符类型分发usbdc.cUSB_DT_DEVICE→usbdc_get_dev_desc()设备描述符固定 0x12 字节超过 0x12 的wLength会被截断USB_DT_CONFIG→usbdc_get_cfg_desc()按wValue低字节配置索引用usb_find_cfg_desc()查找配置描述符并通过usb_cfg_desc_total_len()计算总长度自动处理 ZLP零长度包边界USB_DT_STRING→usbdc_get_str_desc()按字符串索引查找长度以描述符首字节str_desc[0]为准在CONF_USBD_HS_SP开启高速支持时还会处理USB_DT_DEVICE_QUALIFIER与USB_DT_OTHER_SPEED_CONFIG。描述符查找统一使用usb_find_desc()/usb_find_str_desc()等协议工具函数这意味着描述符只需按规范拼接成一个连续字节数组即可无需手工拆分。SET_ADDRESS / SET_CONFIG / SET_INTERFACESET_ADDRESS先以 ZLP 完成状态阶段随后在usbdc_ctrl_status_end()中真正调用usb_d_set_address()写入地址usbdc.cSET_CONFIGusbdc_set_config()解析配置描述符遍历其中每个USB_DT_INTERFACE对每个新出现的接口号调用已注册 Function Driver 的ctrl(func, USBDF_ENABLE, desc)从而把接口描述符与端点信息交给对应类驱动完成安装usbdc.cwValue 0时走usbdc_unconfig()关闭全部接口SET_INTERFACEusbdc_set_interface()在配置描述符中定位bInterfaceNumber与bAlternateSetting匹配的接口先USBDF_DISABLE旧配置再USBDF_ENABLE新配置并维护ifc_alt_map位图记录正在使用备用设置Alternate Setting的接口usbdc.c。GET_STATUS / CLEAR_FEATURE / SET_FEATUREGET_STATUS设备与接口接收方直接返回 0端点接收方则查询端点 halt 状态usb_d_ep_halt(ep, USB_EP_HALT_GET)结果通过ctrl_buf回传 2 字节usbdc.cCLEAR_FEATURE/SET_FEATURE仅支持端点接收方调用usb_d_ep_halt()清除或设置端点的 HALTstall状态并以 ZLP 完成控制传输usbdc.c。三类回调管理机制core 层将回调组织为三类分别对应文档所述三个回调管理维度注册/注销接口为usbdc_register_handler()/usbdc_unregister_handler()usbdc.c处理器类型回调原型触发时机USBDC_HDL_SOFusbdc_sof_cb_tvoid cb(void)每个 SOF帧起始事件经usbd_sof_cb()→usbdc_sof_notify()链式通知USBDC_HDL_REQusbdc_req_cb_tint32_t cb(ep, req, stage)每个控制请求的 SETUP / DATA 阶段见usbdc_request_handler()USBDC_HDL_CHANGEusbdc_change_cb_tvoid cb(change, value)状态 / 连接 / 电源 / 远程唤醒变化Change 通知的类型定义在 usbdc.hUSBDC_C_CONNVBUS 检测到的连接状态变化USB_EV_VBUS事件触发见 usbdc.cUSBDC_C_STATE因 RESET、SetAddress、SetConfig 引起的状态变化USBDC_C_POWER电源状态变化USBDC_C_REMOTE_WAKEUP远程唤醒设置变化。请求回调采用“链式优先处理”语义回调返回 0 表示已处理成功返回ERR_NOT_FOUND表示不处理继续遍历下一个返回其他错误则直接中止并视为协议错误usbdc.c。设备类驱动Function Driver的注册与生命周期上层类驱动通过struct usbdf_driver接口与 core 解耦定义见 usbdc.hstruct usbdf_driver { struct usbdf_driver *next; usbdf_control_cb_t ctrl; /* 控制函数入口 */ void *func_data; /* 驱动私有数据 */ };ctrl接收enum usbdf_control控制码usbdc.hUSBDF_ENABLE参数携带struct usbd_descriptors描述符起始sod/ 结束eod类驱动据此分配端点、注册传输回调并启动接收USBDF_DISABLE关闭接口端点参数为 NULL 时强制禁用USBDF_GET_IFACE返回指定接口的当前 Alternate Setting用于响应GET_INTERFACE。文档特别提醒建议至少有一个设备类运行在 USB Device Core 之上。从实现角度看这是因为 core 层只负责枚举与标准请求具体的功能行为数据收发、通知、线路编码等完全依赖类驱动的USBDF_ENABLE回调在 SetConfiguration 时完成实例化。以 CDC ACM 类为例cdcdf_acm_init()内部会调用usbdc_register_function()把自身挂入 core 的func_list从而在后续SET_CONFIG时被启用见 cdcdf_acm.h。数据传输usbdc_xfer 与端点抽象usbdc_xfer()是 core 层对外统一的数据传输入口其实现非常简洁usbdc.cint32_t usbdc_xfer(uint8_t ep, uint8_t *buf, uint32_t size, bool zlp) { struct usb_d_transfer xfer {(uint8_t *)buf, size, ep, zlp}; return usb_d_ep_transfer(xfer); }参数语义ep端点地址含方向位bit8 表示 IN/OUT 方向buf/size传输缓冲区与字节数zlp是否在数据长度恰为端点最大包长整数倍时追加零长度包用于明确传输结束边界。core 层的描述符响应设备描述符、配置描述符、字符串描述符、GET_STATUS 的 2 字节状态全部经由该接口回传端点 0 的控制缓冲区由调用方在usbdc_init(ctrl_buf)时提供其大小不得小于 EP0 的最大包长见 usbdc.h 的注释约束。依赖与限制依据文档USB Device Core 的依赖为USB Device Driver与USB Protocol Core两层实际编译时还依赖配置头文件usbd_config.h中CONF_USBD_HS_SP等开关决定是否编译高速HS描述符与设备限定符处理分支。限制方面文档明确指出建议至少一个设备类运行在 USB Device Core 之上。此外从 usbdc.c 的实现可推断usbdc_start()在设备已处于USBD_S_POWER及以上状态时会返回ERR_BUSY因此启动流程必须遵循“先 init、后 start”的顺序且同一时刻只能运行一套设备描述符集合。在 SAMD51 上的完整初始化流程本 BSP 的 usb_start.c 给出了以 CDC ACM虚拟串口为上层类的典型启动序列void cdc_device_acm_init(void) { /* 1. 初始化 core提供 EP0 控制缓冲区 */ usbdc_init(ctrl_buffer); /* 2. 注册 CDC ACM 类驱动内部调用 usbdc_register_function */ cdcdf_acm_init(); /* 3. 以描述符数组启动 core解析出 EP0 最大包长并使能控制器 */ usbdc_start(single_desc); /* 4. 连接主机开始枚举 */ usbdc_attach(); }其中ctrl_buffer[64]用作端点 0 控制传输缓冲区single_desc是struct usbd_descriptors数组其字节内容来自cdcdf_acm_desc.h生成的CDCD_ACM_DESCES_LS_FS描述符宏枚举完成后主机发出SET_CONFIGcore 遍历配置描述符并调用 CDC 驱动的USBDF_ENABLE随后通过CDCDF_ACM_CB_STATE_C状态回调DTR 置位注册读写回调、启动数据收发设备即以虚拟 COM 口形态工作。CDC 类驱动完整的功能面读写、线路编码、线状态回调、enable/disable见 cdcdf_acm.h其配套说明文档 usb_device_cdc.rst 介绍了虚拟串口应用场景而本 BSP 的 HAL 层实现 hal_usb_device.c 与 hpl_usb.c 则负责将usb_d_*接口映射到 SAMD51 的 USB 外设寄存器操作形成从协议处理到寄存器控制的完整闭环。小结USB Device Core 是连接 USB 枚举协议与设备类驱动的枢纽它用一套精简的状态机 标准请求分发 链式回调框架把 USB 规范 Chapter 9 中繁杂的枚举流程封装为usbdc_init→usbdc_start→usbdc_attach三步启动路径。理解其请求分发顺序、USBDF_ENABLE/DISABLE控制语义以及三类回调的触发条件是在此基础上扩展新设备类如 HID、MSC或排查枚举失败问题的关键前提。赞分享操作系统嵌入式物联网嵌入式OSRTOS【免费下载链接】rt-threadRT-Thread is an open source IoT Real-Time Operating System (RTOS). https://rt-thread.github.io/rt-thread/项目地址https://gitcode.com/gh_mirrors/rt/rt-thread点击查看免费下载相关推荐RT-Thread 中的 Microchip USB Device CoreSAMD51 枚举与类驱动安装核心解析RT Thread 中的 Microchip USB Device CoreSAMD51 枚举与类驱动安装核心解析 导读 USB Device Core 是操作系统嵌入式物联网嵌入式OSRTOSRT-Thread 中的 Microchip HAL USART 异步驱动原理、API 与 SAMD51 实战解析RT Thread 中的 Microchip HAL USART 异步驱动原理、API 与 SAMD51 实战解析 USART通用同步/异步收发器是嵌入式操作系统嵌入式物联网嵌入式OSRTOSRT-Thread 中 Microchip SAMD51 的 USART 异步驱动usart_async深入解析RT Thread 中 Microchip SAMD51 的 USART 异步驱动usart_async深入解析 本篇技术指南以 RT Thread 仓库中操作系统嵌入式物联网嵌入式OSRTOS创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表