USB总线-Linux内核USB3.0设备控制器中断处理程序分析(九)

news/2024/9/20 7:16:35/文章来源:https://www.cnblogs.com/linhaostudy/p/18412435

1.概述

USB设备枚举、请求处理、数据交互都涉及USB设备控制器中断。当有事件发生时,USB设备控制器首先将事件信息通过DMA写入到事件缓冲区中,然后向CPU发出中断,随后CPU调用中断处理函数开始处理中断事件。

2.事件

dwc3 USB设备控制器事件使用dwc3_event数据结构描述,由4个字节组成。按位域区区分,可分为3类事件,分别为设备端点事件、设备事件及其他核心事件。dwc3_event_type用来描述事件的类型,is_devspec == 1表示事件为设备事件,否则表示设备端点事件。dwc3_event_depevt描述设备端点事件,包含了产生事件的端点编号、具体的事件、事件状态等信息。dwc3_event_devt描述设备控制器事件,包含了具体的设备事件、事件类型、事件信息等。dwc3_event_gevt使用的不多,这里不详细介绍。

[drivers/usb/dwc3/core.h]
/*** union dwc3_event - representation of Event Buffer contents* @raw: raw 32-bit event* @type: the type of the event* @depevt: Device Endpoint Event* @devt: Device Event* @gevt: Global Event*/
union dwc3_event {u32                raw;struct dwc3_event_type        type;   // 事件类型struct dwc3_event_depevt    depevt; // Device Endpoint Eventsstruct dwc3_event_devt        devt;   // Device Eventsstruct dwc3_event_gevt        gevt;   // 全局事件
};
struct dwc3_event_type {u32    is_devspec:1;          // 是否是设备事件 u32    type:7;                // 事件类型u32    reserved8_31:24;       // 保留
} __packed;

[drivers/usb/dwc3/core.h] /* dwc3 USB设备端点事件宏定义 / #define DWC3_DEPEVT_XFERCOMPLETE 0x01 // 传输完成 #define DWC3_DEPEVT_XFERINPROGRESS 0x02 // 传输正在处理中 #define DWC3_DEPEVT_XFERNOTREADY 0x03 // 传输未准备好 // 接收和发送FIFO事件 (IN->Underrun, OUT->Overrun) #define DWC3_DEPEVT_RXTXFIFOEVT 0x04 #define DWC3_DEPEVT_STREAMEVT 0x06 // 流事件 #define DWC3_DEPEVT_EPCMDCMPLT 0x07 // 端点命令完成 struct dwc3_event_depevt { / USB设备端点事件 */ u32 one_bit:1; // 未使用 u32 endpoint_number:5; // 端点编号 u32 endpoint_event:4; // 端点事件 u32 reserved11_10:2; u32 status:4; // 端点事件状态 u32 parameters:16; } __packed;

3.事件缓冲区

dwc3事件保存在dwc3_event_buffer数据结构中,各个成员的意义如下。事件保存在buf中,dma是buf的DMA地址,事件数据由DMA传输到buf中,lpos是缓冲区中已处理事件的偏移,count表示缓冲区中的事件数量。事件使用dwc3_event数据结构描述,上面已经介绍过了。不同的事件,有不同的处理方法。

[drivers/usb/dwc3/core.h]
/* 事件缓冲区数据结构 */
struct dwc3_event_buffer {void            *buf;    // 事件缓冲区地址unsigned        length;  // 事件缓冲区长度unsigned int    lpos;    // 事件缓冲区偏移unsigned int    count;   // 缓存最近一次产生事件的数量unsigned int    flags;   // 事件缓冲区标志
#define DWC3_EVENT_PENDING    BIT(0)dma_addr_t        dma;     // 事件缓冲区DMA地址struct dwc3        *dwc;    // 指向DWC控制器数据结构
};

dwc3_event_buffer数据结构的初始化过程如下:

  1. dwc3_probe函数中,调用dwc3_alloc_event_buffers函数分配dwc3_event_buffer结构体,调用dma_alloc_coherent分配buf,长度为4096字节,记录虚拟地址和DMA地址。
  2. dwc3_core_init函数中,调用dwc3_event_buffers_setup函数,将buf的DMA地址、长度分别写入USB设备控制器对应的寄存器,将事件数量寄存器和缓冲区偏移清零。

4.事件处理

dwc3 USB设备控制器的事件分为两步处理。第一步在中断上半部分处理,只记录事件数量,第二步在中断下半部(线程)处理,遍历事件缓冲区,循环处理所有事件。

4.1.中断上半部分

dwc3 USB3.0设备控制器事件的中断上半部分处理流程如下图所示。首先保存全局事件数量,设置事件pending标志,接着屏蔽控制器的中断,最后返回IRQ_WAKE_THREAD,唤醒中断处理线程。可以看出,中断上半部分很简单,只做了读写寄存器和保存状态的工作,不涉及具体事件的处理。

