精华内容
下载资源
问答
  • 在淘宝中USB2.0扩展器一拖四接口大概需要20元RMB+,今日为各位分享基于MA8601芯片实现的USB2.0 扩展器(一拖四)原理图、PCB。

    在淘宝中USB2.0扩展器一拖四接口大概需要20元RMB+,今日为各位分享基于MA8601芯片实现的USB2.0 扩展器(一拖四)原理图、PCB。

     MA8601 芯片是4端口USB 2.0高速HUB集线控制器,4个端口功能可同时工作,产品低功耗、低成本,用户可以通过外挂EEPROM,实现多个集线器配置选项。

    原理图如下所示:

    PCB效果如下所示:

    3D仿真效果如下所示:

    项目资源下载:https://download.csdn.net/download/m0_38106923/12647431

    请关注公众号,回复关键字:USB,免费获取项目资源~

    展开全文
  • 今天给大侠带来基于 FPGA 的 USB 接口控制设计(VHDL),由于篇幅较长,分三篇。今天带来第二篇,中篇,USB通信原理、USB 系统开发以及设计实例。话不说,上货。 之前有关于 Veriliog HDL 实现的USB 接口控制...

    今天给大侠带来基于 FPGA 的 USB 接口控制器设计(VHDL),由于篇幅较长,分三篇。今天带来第二篇,中篇,USB通信原理、USB 系统开发以及设计实例。话不多说,上货。

    之前有关于 Veriliog HDL 实现的 USB 接口控制器设计,这里放上超链接,仅供各位大侠参考。

    源码系列:基于 FPGA 的 USB2.0 设计

    导读 

     

     

    2019年9月4日,USB-IF终于正式公布USB 4规范。它引入了Intel此前捐献给USB推广组织的Thunderbolt雷电协议规范,双链路运行(Two-lane),传输带宽因此提升,与雷电3持平,都是40Gbps。需要注意的是,你想要体验最高传输速度,就必须使用经过认证的全新数据线。USB4保留了良好的兼容性,可向下兼容USB 3.2/3.1/3.0、雷电3。除此之外,USB4将只有USB Type-C一种接口,并支持多种数据、显示协议,包括DisplayPort,可以一起充分利用高速带宽,也支持USB PD供电。

    比较遗憾的是,USB4的发布时间至今暂未公布。值得注意的是,此次发布的USB4是规范,而并非USB4.0。在此之前,USB Implementers Forum(USB-IF)计划取消USB 3.0/3.1命名,统一划归为USB 3.2。其中USB 3.0更名USB 3.2 Gen 1(5Gbps),USB 3.1更名USB 3.2 Gen 2(10Gbps),USB 3.2更名为USB 3.2 Gen 2x2(20Gbps)。以上就是关于USB标准以及命名的讯息。

    现在大部分USB设备(比如USB接口的鼠标、键盘、闪存、U盘等等)都是采用了USB通用驱动,而你的系统有USB通用驱动的话(比如XP就内建了USB通用驱动)就能用。而有些USB设备是需要特殊驱动的,比如某些手机,连接到电脑的USB口,是需要安装驱动才能使用的。下面我们一起动手做一做USB接口控制器设计,了解一下如何设计。

    第二篇内容摘要:本篇会介绍USB通信原理,包括USB 传输模型、USB 设备检测过程;USB 系统开发,包括USB 硬件系统,USB 接口芯片 PDIUSBD12;USB 设计实例,包括设计需求分析以及设计方案等相关内容。

     

    三、USB通信原理

     

    USB 通信可以分为两大类:一类是用来设置 USB 设备的配置;另一类是用来设置应用程序的通信。其中,设置 USB 设备的配置指的是主机了解设备的功能并且准备与其进行数据交换的过程。此时大部分的通信,是发生在开机或者是连接设备时用来检测的过程中。而第二种通信,即应用程序的通信,则是发生在主机与应用程序之间的数据交换,也就是执行设备原始设计的功能。例如键盘设备的应用程序,就是传送按键码给主机,然后告诉应用程序显示该按键的字符。

     

     

    3.1 USB 传输模型

    在介绍 USB 体系结构的时候已经介绍了 USB 总线有两条数据线,并且两条数据线是由所有设备共享的。USB 主机负责管理总线上的数据传输,它会将传输依据时间来分割成若干帧(Frame)或者微帧(Microframe)。每一个帧的开头是一个开端信息包(Start Of Frame),然后是数据传输的事务(Transaction)。

    每一次 USB 传输是由一次或者几次事务组成,而每一个事务又是由信息包(Packet)所组成,信息包是 USB 传输的载体。要了解事务、包以及其具体内容,首先需要了解的概念是端点(Endpoint)和管道(Pipe),这些被称为 USB 传输要件。

     

    1)USB 传输要件

    (1)端点

    端点是 USB 设备的一个部分,所有的传输都是将端点作为发出点或者接收点。通常情况下,设备端点是一个内存区域,或者是控制芯片的一个缓存器,端点的作用是数据缓存。每个 USB设备有一个惟一的地址,这个地址是在设备连上主机时由主机分配的,而设备中的每个端点在设备内部有惟一的端点号,这个端点号是在设备设计时被给定的。端点号可以是 0~15,方向可以是 IN(设备发送数据给主机)或者 OUT(主机发送数据给设备)。每个设备必须将端点 0设置为控制端点,控制端点是双向数据传输的,而其他类型的端点都是单向数据传输。

    (2)管道

    管道是设备端点和主机控制器之间的连接,在一个传输发生之前,必须首先建立一个管道。管道随着主机和设备的连接的建立而建立,当移除设备时,管道也跟着被移除。每一个设备都会和主机之间建立一个默认的控制管道(Default Control Pipe),此管道使用端口 0。不同的传输类型使用不同的管道(这将在下面的内容介绍),此外管道还可以被分为消息管道(Message Pipe)和流管道(Stream Pipe)。消息管道是指具有某种 USB 定义格式的数据流,是双向的管道;而流管道则是不具有 USB 定义格式的数据流,不具有双向性。控制传输是惟一使用双向消息管道的传输,其他的传输都是使用单方向的流管道。

    (3)传输类型

    USB 具有 4 种传输类型,定义多种传输类型的目的是为了适应众多 USB 设备对传输速率、响应时间等方面的不同需求。

    • 控制传输(Control Transfer) 控制传输用于在设备初次连接时对器件进行配置,以及对设备的状态进行实时检测,还有在设备配置完成后用于特殊传输目的。端点 0 只可以采用控制传送的方式。

    • 中断传输(Interrupt Transfer) 中断传输适用于那些小批量的、点式、非连续的数据传输应用的场合,如用于人机交互的鼠标、键盘、游戏杆。

    • 块传输(Bulk Transfer) 块传输用于进行批量的、非实时的数据传输。如一台 USB扫描仪即可采用块传输的模式,以保证高速传输并且实时纠错。采用块传输方式的信道所占用的 USB 带宽在实时带宽分配中具有最高的优先级。

    • 同步传输(Isochronous Transfer) 为保证数据传输的实时性,同步传输不进行数据错误的重试,也不在硬件层次上回应一个握手数据包,这种传输模式具有产生错误的隐患。为保证在同步传输数据流中致命错误的机率小到可以容忍的程度,而数据传输的延迟又不会对设备的性能造成很大影响,制造商必须为使用同步传输的信道选择一个合适的带宽(即必须在速度和品质之间做出权衡)。

     

    2)事务、信息包和联络信号

    每一个 USB 传输包含一个或者多个事务,而每一个事务又包括了一个、两个或者 3 个信息包。图 6 所示就是 USB 传输的模型。

    图 6 USB 传输模型示意图

     

    事务根据其数据流方向以及目的,可以分为 3 类:输入、输出与设置。每一个传输类型的传输包括一个或者多个阶段(Stage),一个阶段即一种类型的事务。每个阶段又可以分为一个或者几个相位(Phase),相位包含几个或者两个事务信息包。不同的传输类型的阶段、相位关系如表 2 所示。

    表 2 传输类型、阶段、相位关系表

     

    信息包是一个区块的固定格式信息,每个信息包由一个信息包标示符(Packet ID,即 PID)开头,作为信息包的识别。根据事务种类的不同,PID 后面可能有端点地址、数据、状态信息,或者是一个帧号码、错误校验位。

    在控制传输、批量传输和中断传输中都有一个相位是联络数据包,它包含的是联络信息。但是联络信号不是仅仅在联络数据包中,有些数据信息包中也包含联络信号。USB 定义的联络信号如下:

    (1)ACK(Acknowledge) 表示主机或者设备已经成功接收数据。

    (2)NAK(Negative Acknowledge) 表示设备在忙中。

    (3)STALL 可以表示 3 种意义,即不支持的控制要求、控制要求失败或者是端点失败。

    (4)NYET(Not Yet) 表示设备是否已准备好接收数据,只有高速设备才会使用。

    (5)ERR(Error) 表示在集线器和主机的事务中,设备没有传回预期的联络信号。ERR只有在高速集线器完成事务分割时才会使用。表 3 所示为在不同的传输事务中所传输的状态码。

    表 3 事务类型与状态码

     

    3)USB 传输的结构

    USB 传输结构描述的是各个类型 USB 传输的时序、数据包和特征。下面分别介绍一下 4 种USB 传输类型的传输结构。

    (1)控制传输

    每一个控制传输都必须有设置与状态阶段,数据阶段则是选择性的。控制传输的设置事务传输结构如图 7 所示。

     

    图 7 控制传输设置事务传输结构示意图

     

    控制传送的数据阶段,由一个以上的输入或输出事务构成,遵守和批处理传送相同的协议规则。所有的数据阶段里的事务都必须有相同的方向(即全部输入或者全部输出)。在数据项中要发送的数据的数量和其方向在建立阶段被指定。如果数据的数量超过了先前确定的数据包大小,数据在支持最大的包大小的多个事务中被发送(输入或者输出)。任何剩下的数据都作为剩余在最后的事务中被发送。图 8 所示描述了控制传输的读/写操作事务顺序。

    图 8 控制传输读/写操作事务顺序图

     

    (2)批量传输

    批量传输包含一个或者多个传输事务,其传输是单方向的,即所有的事务都必须是输入或者输出事务。如果需要双向传数据,需要另建立一个管道。批量传输的传输结构如图 9 所示。

    图 9 批量传输结构示意图

     

    (3)中断传输

    中断传输必须在指定的时间内完成,它一般应用于鼠标、键盘、游戏杆等 HID(HumanInterface Device)类设备以及集线器的状态报表中。中断传输的传输结构如图 10 所示。

     

    图 10 中断传输结构示意图

     

    (4)实时传输

    实时传输的意义在于每一个帧或者微帧内必须传输固定数目的字节数据,它适用于固定速率或者特定时间的传输。实时传输没有联络阶段,所以不能保证传输的完全可靠性。实时传输的传输结构如图 11 所示。

     

    图 11 实时传输结构示意图

     

    对实时传输有两点需要注意:

    • 设备或主机控制器都应该能接收 DATA0 和 DATA1,设备或主机控制器应该只发送 DATA0;

    • 实时传输事务不支持切换时序。

     

     

    3.2 USB 设备检测过程

    1)USB 总线枚举

    USB 规范定义的设备状态总共有 6 个,分别是连接(Attached)、上电(Powered)、默认(Default)、地址(Address)、配置(Configured)和挂起(Suspend)。USB 总线枚举过程中,USB 设备需要经历后 4 个状态,如图 12 所示。

     

    图 12 USB 设备状态转换图

     

    USB 集线器负责监测设备的连接情况,而 USB 主机会通过集线器轮询地查询设备。当主机发现有一个新的设备时,会要求集线器建立与设备的通信通道,即设备的端点 0,控制传输端点。之后,主机会通过此通道向设备发送一系列的标准 USB 请求以获取所需的信息,设备必须响应这些请求并且采取适当的动作。这个过程称为 USB 的总线枚举。设备描述符包含的是设备信息,而 USB 请求是指 USB 主机和设备之间获取特定信息的格式,标准的 USB 请求有 11 个。

    设备枚举的步骤如下:

    • 在主机的 USB 集线器口连接上 USB 设备,主机会首先发出一个获取设备描述符的请求Get_Descriptor(wValue = 0x01)。设备接收到这个主机请求,发送设备描述符,这时由于主机对设备的描述符将有多长实际上都不知道,所以这个步骤只是试探性的。实际上,这时候即使只发送部分设备描述符,主机也会进行下面的步骤。

    • 主机发送设置地址的请求 Set_Address,这时候,设备的地址就是 Set_Address 请求数据包内对应的地址,一般为 02 或 03。

    • 完成地址设置后,主机会再次发送 Get_Descriptor(wValue = 0x01)的请求,读取完整的设备描述符,一般为 18 个字节,如果没有收到正确的设备描述符,主机会再次尝试,总共尝试 3 次。

    • 主机发送获取配置描述符的请求 Get_Descriptor(wValue = 0x02),此时请求的仅仅是配置描述符,总长度为 9 个字节。

    • 主机再次发送获取配置描述符的请求 Get_Descriptor(wValue = 0x02),这次请求的数据长度可能会是 0xFF,这表示主机要求获取所有的配置信息,包括配置描述符、接口描述符和端点描述符,设备应该将以上所有的描述符都发送给主机。

    • 在正确获取到所有配置描述符之后,主机就会开始查找驱动,如果未能搜索到驱动的话,主机系统会提示找到设备但是未找到驱动。

    • 当正确找到驱动后,主机会给设备发送 Set_Configuration 的请求,这样才算是一个设备被正确枚举了。

     

    2)USB 设备的描述符

    标准的 USB 描述符包括设备(Device)描述符、配置(Configuration)描述符、接口(Interface)描述符、端点(Endpoint)描述符以及字符串(String)描述符等。不同的描述符从不同的层级来表示设备的属性。设备描述符包含了整个设备的信息以及设备支持的配置号码,每一个设备只能有一个设备描述符。但每一个设备可以有几个配置描述符,它包含了电源管理信息以及所支持的接口号码。接口描述符包含了与端点通信所需要的信息,它可以有零个或者多个端点描述符。标准 USB 描述符如表 4 所示。

    表 4 标准 USB 描述符表

     

    下面详细介绍一下几个基本描述符的具体格式。

    (1)设备描述符

    设备描述符描述了一个 USB 设备的总体信息,它是枚举过程中主机从设备读取的第一个描述符。设备描述符总共有 18 个字节,分为 14 个字段,如表 5 所示。

    表 5 设备描述符

     

    (2)配置描述符

    配置、接口以及端点描述符都是在主机得到设备描述符之后发送给主机的。配置描述符描述了一个特定的设备配置信息,主机使用 Set_Configuration 请求来选择一个配置,用Get_Configuration 请求来返回一个配置。当主机请求获取一个配置描述符的时候,与配置描述符相关的所有接口、端点描述符都会一并返回。配置描述符由 9 个字节组成,分为 8 个字段,如表 6 所示。

    表 6 配置描述符

     

    (3)接口描述符

    接口描述符描述了一个配置中的特定接口。接口描述符总是作为配置描述符的一部分被返回,主机不能通过 Get_Descriptor 请求直接获取接口描述符。接口描述符由 9 个字节组成,分为 9 个字段,如表 7 所示。

    表 7 接口描述符

     

    (4)端点描述符

    端点描述符包含了主机用来确定一个端点带宽要求的信息。除了端点 0 外,一个接口所使用的每一个端点都有它自己的描述符。端点 0 不需要描述符,它也不能直接由 Get_Descriptor请求来获得。端点描述由 7 个字节组成,分为 6 个字段,如表 8 所示。

    表 8 端点描述符

     

    3)USB 请求

    前文已经介绍了控制传输的结构包括令牌包、数据包和状态包,其中数据阶段的格式如图13 所示。

    图 13 控制传输数据阶段格式

     

    从上图可以看出数据阶段的格式包括一个 PID、一个包含了零个或者多个字节数据的数据字段和一个 CRC 字段。在设置阶段,数据包的数据字段永远是 8 个字节,这时候的数据包传输的就是 USB 请求。8 个字节的 USB 请求分为 5 个字段,如表 9 所示。

    表 9 USB 请求

     

    USB 规范定义了 3 种请求,分别是标准请求(Standard Request)、类请求(Class Request)和厂商请求(Vendor Request)。

    某些设备的功能类似或者提供类似的服务,USB 协议中将它们归为一类,并且定义了特定的请求,称为类请求。例如,集线器设备就已经被 USB 规范定义为一个设备类,它的bDeviceClass 规定为 0x09,它们也用于特定的请求,比如用于获得集线器端口状态信息的Get_Port_Status 请求。

    但是光有类请求是不能满足众多 USB 厂商的需求的,所以,USB 协议允许一个供应商为它的设备自定义特殊的请求,此类请求称为厂商请求。

    USB 规范定了 11 种标准请求,所有设备都必须对这 11 种请求作出响应,即使当主机没有给设备分配一个地址或者没有配置设备。下面详细介绍这 11 种标准请求。

    (1)Clear_Feature

    代码:0x01。

    功能:主机要求禁用设备、接口或者端点上的特征。

    数据:无数据。

    格式:

     

    表 10 标准特征选择表

    说明:wValue 字段根据标准特征选择表定义禁用对象;如果是设备特征,wIndex 字段为0,如果是接口或者端点特征,它表示各自的号码。

     

    (2)Get_Configuration

    代码:0x08。

    功能:主机要求获取目前配置的数值。

    数据:设备到主机,长度 1 字节,为目前的配置的索引。

    格式:

    说明:当前的配置数值作为数据被传送回主机。

     

    (3)Get_Descriptor

    代码:0x06。

    功能:主机要求获取一个描述符。

    数据:设备到主机,所请求获取的描述符的长度。

    格式:

    说明:一个 USB 设备只有一个设备描述符,至少一个配置描述符合接口描述符,如果主机请求获得配置描述符,该配置的所有接口描述符和接口描述符的端点描述符都需要被传送过去。

     

    (4)Get_Interface

    代码:0x0A。

    功能:主机要求获取接口的数值。

    数据:设备到主机,长度 1 字节,当前配置可替换的接口数值。

    格式:

    说明:wIndex 字段是配置描述符中的 bInterface 字段,而数据字段的内容就是当前的配置的 bAlternateInterface。

     

    (5)Get_Status

    代码:0x00。

    功能:主机要求获得一个设备、接口或者端点的状态。

    数据:设备到主机,2 个字节,根据不同的对象表示不同的意义,如表 11、12 和 13所示。

    表 11 设备状态返回数据

     

    表 12 接口状态返回数据

     

    表 13 端点状态返回数据

     

    格式:

    说明:wValue 字段为 0;如果是设备特征,wIndex 字段为 0,如果是接口或者端点特征,它表示各自的号码。

     

    (6)Set_Address

    代码:0x05。

    功能:主机给设备指定一个地址。

    数据:无数据。

    格式:

    说明:设备刚和主机连接时,主机使用地址 0 和设备通信,当正确获取一定信息后,主机会通过 Set_Address 请求给设备分配一个地址,地址的数据就是 wValue 字段。

     

    (7)Set_Configuration

    代码:0x09。

    功能:主机给设备指定一个地址。

    数据:无数据。

    格式:

    说明:设备刚和主机连接时,主机使用地址 0 和设备通信,当正确获取一定信息后,主机会通过 Set_Address 请求给设备分配一个地址,地址的数据就是 wValue 字段。

     

    (8)Set_Descriptor

    代码:0x07。

    功能:主机要求添加一个描述符或者修改一个现有的描述符。

    数据:主机到设备,数据为添加或者修改的描述符。

    格式:

    说明:wIndex 字段高字节是描述符类型(见描述符类型表),低字节是描述符的数值;wIndex 字段在字符串描述符时是语言 ID,其他情况下是 0。

     

    (9)Set_Feature

    代码:0x03。

    功能:主机要求启用一个在设备、接口或者端点上的特征。

    数据:无数据。

    格式:

    说明:wValue 字段根据标准特征选择表定义禁用对象;如果是设备特征,wIndex 字段为0,如果是接口或者端点特征,它表示各自的号码。

     

    (10)Set_Interface

    代码:0x0B。

    功能:主机要求设备使用一个指定的配置。

    数据:无数据格式:

    说明:wIndex 字段是要选择的替代配置描述符中 bInterface 字段的内容,wIndex 字段是接口的号码。

     

    (11)Synch_Frame

    代码:0x0C。

    功能:主机要求设备设置与报告一个端点的同步帧。

    数据:主机到设备,数据为帧的数目。

    格式:

    说明:wIndex 字段是需设置的端点号码,此请求使得主机与端点从某一个帧开始传送重复序列。

     

    四、USB 系统开发

     

    4.1 USB 硬件系统

    按照 USB 体系的定义,USB 硬件系统也可以分为两个部分,即 USB 主机和 USB 设备。其中USB 主机主要包括 CPU 模块(主机 CPU)、USB 主机控制器模块、USB 根集线器模块以及 USB 电源模块组成;而 USB 设备主要由 CPU 模块(设备 CPU)、USB SIE 模块、USB 收发器模块组成,如图 14 所示。

     

    图 14 USB 硬件系统框图

     

    按照功能可以将 USB 接口器件分为 6 类:主机控制器、集线器、USB 接口器件、USB 控制器、USB 电源管理器件以及 USB 特殊功能器件。

    (1)主机控制器

    USB 主机控制器的功能是实现标准的 USB 主机串口引擎(SIE)和根集线器功能,它们一般通过 PCI 或其他总线和主机 CPU 通信。常见的 USB 主机控制器包括 Motorola 的 MPC850,CMD的 USB0670、USB0673,Cypress 公司的 CY7C670xx 等。

    (2)集线器

    USB 集线器实现了 USB 协议所规定的集线器的基本功能,常见的 USB 集线器有 Atmel 的AT43301、AT43311,Intel 的 8x930Hx、8x931Hx,Motorola 的 MC141555、MC141556 等。

    (3)USB 接口器件

    USB 接口器件是开发 USB 设备所需要的扩展 USB 接口的器件,一般包括了 USB SIE 的基本功能以及 USB 数据收发功能。USB 接口器件通过数据地址线、串行总线或者 I/O 口和设备的 CPU相连接。目前比较流行的 USB 接口器件有 Philips 的 PDIUSBD11、PDIUSBD12,National 的USBN9602 以及 ScanLogic 的 SL11、SL16 等。

    (4)USB 控制器

    USB 控制器指的就是带有 USB 接口器件的处理器。原来的 USB 设备都至少需要一个核心处理器和一个 USB 接口器件,但是现在出现的 USB 控制器将两者合二为一,这大大简化了硬件电路的设计,同时也利于降低开发成本。常见的 USB 控制器有 Cypress 的 CY7C63xxx、CY7C64xxx、CY7C65xxx,AMD 的 AM186CC、AM186CU,Intel 的 8x930A,Motorola 的 MC68HC05JB3、MC68HC05JB4等。

    (5)USB 电源管理器件

    每个 USB 集线器需要向下游端口提供+5V/500 mA 的电源,而 USB 电源管理器件就是有效地实现总线电源管理的功能,常见的有 TI 的 TPS2014、TPS2015,Micrel 的 MIC2525、MIC2527 等。

    (6)USB 特殊功能器件

    市场上除了有上面介绍的基本 USB 功能器件外,还有很多芯片厂商提供具有特定功能的USB 器件,例如常见的 USB 鼠标内部就是一个 USB 鼠标控制芯片,其功能就是获取鼠标移动信息并且将数据通过 USB 接口传送到计算机。USB 特殊功能器件种类繁多,在此就不一一介绍了。

     

     

    4.2 USB 接口芯片 PDIUSBD12

    1)PDIUSBD12 简介

    PDIUSBD12 是一款带并行总线、支持本地的 DMA 传输的 USB 接口器件,它通常用在微控制器系统中实现与微控制器进行通信的高速通用并行接口,是一款性价比很高的 USB 器件。PDIUSBD12 完全符合 USB1.1 版的规范,它还符合大多数器件的分类规格:成像类、海量存储器件、通信器件、打印设备以及人机接口设备。同样地,PDIUSBD12 还可以应用于许多设备中,例如打印机、扫描仪、外部的存储设备(Zip 驱动器)和数码相机等。

    PDIUSBD12 芯片的特性如下:

    • 符合通用串行总线 USB 1.1 版规范;

    • 高性能 USB 接口器件,集成了 SIE、FIFO 存储器、收发器以及电压调整器;

    • 符合大多数器件的分类规格;

    • 可与任何外部微控制器/微处理实现高速并行接口,速度达到 2Mbit/s;

    • 完全自治的直接内存存取(DMA)操作;

    • 集成 320 字节多结构 FIFO 存储器;

    • 主端点的双缓冲配置增加了数据吞吐量并轻松实现实时数据传输;

    • 在批量模式和同步模式下均可实现 1Mbit/s 的数据传输速率;

    • 具有良好 EMI 特性的总线供电能力;

    • 在挂起时可控制 LazyClock 输出;

    • 可通过软件控制与 USB 的连接;

    • 采用 GoodLink 技术的连接指示器,在通信时使 LED 闪烁;

    • 可编程的时钟频率输出;

    • 符合 ACPI、OnNOW 和 USB 电源管理的要求;

    • 内部上电复位和低电压复位电路;

    • 有 SO28 和 TSSOP28 封装;

    • 工业级操作温度-40~+85;

    • 高于 8kV 的在片静电防护电路,减少了额外元件的费用;

    • 具有高错误恢复率(>99%)的全扫描设计确保了高品质;

    • 双电源操作,3.3V 或扩展的 5V 电源,范围为 3.6~5.5V;

    • 多中断模式实现批量和同步传输。

     

    PDIUSBD12 的功能框图如图 15 所示。

     

    图 15 PDIUSBD12 的功能框图

     

    PDIUSBD12 功能框图中主要模块的功能如下。

    (1)VOLTAGE REGULATOR

    电压调整器。片内集成了一个 3.3V 的调整器,用于模拟收发器的供电,该电压还作为输出连接到外部 1.5kΩ 的上拉电阻。可选择 PDIUSBD12 提供的带 1.5kΩ 内部上拉电阻的软件连接(SoftConnect)技术。

    (2)SoftConnect

    与 USB 的连接是通过 1.5kΩ 上拉电阻将 D+(用于高速 USB 器件)置为高实现的。1.5kΩ上拉电阻集成在 PDIUSBD12 片内,默认状态下不与 VCC 相连。连接的建立通过外部/系统微控制器发送命令来实现。这就允许系统微控制器在决定与 USB 建立连接之前完成初始化时序。USB总线连接可以重新初始化而不需要拔出电缆。

    (3)ANALOG Tx/Rx

    模拟收发器,集成于芯片内,可通过终端电阻直接与 USB 电缆相连。

    (4)PHILIPS SIEPhilips 

    串行接口引擎,实现了全部的 USB 协议层,并且完全由硬件实现而不需要固件的参与。该模块的功能包括同步模式的识别、并行/串行转换、位填充/解除、填充 CRC 校验/产生、PID 校验/产生、地址识别和握手评估/产生。

    (5)PLL

    片内集成了 6M 到 48M 时钟乘法 PLL(锁相环),这样就可使用低成本的 6MHz 晶振,EMI也随之降低。PLL 的工作不需要外部元件。

    (6)BIT CLOCK RECOVERY

    位时钟恢复电路使用 4 倍过采样规则,从进入的 USB 数据流中恢复时钟。它能跟踪 USB 规定范围内的抖动和频漂。

    (7)GOODLINK

    GoodLink 技术可提供良好的 USB 连接指示,其对应的管脚一般外接一个 LED。在 USB 设备的枚举中,LED 指示根据通信的状况间歇闪烁;当 PDIUSBD12 成功地枚举和配置后,LED 指示将保持点亮一定的时间;之后,当主机与 PDIUSBD12 之间成功的传输(带应答)后,PDIUSBD12将关闭 LED;处于挂起状态时,LED 也会关闭。该特性为 USB 器件、集线器和 USB 通信状态提供了很方便的指示,作为一个诊断工具对设备的隔离故障是很有用的。

    (8)MEMORY MANAGERMENT UNIT(MMU)/INTEGRATED RAM

    在以 12Mbit/s 的速率传输并与微控制器并口相连时,内存管理单元(MMU)和集成 RAM(INTEGRATED RAM)作为 USB 之间速度差异的缓冲区,这就允许微控制器以它自己的速率对 USB信息包进行读写。

    (9)PARALLEL AND DMA INTERFACE

    对一个微控制器而言,PDIUSBD12 看起来就像一个带 8 位数据总线和一个地址位(占用 2 个位置)的存储器件。PDIUSBD12 支持多路复用和非复用的地址和数据总线,还支持主端点与本地共享 RAM 之间单周期模式和突发模式的 DMA 传输。关于 DMA 传输的详细资料,请参考PDIUSBD12 的官方手册。

    除了以上功能外,PDIUSBD12 为了适合多种类型的 USB 设备(例如图像、打印机、海量存储设备和通信设备等),还提供了若干种端点的工作模式,如表 14~18 所示。

    表 14 PDIUSBD12 端点工作模式表

     

    表 15 模式 0 配置情况表

     

    表 16 模式 1 配置情况表

     

    表 17 模式 2 配置情况表

     

    表 18 模式 3 配置情况表

     

    主端点(端点 2)是一个比较特殊的端点,它是进行大数据量传输的主要端点。设置端点工作模式的方法是通过 Set Mode 命令,这将在后面的内容中介绍。

     

    2) PDIUSBD12 硬件连接

    PDIUSBD12 提供了两种封装,即 28 脚塑料 SO 和 28 脚塑料 TSSOP,管脚配置如图 16 所示。

    图 16 PDIUSBD12 的管脚图

     

    以上各个管脚的说明如表 19 所示。

    表 19 PDIUSBD12 管脚说明表

    [注]

    O2:2mA 驱动输出

    OD4:4mA 驱动开漏输出

    OD8:8mA 驱动开漏输出

    IO2:4mA 输出

    O4:4mA 驱动输出

     

    下面以 PDIUSBD12 和 80C51 单片机的连接为例说明一下芯片的连接方法。

    图 17 所示是 PDIUSBD12 和 80C51 单片机的连接示意图,在该例中,ALE 接低电平,表示一个独立的地址和数据总线配置。A0 脚与 80C51 的任意一个 I/O 口相连,该端口控制PDIUSBD12 的命令和数据状态。80C51 的多位地址和数据总线可直接与 PDIUSBD12 的数据总线相连。80C51 的频率输入可由 PDIUSBD12 的 CLKOUT 提供。

     

    图 17 PDIUSBD12 与 80C51 单片机连接示意图

     

    3) PDIUSBD12 控制命令

    PDIUSBD12 能够处理大部分协议层解析的工作,例如 CRC 校验、数据位填充等。所以,开发人员需要做的仅仅是对 PDIUSBD12 进行控制并且按照其数据读写时序实现数据访问。而要对PDIUSBD12 进行控制和数据访问,就需要通过 PDIUSBD12 的控制命令。

    PDIUSBD12 的控制命令是一个 8 位数据,当需要发送一个命令的时候,只需向 A0 输入高电平(表示总线上的是命令),将命令的值输出到 8 位双向总线上,再控制 WR_N 信号产生一个下降沿即可。有些命令是从 PDIUSBD12 读写数据的,这些命令的操作方法一般都是首先读取命令,然后按照数据读写的时序依次读取所需的数据。读取数据的方法和读取命令的方法类似,只不过是向 A0 输入低电平(表示总线上的是数据),再控制 RD_N 信号产生一个下降沿,等待一定的时间之后总线上的数据就是所读取的数据了。PDIUSBD12 读写的时序如图 18 所示。

     

    图 18 PDIUSBD12 总线读写时序

     

    读写的时序还有一点时间上的约束,主要需要注意的是读和写的周期 TRC、TWC 不能小于500ns,详细的参数请读者参考官方的手册。

    PDIUSBD12 的命令大致可以分为下面 3 类:

    • 初始化命令:初始化命令在 USB 网络进行枚举处理的时候使用,用于使能端点的功能,还可以用来设置 USB 分配的地址,其命令如表 20 所示。

    表 20 PDIUSBD12 命令汇总表——初始化命令

     

    • 数据流命令:数据流命令用于管理 USB 端点和外部处理器之间的数据传输,通过外部处理器中断初始化大量的数据流,可以访问和设置端点的缓冲区是否有效,其命令如表 21 所示。

    表 21 PDIUSBD12 命令汇总表——数据流命令

     

    • 普通命令:普通命令用于实现一些基本的辅助功能,其命令如表 22 所示。

    表 22 PDIUSBD12 命令汇总表——普通命令

     

    以上是 PDIUSBD12 控制命令的汇总表,下面就各个命令的功能以及读写数据的格式做一下详细地介绍。

    (1)初始化命令

    • 命令:设置地址/使能。

    编码:D0。

    描述:该命令用于设置 USB 分配的地址和使能功能。

    位分配:如图 19 所示。

     

    图 19 设置地址/使能位分配示意图

     

    说明:如表 23 所示。

    表 23 设置地址/使能位分配说明表

     

    • 命令:设置端点使能。

    编码:D8。

    描述:调用该命令使能端点之前必须先设置地址/使能命令。

    位分配:如图 20 所示。

    图 20 设置端点使能位分配示意图

     

    说明:如表 24 所示。

    表 24 设置端点使能位分配说明表

     

    • 命令:设置模式。

    编码:F3。

    描述:设置模式命令需要在写入命令之后写入两个字节的数据,第一个字节包含配置字节信息,第二个字节是时钟分频因数字节。

    位分配:如图 6-21、6-22 所示。

    图 21 配置字节位分配示意图 

     

    图 22 时钟分频系数位分配示意图

     

    说明:如表 25、26 所示。

    表 25 配置字节位分配说明表

     

    表 26 时钟分频系数位分配说明表

     

    • 命令:设置 DMA。

    编码:FB。

    描述:读写 DMA 配置寄存器。在 DMA 操作中,两个字节的缓冲区头(状态和字节长度信息)不参与传送。这就保证了 DMA 数据的连续性,不用插入信息头。在 DMA 读操作时,信息头会被跳过,直接读取缓冲区命令。在 DMA 些操作时,信息头会自动被添加,这样就提供了一个简洁的 DMA 数据传输。

    位分配:如图 23 所示。

    图 23 设置 DMA 命令位分配示意图

     

    说明:如表 27 所示。

    表 27 设置 DMA 命令位分配说明表

     

    (2)数据流命令

    • 命令:读中断寄存器。

    编码:F4。

    描述:该命令用于读取中断寄存器 1 和中断寄存器 2 的内容。

    位分配:如图 24、25 所示。

     

    图 24 中断寄存器 1 位分配示意图 

     

    图 25 中断寄存器 2 位分配示意图

     

    说明:如表 28、29 所示。

    表 28 中断寄存器 1 位分配说明表

     

    表 29 中断寄存器 2 位分配说明表

     

    • 命令:选择端点。

    编码:00、01、02、03、04、05。

    描述:选择端点,将内部指针指向所选择端点缓冲区的起始位置。该命令返回一个字节(可选)。

    位分配:如图 26 所示。

    图 26 选择端点命令返回字节位分配示意图

     

    说明:如表 30 所示。

    表 30 选择端点命令返回字节位分配说明表

     

    • 命令:读取所选择的端点状态。

    编码:80、81、82、83、84、85。

    描述:读最后处理状态寄存器命令后跟一个数据返回端点最后处理的状态。该命令同时复位中断寄存器中的相应位并将状态清零表示已经读取。由于它保留了每次处理的记录,所以该命令在以调试为目的时很有用。在每次新的处理之后会将原来的状态信息覆盖。

    位分配:如图 27 所示。

    图 27 读取端点状态返回值位分配示意图

     

    说明:如表 31 所示。

    表 31 选择端点命令返回字节位分配说明表

     

    • 命令:设置所选择的端点状态。

    编码:40、41、42、43、44、45。描述:当一个停止控制的端点接收到 SETUP 标志时自动解除停止,而不管信息包的内容如何。如果端点应当停在停止状态,微控制器可以重新停止它。当一个停止的端点解除了停止(设置端点命令或接收到一个 SETUP 标志),它同时被重新初始化。将缓冲区刷新,如果是 OUT 缓冲区就等待一个 DATA 0 PID,如果是 IN 缓冲区就写入一个 DATA 0 PID。即使在解除停止时,将设置端点状态写为 0 也将初始化端点。

    位分配:如图 28 所示。

    图 28 设置端点状态参数位分配示意图

     

    说明:如表 32 所示。

    表 32 设置端点状态参数位分配位分配说明表

     

    • 命令:读取最后处理状态寄存器。

    编码:40、41、42、43、44、45。

    描述:读最后处理状态寄存器命令后跟一个数据返回端点最后处理的状态。该命令同时复位中断寄存器中的相应位并将状态清零表示已经读取。由于它保留了每次处理的记录,所以该命令在以调试为目的时很有用。在每次新的处理之后会将原来的状态信息覆盖。

    位分配:如图 29 所示。

    图 29 读最后处理状态寄存器返回值位分配示意图

     

    说明:如表 33 所示。

    表 33 读最后处理状态寄存器返回值位分配说明表

     

    表 34 读最后处理状态寄存器错误代码表

     

    • 命令:读取所选择端点的缓冲区。

    编码:F0。

    描述:读缓冲区命令返回一系列从选择的端点数据缓冲区读出的数据。每读一个字节,内部缓冲区指针自动加 1。读缓冲区命令不会将缓冲区指针复位到缓冲区起始端。这意味着可被其他的命令所中断(选择端点命令除外)。

    说明:缓冲区的第一个字节是保留的,无效;第二个字节是缓冲区内数据的长度;第三个字节开始才是有效的数据。缓冲区的结构示意图如图 30 所示。

    图 30 缓冲区结构示意图

     

    • 命令:向所选择端点的缓冲区写数据。

    编码:F0。

    描述:写缓冲区命令后跟一系列需要写入端点缓冲区的数据。需要注意的是越过缓冲区边界的写入/读出,写入 OUT 缓冲区或读出 IN 缓冲区都是不受保护的,其中的任何一个都会导致错误的操作。OUT 缓冲区的数据只在成功发送之后才有意义。例外的情况是在主端点的 DMA 操作时,指针在到达边界(双缓冲结构)后会自动指向第二个缓冲区。说明:缓冲区的结构同上。

     

    • 命令:清空所选择的端点的缓冲区。

    编码:F2。

    描述:当一个信息包完全接收之后,内部端点缓冲区满标志置位,所有后续的包将被返回的 NAK 拒绝。当微控制器已读取数据时,它应当通过清缓冲区命令来释放缓冲区。当缓冲区清空之后,新的信息包就可被接收了。

     

    • 命令:使所选择的端点的缓冲区有效。

    编码:FA。

    描述:当微控制器已将数据写入 IN 缓冲区时,它应当通过使缓冲区有效命令设置缓冲区满标志。这表示缓冲区内的数据有效并可在接收到下一个 IN 标志时将其送入主机。

    • 命令:应答所选择的端点。

    编码:F1。

    描述:一个 SETUP 信息包的到达将 IN 缓冲区刷新并禁止对 IN 和 OUT 端点的两条命令——使缓冲区有效和清零缓冲区。微控制器需要通过应答 SETUP 命令重新使能这些命令,这确保了最后的 SETUP 包留在缓冲区内并且在微控制器看到 SETUP 包并应答之前不会有任何包发回主机。微控制器必须将应答 SETUP 命令发送到 IN 和 OUT 端点。

     

    (3)普通命令

    • 命令:发送恢复。

    编码:F6。

    描述:发送一个上行数据流恢复信号 10ms,该命令通常用于器件处于挂起状态时。恢复命令后不跟读出或写入的数据。

     

    • 命令:读取当前帧数目。

    编码:F5。

    描述:该命令后跟 1~2 个读出的字节并返回最后成功接收的 SOF 帧数目。帧数目为返回的低位字节,如图 31 所示。

    图 31 读取当前帧数目命令返回值示意图

     

     

    五、USB 设计实例

     

    5.1 设计需求分析

    本设计的硬件平台是一块带有 PDIUSBD12 接口器件的 FPGA 实验板,操作系统平台是Microsoft Windows XP,开发工具是 ISE (FPGA 固件开发)、Microsoft Visual C++(软件和驱动开发)、Compuware DriverStudio(驱动开发)。

    设计的基本要求是通过 FPGA 芯片控制 USB 芯片,实现实验板和 PC 机之间的 USB 接口数据通信,来模拟一个硬件加密设备的功能。实际应用中硬件加密设备是为软件开发商提供的一种智能型的软件加密工具,包含一个安装在计算机并行口或 USB 口上的硬件,及一套适用于各种语言的接口软件和工具软件,其目的是通过对软件与数据的加密防止知识产权被非法使用。

    本例中系统框图如图 32 所示。要实现一个完整的硬件加密设备的功能非常复杂,而且很多的内容也不是本章节的重点,所以本例中只实现 USB 接口的通信,完成一定的数据传输,而不涉及加密算法等内容。简单地说,本次设计要实现的就是两部分内容——USB 设备的枚举和厂商请求的实现。

     

    图 32 硬件加密设备系统框图

     

     

    5.2 设计方案

    要模拟一个硬件加密系统的工作,至少需要 4 部分的工作,即硬件电路板设计制作、处理器的固件编写、USB 驱动的开发以及 USB 软件的制作,如图 33 所示。

    图 33 硬件加密系统设计方案

     

    设计方案:显然,首先需要完成的是硬件电路板的设计和制作,由于本例是基于已有的FPGA 实验板,所以这部分不在此作介绍。

     

     

    本篇到此结束,下一篇带来基于 FPGA 的 USB 接口控制器设计(VHDL)(下),会介绍FPGA 固件开发,包括固件模块划分、自定义包编写、分频器模块的实现、沿控制模块的实现、输入/输出切换模块的实现、请求处理模块的实现、设备收发器模块的实现、测试平台的编写;USB 驱动和软件开发,包括USB 驱动编写、USB 软件编写以及总结等相关内容。

     

     

    END

     

    后续会持续更新,带来Vivado、 ISE、Quartus II 、candence等安装相关设计教程,学习资源、项目资源、好文推荐等,希望大侠持续关注。

    大侠们,江湖偌大,继续闯荡,愿一切安好,有缘再见!

     

     

     

     

     

    精彩推荐

     

     

     

     

    毕设:基于FPGA的FIR数字滤波器设计

    叁芯智能科技 FPGA开发板,热销中!

    FPGA工程师用了都喜欢的编辑神器—Vs Code

    FPGA工程师高薪就业,9月份开课!

    展开全文
  • USB接口WiFi驱动浅析

    千次阅读 2018-04-11 18:20:20
    前面学习了SDIO接口的WiFi驱动,现在我们来学习一下USB接口的WiFi驱动,二者的区别在于接口不同。而USB接口的设备驱动,我们前面也有学习,比如USB摄像头驱动、USB鼠标驱动,同样都符合LinuxUSB驱动结构: USB设备...

        前面学习了SDIO接口的WiFi驱动,现在我们来学习一下USB接口的WiFi驱动,二者的区别在于接口不同。而USB接口的设备驱动,我们前面也有学习,比如USB摄像头驱动、USB鼠标驱动,同样都符合LinuxUSB驱动结构:


            USB设备驱动(字符设备、块设备、网络设备)

                                                   |

                                            USB 核心

                                                   |

                                  USB主机控制器驱动


            不同之处只是在于USB摄像头驱动是字符设备,而我们今天要学习的WiFi驱动是网络设备;当然由我们编写的部分还是USB设备驱动部分,下面进入USB接口WiFi驱动的分析,如何分析呢?我们下面从这几个方面入手:

            从硬件层面上看,WIFI设备与CPU通信是通过USB接口的与其他WIFI设备之间的通信是通过无线射频(RF)

            从软件层面上看,Linux操作系统要管理WIFI设备,那么就要将WIFI设备挂载到USB总线上,通过USB子系统实现管理。而同时为了对接网络,又将WIFI设备封装成一个网络设备

            我们以USB接口的WIFI模块进行分析:

    a -- 从USB总线的角度去看,它是USB设备;

    b -- 从Linux设备的分类上看,它又是网络设备;

    c -- 从WIFI本身的角度去看,它又有自己独特的功能及属性,因此它又是一个私有的设备;

    通过上述的分析,我们只要抓住这三条线索深入去分析它的驱动源码,整个WIFI驱动框架就会浮现在你眼前。


    一、框架整理

    1、USB设备驱动

          现在我们先从USB设备开始,要写一个USB设备驱动,那么大致步骤如下:

    a -- 需要针对该设备定义一个USB驱动,对应到代码中即定义一个usb_driver结构体变量

    代码如下:

    1. struct usb_driver xxx_usb_wifi_driver;  

    b -- 填充该设备的usb_driver结构体成员变量

    代码如下:

    1. static struct usb_driver xxx_usb_wifi_driver = {  
    2.     .name = "XXX_USB_WIFI",  
    3.     .probe = xxx_probe,  
    4.     .disconnect = xxx_disconnect,  
    5.     .suspend = xxx_suspend,  
    6.     .resume = xxx_resume,  
    7.     .id_table = xxx_table,  
    8. };  

    c -- 将该驱动注册到USB子系统

    代码如下:

    1. usb_register(&xxx_usb_wifi_driver);  

          以上步骤只是一个大致的USB驱动框架流程,而最大和最复杂的工作是填充usb_driver结构体成员变量。以上步骤的主要工作是将USB接口的WIFI设备挂载到USB总线上,以便Linux系统在USB总线上就能够找到该设备。

    2、网络设备驱动

          接下来是网络设备的线索,网络设备驱动大致步骤如下:

    a -- 定义一个net_device结构体变量ndev

    代码如下:

    1. struct net_device *ndev;  

    b -- 初始化ndev变量并分配内存

    代码如下:

    1. ndev=alloc_etherdev();  

    c -- 填充ndev -> netdev_ops结构体成员变量

    代码如下:

    1. static const struct net_device_ops xxx_netdev_ops= {  
    2.     .ndo_init = xxx_ndev_init,  
    3.     .ndo_uninit = xxx _ndev_uninit,  
    4.     .ndo_open = netdev_open,  
    5.     .ndo_stop = netdev_close,  
    6.     .ndo_start_xmit = xxx_xmit_entry,  
    7.     .ndo_set_mac_address = xxx_net_set_mac_address,  
    8.     .ndo_get_stats = xxx_net_get_stats,  
    9.     .ndo_do_ioctl = xxx_ioctl,  
    10. };  

    d -- 填充ndev->wireless_handlers结构体成员变量,该变量是无线扩展功能

    代码如下:

    1. ndev->wireless_handlers = (struct iw_handler_def *)&xxx_handlers_def;  

    e -- 将ndev设备注册到网络子系统

    代码如下:

    1. register_netdev(ndev);  

    3、 WIFI设备本身私有的功能及属性

          如自身的配置及初始化、建立与用户空间的交互接口、自身功能的实现等。

    a -- 自身的配置及初始化

    代码如下:                

    1. xxx_read_chip_info();  
    2.   
    3. xxx_chip_configure();  
    4.   
    5. xxx_hal_init();  

    b -- 主要是在proc和sys文件系统上建立与用户空间的交互接口

    代码如下:

    1. xxx_drv_proc_init();  
    2.   
    3. xxx_ndev_notifier_register();  

    c -- 自身功能的实现

          WIFI的网络及接入原理,如扫描等。同时由于WIFI在移动设备中,相对功耗比较大,因此,对于功耗、电源管理也会在驱动中体现。


    二、USB 设备驱动分析

            在分析之前,我们需要理解在整个wifi模块中,USB充当什么角色?它的作用是什么?实质上wifi模块上的数据传输有两端,一端是wifi芯片与wifi芯片之间,通过无线射频(RF)进行数据传输;另一端则是wifi芯片与CPU之间,通过USB进行数据传输

           了解Linux的USB驱动的读者都知道,USB驱动分为两种:一种是USB主机驱动;另一种是USB设备驱动。而我们的USB接口的wifi模块对于CPU(主机)来说,属于USB设备,因此采用USB设备驱动。

           有了以上信息之后,我们先让Linux系统识别该USB接口的wifi模块,首先我们在驱动源码中大致添加以下几步工作(前面分析过,这里只看步骤,不看代码):

    a -- 定义一个usb_driver结构体变量

    b -- 填充该设备的usb_driver结构体成员变量

    c -- 将该驱动注册到USB子系统

          简单完成以上几步工作,再加上板级文件(arch/mach-xxx.c)对USB设备的支持,Linux的USB子系统几乎可以挂载该wifi模块为USB设备了。但是这并不是我们最终想要的结果。我们还要让Linux系统知道它挂载的USB设备属于无线网络设备,同时能够访问它,利用它实施无线网络的工作

         我们都知道,若要让USB设备真正工作起来,需要对USB设备的4个层次(设备、配置、接口、端点)进行初始化。当然这四个层次并不是一定都要进行初始化,而是根据你的USB设备的功能进行选择的,大致初始化流程如下伪代码:

    1. static struct dvobj_priv *usb_dvobj_init(struct usb_interface *usb_intf)  
    2. {  
    3.     int    i;  
    4.     u8     val8;  
    5.     int    status= _FAIL;  
    6.     struct dvobj_priv *pdvobjpriv;  
    7.   
    8.     //设备  
    9.     struct usb_device *pusbd;  
    10.     struct usb_device_descriptor *pdev_desc;  
    11.   
    12.     //配置  
    13.     struct usb_host_config *phost_conf;  
    14.     struct usb_config_descriptor *pconf_desc;  
    15.   
    16.     //接口  
    17.     struct usb_host_interface *phost_iface;  
    18.     struct usb_interface_descriptor *piface_desc;  
    19.       
    20.     //端点  
    21.     struct usb_host_endpoint *phost_endp;  
    22.     struct usb_endpoint_descriptor *pendp_desc;  
    23.   
    24.   
    25.     //设备的初始化  
    26.     pdvobjpriv->pusbintf = usb_intf ;  
    27.     pusbd =pdvobjpriv->pusbdev = interface_to_usbdev(usb_intf);  
    28.     usb_set_intfdata(usb_intf, pdvobjpriv);  
    29.     pdev_desc =&pusbd->descriptor;  
    30.   
    31.       
    32.     //配置的初始化  
    33.     phost_conf =pusbd->actconfig;  
    34.     pconf_desc =&phost_conf->desc;  
    35.   
    36.    
    37.     //接口的初始化  
    38.     phost_iface =&usb_intf->altsetting[0];  
    39.     piface_desc =&phost_iface->desc;  
    40.   
    41.       
    42.     //端点的初始化,由于wifi模块属于网络设备,传输批量数据,因此需要初始化为批量端点,端点方向(输入、输出)等。同时,由于wifi驱动功能比较多,需要初始化几个输入输出端点。  
    43.     for (i = 0; i <pdvobjpriv->nr_endpoint; i++)  
    44.     {  
    45.         phost_endp = phost_iface->endpoint +i;  
    46.         if (phost_endp)  
    47.         {  
    48.             pendp_desc =&phost_endp->desc;  
    49.   
    50.             //检查是否为输入端点  
    51.             usb_endpoint_is_bulk_in(pendp_desc);  
    52.   
    53.             //检查是否为输出端点  
    54.             usb_endpoint_is_bulk_out(pendp_desc);  
    55.         }  
    56.   
    57.     }  
    58.   
    59.     usb_get_dev(pusbd);  
    60.   
    61. }  

          完成以上的初始化工作之后,接下来我们需要理清一下USB接口的作用,它是wifi芯片内部的固件程序与主机上的Linux系统进行数据通信。USB设备通信不像普通字符设备那样采用I/O内存和I/O端口的访问,而是采用一种称为URB(USB Request Block)的USB请求块,URB在整个USB子系统中,相当于通电设备中的“电波”,USB主机与设备的通信,通过“电波”来传递。下面我们就来编写USB接口的读写操作函数,伪代码如下:

    1. void xxx_wifi_usb_intf_ops(struct _io_ops     *pops)  
    2. {  
    3.     //当需要进行简单数据的读取时,采用以下操作  
    4.     pops->_read8 = &usb_read8;  
    5.     pops->_read16 = &usb_read16;  
    6.     pops->_read32 = &usb_read32;  
    7.   
    8.     //当需要进行批量数据的读取时,采用以下操作  
    9.     pops->_read_port = &usb_read_port;     
    10.   
    11.     //当需要进行简单数据的写时,采用以下操作  
    12.     pops->_write8 = &usb_write8;  
    13.     pops->_write16 = &usb_write16;  
    14.     pops->_write32 = &usb_write32;  
    15.     pops->_writeN = &usb_writeN;  
    16.   
    17.     //当需要进行批量数据的写时,采用以下操作  
    18.     pops->_write_port = &usb_write_port;  
    19.   
    20.     //取消读写urb  
    21.     pops->_read_port_cancel = &usb_read_port_cancel;  
    22.     pops->_write_port_cancel = &usb_write_port_cancel;  
    23.   
    24. }  

             在进行批量数据的读写时,如usb_read_port()和usb_write_port()函数,需要完成urb创建、初始化、提交、完成处理这个完整的流程。伪代码如下:

    1)批量读操作

    1. static u32 usb_read_port(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *rmem)  
    2. {         
    3.     int err;  
    4.     unsigned intpipe;  
    5.     PURB purb =NULL;  
    6.     structrecv_buf         *precvbuf = (structrecv_buf *)rmem;  
    7.     structusb_device    *pusbd = pdvobj->pusbdev;  
    8.   
    9.     //创建urb,这里是在其它地方创建完成之后,传递过来  
    10.     purb =precvbuf->purb;  
    11.   
    12.     //初始化批量urb  
    13.     usb_fill_bulk_urb(purb, pusbd, pipe,  
    14.         precvbuf->pbuf,  
    15.         MAX_RECVBUF_SZ,  
    16.         usb_read_port_complete,  
    17.         precvbuf);//contextis precvbuf  
    18.       
    19.     //提交urb  
    20.     err =usb_submit_urb(purb, GFP_ATOMIC);  
    21.   
    22. }  

    2)批量写操作

    1. u32 usb_write_port(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *wmem)  
    2. {     
    3.     unsigned int pipe;  
    4.     intstatus;  
    5.     PURB        purb = NULL;  
    6.   
    7.     structxmit_priv       *pxmitpriv =&padapter->xmitpriv;  
    8.     structxmit_buf *pxmitbuf = (struct xmit_buf *)wmem;  
    9.     structxmit_frame *pxmitframe = (struct xmit_frame *)pxmitbuf->priv_data;  
    10.     structusb_device *pusbd = pdvobj->pusbdev;  
    11.     structpkt_attrib *pattrib = &pxmitframe->attrib;  
    12.   
    13.     //创建urb,这里是在其它地方创建完成之后,传递过来  
    14.      purb = pxmitbuf->pxmit_urb[0];  
    15.   
    16.     //初始化批量urb  
    17.     usb_fill_bulk_urb(purb, pusbd, pipe,  
    18.         pxmitframe->buf_addr,//= pxmitbuf->pbuf  
    19.         cnt,  
    20.         usb_write_port_complete,  
    21.         pxmitbuf);//contextis pxmitbuf  
    22.   
    23.     //提交urb  
    24.     status = usb_submit_urb(purb,GFP_ATOMIC);  
    25.   
    26.     return ret;  
    27.   
    28. }  

            完成以上批量数据的读写操作之后,大家可能会疑问:这不是一般USB设备驱动的操作流程吗?貌似和wifi没有半毛钱的关系啊!从上面看,确实和wifi没有任何联系,但是以上只是一个铺垫。我们一直强调USB接口在wifi模块中充当什么角色,既然是接口,那么它就是为数据传输而生。所以,和wifi扯上关系的就在于usb_read_port()usb_write_port()这两个函数。


    三、读写函数分析

           USB接口在wifi模块中的最重要两个函数是usb_read_port()和usb_write_port()。那它们是怎么和wifi扯上关系的呢?我们可以从以下三个方面去分析:

    a -- 首先需要明确wifi模块是USB设备,主控(CPU)端是USB主机;

    b -- USB主机若需要对wifi模块进行数据的读写时,就必须经过USB接口;

    c -- 既然涉及到数据的读写操作,必然要用相应的读写函数,那么usb_read_port()和usb_write_port()即是它们的读写函数。


           我们先从读数据开始进行分析,在分析之前,我们必须了解USB设备驱动的读数据过程。USB读取数据操作流程如下:

    a -- 通过usb_alloc_urb()函数创建并分配一个URB,作为传输USB数据的载体;

    b -- 创建并分配DMA缓冲区,以DMA方式快速传输数据;

    c -- 初始化URB,根据wifi的传输数据量,我们需要初始化为批量URB,相应操作函数为usb_fill_bulk_urb();

    d -- 将URB提交到USB核心;

    e -- 提交成功后,URB的完成函数将被USB核心调用。

            我们知道只有当wifi模块有数据可读时,主控端才能成功地读取数据。那么wifi模块什么时候有数据可读呢?——下面重点来了!wifi模块通过RF端接收到无线网络数据,然后缓存到wifi芯片的RAM中,此时,wifi模块就有数据可读了

           经过上面的分析,我们找到了一条USB接口与wifi模块扯上关系的线索,就是wifi模块的接收数据,会引发USB接口的读数据;

          现在,我们转到wifi模块的接收函数中,看看是不是真的这样?

          在wifi接收函数初始化中,我们可以看到usb_alloc_urb()创建一个中断URB。伪代码如下:

    1. int xxxwifi_init_recv(_adapter *padapter)    
    2. {    
    3.     struct recv_priv *precvpriv = &padapter->recvpriv;    
    4.     int i, res = _SUCCESS;    
    5.     struct recv_buf *precvbuf;    
    6.     
    7.     tasklet_init(&precvpriv->recv_tasklet, (void(*)(unsigned long))rtl8188eu_recv_tasklet, (unsigned long)padapter);    
    8.     
    9.     precvpriv->int_in_urb = usb_alloc_urb(0, GFP_KERNEL); //创建一个中断URB    
    10.     
    11.     precvpriv->int_in_buf = rtw_zmalloc(INTERRUPT_MSG_FORMAT_LEN);    
    12.     //init recv_buf    
    13.     _rtw_init_queue(&precvpriv->free_recv_buf_queue);    
    14.     _rtw_init_queue(&precvpriv->recv_buf_pending_queue);    
    15.     
    16.     precvpriv -> pallocated_recv_buf = rtw_zmalloc(NR_RECVBUFF *sizeof(struct recv_buf) + 4);    
    17.     precvbuf = (struct recv_buf*)precvpriv->precv_buf;    
    18.     
    19.     for(i=0; i < NR_RECVBUFF ; i++)    
    20.     {    
    21.         _rtw_init_listhead(&precvbuf->list);    
    22.         _rtw_spinlock_init(&precvbuf->recvbuf_lock);    
    23.         precvbuf->alloc_sz = MAX_RECVBUF_SZ;    
    24.     
    25.         res = rtw_os_recvbuf_resource_alloc(padapter, precvbuf);    
    26.     
    27.         precvbuf->ref_cnt = 0;    
    28.         precvbuf->adapter =padapter;    
    29.         precvbuf++;    
    30.     }    
    31.     precvpriv->free_recv_buf_queue_cnt = NR_RECVBUFF;    
    32.     
    33.     skb_queue_head_init(&precvpriv->rx_skb_queue);    
    34.     
    35. #ifdef CONFIG_PREALLOC_RECV_SKB    
    36.     {    
    37.         int i;    
    38.         SIZE_PTR tmpaddr=0;    
    39.         SIZE_PTR alignment=0;    
    40.         struct sk_buff *pskb=NULL;    
    41.         skb_queue_head_init(&precvpriv->free_recv_skb_queue);    
    42.         for(i=0; i<NR_PREALLOC_RECV_SKB; i++)    
    43.         {    
    44.             pskb = rtw_skb_alloc(MAX_RECVBUF_SZ + RECVBUFF_ALIGN_SZ);    
    45.             if(pskb)    
    46.             {    
    47.                 pskb->dev = padapter->pnetdev;    
    48.                 tmpaddr = (SIZE_PTR)pskb->data;    
    49.                 alignment = tmpaddr & (RECVBUFF_ALIGN_SZ-1);    
    50.                 skb_reserve(pskb, (RECVBUFF_ALIGN_SZ - alignment));    
    51.                 skb_queue_tail(&precvpriv->free_recv_skb_queue, pskb);    
    52.             }    
    53.             pskb=NULL;    
    54.         }    
    55.     }    
    56. #endif    
    57.     return res;    
    58. }    

     在rtw_os_recvbuf_resource_alloc函数中,创建一个批量URB和一个DMA缓冲区。伪代码如下:

    1. int rtw_os_recvbuf_resource_alloc(_adapter *padapter, struct recv_buf *precvbuf)    
    2. {    
    3.     int res=_SUCCESS;    
    4.     struct dvobj_priv   *pdvobjpriv = adapter_to_dvobj(padapter);    
    5.     struct usb_device   *pusbd = pdvobjpriv->pusbdev;    
    6.     
    7.     precvbuf->irp_pending = _FALSE;    
    8.     precvbuf->purb = usb_alloc_urb(0, GFP_KERNEL); //创建一个批量URB    
    9.     
    10.     precvbuf->pskb = NULL;    
    11.     precvbuf->reuse = _FALSE;    
    12.     precvbuf->pallocated_buf  = precvbuf->pbuf = NULL;    
    13.     precvbuf->pdata = precvbuf->phead = precvbuf->ptail = precvbuf->pend = NULL;    
    14.     precvbuf->transfer_len = 0;    
    15.     precvbuf->len = 0;    
    16.     
    17.     #ifdef CONFIG_USE_USB_BUFFER_ALLOC_RX    
    18.     precvbuf->pallocated_buf = rtw_usb_buffer_alloc(pusbd, (size_t)precvbuf->alloc_sz, &precvbuf->dma_transfer_addr);  //创建一个DMA缓冲区    
    19.     precvbuf->pbuf = precvbuf->pallocated_buf;    
    20.     if(precvbuf->pallocated_buf == NULL)    
    21.         return _FAIL;    
    22.     #endif //CONFIG_USE_USB_BUFFER_ALLOC_RX    
    23.         
    24.     return res;    
    25. }    

          在usb_read_port()函数中,通过usb_fill_bulk_urb()初始化批量URB,并且提交给USB核心,也即USB读取数据操作流程的第3、4步。在usb_fill_bulk_urb()函数中,初始化URB的完成函数usb_read_port_complete(),只有当URB提交完成后,函数usb_read_port_complete()将被调用。伪代码如下:

    1. static u32 usb_read_port(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *rmem)    
    2. {       
    3.     struct recv_buf *precvbuf = (struct recv_buf *)rmem;    
    4.     _adapter        *adapter = pintfhdl->padapter;    
    5.     struct dvobj_priv   *pdvobj = adapter_to_dvobj(adapter);    
    6.     struct pwrctrl_priv *pwrctl = dvobj_to_pwrctl(pdvobj);    
    7.     struct recv_priv    *precvpriv = &adapter->recvpriv;    
    8.     struct usb_device   *pusbd = pdvobj->pusbdev;    
    9.     
    10.     rtl8188eu_init_recvbuf(adapter, precvbuf);          
    11.     
    12.     precvpriv->rx_pending_cnt++;    
    13.     
    14.     purb = precvbuf->purb;    
    15.     
    16.     //translate DMA FIFO addr to pipehandle    
    17.     pipe = ffaddr2pipehdl(pdvobj, addr);    
    18.     
    19.     usb_fill_bulk_urb(purb, pusbd, pipe,     
    20.                     precvbuf->pbuf,    
    21.                             MAX_RECVBUF_SZ,    
    22.                             usb_read_port_complete,    
    23.                             precvbuf);//context is precvbuf    
    24.     
    25.     err = usb_submit_urb(purb, GFP_ATOMIC);    
    26.     
    27.     return ret;    
    28. }    
         通过上面的代码,我们可以得知在wifi模块为接收数据做初始化准备时,分配了URB和DMA缓冲区。而在usb_read_port()函数中初始化URB和提交URB。

    致谢

    1、USB接口WiFi驱动浅析




    展开全文
  • 树莓派ZERO体积小巧,奈何代价就是USB口只有一个而且还是micro usb规格,我要接鼠标键盘,我要上网,咋整? 解决方案一:Zero的需要找一条USB OTG线,把他转成type A 母...3个USB扩展口,兼容USB2.0/1.1传输。 1个RJ

    树莓派ZERO体积小巧,奈何代价就是USB口只有一个而且还是micro usb规格,我要接鼠标键盘,我要上网,咋整?

    解决方案一:Zero的需要找一条USB OTG线,把他转成type A 母口【有A口的版本忽略这步】,然后再找一个通用的USB HUB,再接上你要的键盘鼠标,USB网卡等等。

    缺点就是接线麻烦,一堆的线。

    解决方案二:使用Waveshare研发的ETH/USB HUB HAT集成了以太网口和USB集线器的树莓派扩展板:

    • 3个USB扩展口,兼容USB2.0/1.1传输。
    • 1个RJ45网口采用RTL8152B以太网芯片, 10/100M自适应。
    • 板载多个指示灯,方便查看电源、网口和USB扩展接口的工作状态。

     

     

    这样就整齐简洁很多了。免驱的,即插即用。

    还有就是除了ZERO能用其他版本的树莓派都能用,例如树莓派3B/3B+/4B都可以。还可以接Windows系统的电脑。

    如果你是用树莓派4B【即Raspberry Pi 4 Model B】,

    这时你又需要多个USB3.0的口【板载只有2个】,可以用USB 3.2 Gen1 HUB HAT微雪这个产品扩展出4个USB 3.2 Gen1 .

    基于 Raspberry Pi 40PIN 接口设计,适用于莓派系列主板。

    • 免驱动,即插即用,兼容 Windows、mac OS、Linux 和 Android 等系统
    展开全文
  • 1.手机USB接口通信特点 - 1.1 使用方便 - 1.2 通用性强 - 1.3 速度快 - 1.4 可采用总线供电 2. 手机USB接口通信原理 - 2.1 常见手机USB接口 - 2.2 通信过程 - 2.3 体系架构 2.4软件层次 3. 手机USB接口与...
  • USB接口介绍

    千次阅读 2010-08-26 10:03:00
    网上找的个人认为比较有用的资料,和大家共享 第1章 USB通信 3.1 USB概述 USB是英语“Universal Serial ...目前主要有USB1.1和USB2.0两版本,USB1.1支持1.5Mb/s的低速传输和12Mb/s的全速传输
  • Windows下usb接口驱动技术

    千次阅读 2019-08-16 09:57:38
    一、USB概述 USB的英文全称为Universal Serial Bus,中文含义是通用串行总线,是由Conpaq、DEC、IBM、Inter、Microsoft、NEC和Northen Telecom等公司为简化PC与外设之间...现在生产的PC几乎都配备了USB接口,Micros...
  • USB接口的数字摄像系统设计作者:佚名 文章来源:西安电子科技大学电器CAD所 点击数: ...USB总线具有时分复用的特点,多个不同速度的USB外设可以通过集线同时连接到同一台计算机的同一个USB口上,在USB总线带宽允
  • 我们在使用电脑的时候,经常会用到电脑的USB接口,因为有很多USB接口的设备会连接电脑。但是当我们的电脑提示USB接口供电不足,那么我们应该怎么解决这样的问题呢?一起来看看吧。 一般来说,USB设备插入到...
  • USB接口技术分析及电路设计

    千次阅读 2011-07-12 12:38:56
    USB接口使用方便,它可以连接多个不同的设备,而过去的串口和并口只能接一个设备。速度快是USB技术的突出特点之一。全速USB接口的最高传输率可达12Mb/s,比串口快了整整100倍,而执行USB2.0标准的高速USB接口速率更是...
  • USB接口芯片汇总(转)

    千次阅读 2013-02-20 09:53:53
    USB接口芯片汇总(转)  2011-05-05 13:33:59| 分类: 电脑技术|字号 订阅 ...USB接口功能的芯片很,主要分为3大类。 第1类是需要外接微处理的USB芯片。例如朗讯的USS820/825、松下的USBN9602/ USBN
  • 很多人用过USB3.0扩展坞,用于扩展便携笔记本电脑接口。USB3.0的带宽足以胜任大部分使用场合,例如数据拷贝、视频信号传输、USB千兆网络以及读卡等。 很厂商都推出了USB3.0...DisplayLink是一通过USB接口实现
  • Windows下usb接口驱动技术(一)

    千次阅读 2013-01-18 17:56:25
    Windows下usb接口芯片的驱动技术 一、 USB概述   USB的英文全称为Universal Serial Bus,中文含义是通用串行总线,是由Conpaq、DEC、IBM、Inter、Microsoft、NEC和Northen Telecom等公司为简化PC与外设之间的...
  • Linux 下wifi 驱动开发(四)—— USB接口WiFi驱动浅析

    万次阅读 多人点赞 2016-04-10 21:33:08
    前面学习了SDIO接口的WiFi驱动,现在我们来学习一下USB接口的WiFi驱动,二者的区别在于接口不同。而USB接口的设备驱动,我们前面也有学习,比如USB摄像头驱动、USB鼠标驱动,同样都符合LinuxUSB驱动结构:  USB设备...
  • PS/2鼠标自己动手改USB接口

    千次阅读 2013-07-12 10:50:46
    USB作为电脑外设的一种高速连接标准,目前已广泛应用到了各种外部设备上。...键盘上这种体贴的设计让我等用户羡慕不已,我们能不能自己动手让普通键盘也能拥有一个USB接口呢? 答案当然是肯定的。由于键盘与
  • 而传统串行通信标准的数据传输率比较低,在使用上也很不方便,特别是双向通信能力和多接口扩展能力非常有限。因此,为满足数量众多、种类不一的计算机外设的数据传输需求,业界鱼待一种新的接口方案来解决上述问题。...
  • 通用串行总线控制总是有叹号解决办法 ...并在控制面板发现:通用串行总线控制总是感叹号,插入外设时USB无反应。如图:​ 并且右键选中其中一,点击最后一选项:“属性” 可以发现“设备状态”中会提示“由...
  • USB通信接口介绍

    万次阅读 2018-11-09 10:55:15
    1. 概述 ...一个USB系统中仅有一个USB主机,设备包括功能设备和hub,最多支持127个设备。 由于USB是主从模式的结构,设备与设备之间、主机与主机之间不能互连,为解决这个问题,扩大USB的应用...
  • 五种方法限制计算机禁用USB接口

    千次阅读 2012-07-10 18:17:24
    那么,我们为什么要禁用USB接口啊? 原因太了,如果您在公用办公室上班,那么您就惨洛,会莫名其妙的有一大堆人来使用您的电脑,您所使用的计算机,就像被“千人压、万人骑”,插一次,有80%的概率会导致计算机...
  • USB接口在周边的电子产品中非常普遍,其良好的统一性、广泛性等特点已成为电子产品的标配接口。所以越来越的MCU上将其集成为外设便于产品应用开发。 下面我们来简单对比 2款常用的MCU产品自身USB资源差异: (1) 中...
  • 报表描述符和 USB 的其他描述符是不一样的,它不是一简单的表格, 报表描述符是 USB 所有描述符中最复杂的 。报表描述符非常复杂而有弹性,因为它需要处理各种用途的设备。报表的数据必须以简洁的格式来储存,这样...
  • 传统的数据采集系统以ISA,EISA或PCI插卡的形式完成数据传输,这种方式存在安装麻烦,受计算机插槽数量、地址、中断资源限制,可扩展性差等缺点。由于通用串行总线(Universal Serial Bus.USB)具有自动被系统识别...
  • mini2440 usb 扩展的问题

    千次阅读 2012-08-21 17:28:41
    我在mini2440外面扩展个usb hub,我目前有三种usb设备,鼠标、U盘、自己用ch375开发的一个usb板子,这三种设备任意两种组合,wince都可以认出,工作正常,再插入第三种设备,提示我加驱动程序,我的都是标准接口,...
  • 个USB HUB电路分享

    千次阅读 2020-04-30 12:00:28
    当USB接口不够用的时候,可以采用USB HUB电路进行扩展,将一个USB接口扩展多个,并可以使这些接口同时使用的装置。USB HUB根据所属USB协议可分为USB2.0 HUB、USB3.0 HUB与USB3.1 HUB。 选用的USB HUB芯片为 USB...
  • 本文为主要是讲解USB TYPE-C转HDMI +PD+USB3.0/USB3.1扩展坞设计方案和设计参考电路。此功能的实现主要是依用台湾安格AG9311MCQ芯片来设计的。首先我们从AG9311MCQ的性能和参数特性,以及封装方式和管脚描述,设计...
  • 一般的电子设备都是用TTL,一些通信方式如RS232、RS485、USB等在传输线上使用差分信号(一般两信号线的差大于2~6V为逻辑1,小于为逻辑0)进行传输(这样的好处是能够有效抑制共模干扰),因此这些通信线上的信号在...
  • 基于VC的USB接口通信程序设计

    千次阅读 2008-07-21 15:15:00
    而在早期的计算机系统上通常使用串口或并口来发送数据,每个接口都需要占用计算机内部很的资源,传统的接口一般采用PCI总线或RS-232串行总线。PCI总线有较高的传输速率,可达132 Mbit/s,也可以即插即用,但是...
  • 针对这一命题,我们选择一款芯片AG9321MCQ来实现设计,且这款方案是Algoltek安格科技 在2020年针对USB TYPE-C扩展坞和USB TYPE-CUSB扩展器市场需求下,新开发的集成性和低成本BOM方案。目前这款方案设计出的产品分别...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 26,810
精华内容 10,724
关键字:

多个usb接口扩展器