4.2.中断下半部分

dwc3 USB3.0设备控制器的中断下半部分处理流程如下图所示。事件处理是在持有自旋锁和关中断的情况进行的。在dwc3_process_event_buf函数中,循环处理所有事件。处理完毕,将事件数量和事件pending标记清零,最后重新打开中断并退出。

dwc3_process_event_entry函数负责处理一个具体的事件,根据事件类型,又分为端点事件和设备事件,端点事件调用dwc3_endpoint_interrupt函数处理,设备事件调用dwc3_gadget_interrupt函数处理。端点事件和设备事件下又分了很多具体的事件,比较复杂,碍于篇幅,这里只介绍端点0的事件。

image

4.2.1.端点0事件

端点0事件调用dwc3_ep0_interrupt函数处理,处理流程如下图所示。对于DWC3_DEPEVT_XFERINPROGRESSDWC3_DEPEVT_RXTXFIFOEVTDWC3_DEPEVT_STREAMEVTDWC3_DEPEVT_EPCMDCMPLT事件,驱动程序不做额外的处理,直接返回。当端点0产生DWC3_DEPEVT_XFERCOMPLETE事件时,其对应端点0控制传输的三个状态,分别为建立阶段、数据阶段和状态阶段,其中数据阶段可选。具体可参考http://www.usbzh.com/article/detail-55.html。下面分析一下dwc3 USB设备控制器驱动对这个三个阶段的处理。

image

  1. EP0_SETUP_PHASE

在调用dwc3_gadget_start使能USB设备控制器时,端点0的状态被设置为EP0_SETUP_PHASE,等待接收来自主机的SETUP数据包,接收到SETUP数据包后控制器产生DWC3_DEPEVT_XFERCOMPLETE事件,根据端点0状态进入dwc3_ep0_inspect_setup函数进行处理。主机发送的SETUP数包可分为两类,一类是标准的USB请求,如USB_REQ_GET_STATUSUSB_REQ_CLEAR_FEATUREUSB_REQ_SET_FEATURE等,调用dwc3_ep0_std_request函数处理。非标准请求调用dwc3_ep0_delegate_req函数处理。在dwc3_ep0_std_request函数中,驱动处理了一部分标准的USB请求,如获取和设置设备或端点的特性、状态等,其他复杂的请求,调用dwc3_ep0_delegate_req函数处理。dwc3_ep0_delegate_req函数内部会调用上层USB gadget driver提供的set_up函数,即composite_setup函数。

composite_setup函数的处理流程如下图所示。按主机发送的USB请求进行处理,分为标准的USB请求和非标准的USB请求。非标准的USB请求最终通过调用uac2驱动的afunc_setup函数处理。最后判断是否有数据要传输,如USB_REQ_GET_DESCRIPTOR请求是需要数据阶段的,若需要,则会调用composite_ep0_queue将数据发送到端点0,同时将端点的状态设置为EP0_DATA_PHASE

usb_ctrlrequest各个字段的定义如下图所示。USB标准请求bRequest字段的bit[5-6]位都为0。若bRequest字段的bit[5-6]位为01,则是USB类设备定义的命令,需要USB类设备驱动处理。下面是uac2设备接收的USB请求,需要调用uac2驱动的afunc_setup函数处理。

bRequestType = 0xa1
bRequest     = 0x2
wValue       = 0x100
wIndex       = 0x500
wLength      = 0x100
  1. EP0_DATA_PHASE

EP0_SETUP_PHASE阶段之后,若需要传输数据,则会有EP0_DATA_PHASE阶段。数据传输完成后,产生DWC3_DEPEVT_XFERCOMPLETE事件,根据当前端点0的状态,进入dwc3_ep0_complete_data函数处理。dwc3_ep0_complete_data的主要工作是判断端点0是否还有数据要传输,若需要先回调usb_request的回调函数,接着启动传输,反之直接返回。

  1. EP0_STATUS_PHASE

EP0_STATUS_PHASEDWC3_DEPEVT_XFERNOTREADY事件设置。此阶段由dwc3_ep0_complete_status函数处理,主要的工作准备TRB,为下一次的控制传输的SETUP做准备。

端点0的DWC3_DEPEVT_XFERNOTREADY事件主要用于指出当前请求的传输阶段是数据阶段还是状态阶段。具体由dwc3_event_depevtstatus字段决定。若是数据阶段且还有未发送完的数据,则会忽略;若是状态阶段,则首先设置端点0的状态为EP0_STATUS_PHASE,接着传输状态阶段(DWC3_TRBCTL_CONTROL_STATUS3/DWC3_TRBCTL_CONTROL_STATUS2)的数据包。

当状态阶段的数据包传输完成后,产生DWC3_DEPEVT_XFERCOMPLETE事件,此时就进入了EP0_STATUS_PHASE的处理逻辑

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/796622.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

通义灵码企业代码补全增强使用实践

通义灵码提供了企业代码补全增强的能⼒,在开发者使⽤通义灵码 IDE 插件的⾏间代码补全时,可以结合企业上传的代码库作为上下⽂进⾏⾏间代码补全,使代码补全更加贴合企业代码规范、业务特点。本⽂将分享如何构建⾼质量的企业代码库,以及开发者在前端和后端开发场景的使⽤实践…

LeetCode算法—分治法

纵有疾风起;人生不言弃思路:分治法的核心思想是“分而治之”,即将一个复杂的问题分成多个较小的子问题,分别求解这些子问题,然后将子问题的解合并,得到原问题的解。具体到求众数的问题上,分治法通过递归地将数组分成两部分,分别找出每一部分的众数,最后通过合并步骤来…

学习高校课程-软件设计模式-OOP 和 UML 类图 OOP 与 Java(lec1)

OOP 和 UML 类图 OOP 与 JavaLecture 1:OOP and UML Class DiagramsOOP with Java OOP 和 UML 类图 OOP 与 Java Object-Oriented Programming 面向对象编程Class Hierarchies 类层次结构 Superclass and subclass 超类和子类Pillars of Object-Oriented Programming 面向对象…

路由器刷机踩坑

ssh/telnet 路由器一般是用23端口,也就是telnet。具体如何开启ssh看型号。 breed breed是一个bootloader,在功能上类似于手机的Rec,用于提供一个界面刷入不同分区的镜像(至少不用敲命令行了)。 注意 breed不能用于刷入原厂固件,否则会砖(我就是这么干的)。 这是恩山论坛…

Pbootcms网站挂马解决方案(详细说明)

当你的PbootCMS网站被挂马时,应该立即采取措施来清除恶意代码,并加强系统的安全性,防止未来的攻击。以下是一个详细的解决方案: 1. 备份现有数据 在开始任何修复工作之前,首先备份你的网站数据,包括数据库和文件系统。这一步骤是为了防止在修复过程中丢失重要数据。 2. 检…

SVN在MacOS下报E230001错误

#macos #rider for Mac #SVN #E230001svn为什么会报E230001错误呢?根据详细错误信息Server SSL certificate verification failed: certificate issued知道这是https证书有问题,不用管它证书了,这里介绍一种简单的方法。 首先,打开终端(terminal,mac os/linux一般都是带…

面试-JS Web API - 存储

cookie HTML5存储(localStorage 和 sessionStorage)cookie cookie本身用于浏览器和server通讯的,被借用到本地存储来。可以用document.cookie来修改。同一个变量会覆盖,不同变量会追加。localStorage 和 sessionStorage// 保存数据到 localStorage localStorage.getItem(a,10…

MySQL8的新特性

一 字典数据与资源管理1.1 数据字典 以前MySQL都是采用元数据文件、非事务性表结构或者是存储引擎特有的方式来存储字典数据,这些字典数据通常都是以数据对象为主,比如说最常见的表结构信息等。 在MySQL8.0中,这些字典数据都被移动到拥有InnoDB存储引擎的事务性表中进行存储…

通义灵码获得国产 AI 编码工具最高成绩丨阿里云云原生 8 月产品月报

《阿里云云原生每月动态》,从趋势热点、产品新功能、服务客户、开源与开发者动态等方面,为企业提供数字化的路径与指南。云原生月度动态 云原生是企业数字创新的最短路径。 《阿里云云原生每月动态》,从趋势热点、产品新功能、服务客户、开源与开发者动态等方面,为企业提供…

执行yarn命令的时候报错: error Error: certificate has expired

完整错误:原因是:SSL证书过期 执行命令关闭验证: yarn config set strict-ssl false

《抽象代数》系列之群论入门

一、重要性 1.1 领域意义 群论是数学的一个分支,主要研究代数结构中的群、环、域等。尽管它看似抽象,但在编程领域,群论有着广泛的应用和深刻的意义。算法设计与优化:群论在算法设计中发挥着重要作用。例如,在密码学中,群论被用于设计安全的加密算法,如椭圆曲线密码学,…

【转】Chrome 的无头模式升级了:推出 --headless=new

Chrome的无头模式变得更好用了!本文概要介绍了近期的工程工作,让 Headless 更接近Chrome的常规“Headful”模式,让Headless对开发者更有用。 背景 早在 2017 年,Chrome 59 便引入了所谓的无头模式,可让您在没有任何可见界面的无人值守环境中运行浏览器。从本质上讲,就是在…