1.写在前面

系列文章(一)到(十一)应该是总分的结构,最开始大致写明我要写的内容,后面将每一个点拆解出来作为一篇。本篇所要讲述的内容是基于Cyusb3014实现控制传输的原理,要求比较高,硬是从写文结构上拆解,应该属于“总”的内容。读者应至少对前十一节的内容有所了解,否则很可能通读全文仍不知所云。当然还有一种情况是,前面的内容相对独立,很难在他们之间建立起联系,在脑海中形成自己的框架。上述两种情况,都应该仔细阅读本篇,相信会有醍醐灌顶,茅塞顿开恍然大悟豁然开朗的感觉。

控制传输实现的原理涉及了比较多的内容,读文之前,应对以下文章比较熟悉。“(四)USB原理之一连接建立”“(五)USB原理之二标准请求、传输”“(九)Cyusb3014芯片原理之一数据流”“(十)Cyusb3014芯片原理之二代码流程”。在此过程中明确控制传输有什么特点,传输过程分为哪几个阶段,事务、包、域的概念,并由此产生疑问:如何发起控制传输,控制传输的数据是如何打包的?发起控制传输后,固件中的代码是如何处理呢,怎样将其转发到FPGA端呢?FPGA端接收控制传输数据与AN65974接收Bulk传输数据有何异同?带着这些疑问,且听我的叙述。

2.控制传输原理

2.1USB命令

应该知道,USB传输模型中,所有的传输都是由主机发起,从设备被动响应,当然对于控制传输也不例外。但是不同于Bulk传输、中断传输、Iso传输,控制传输需要传递参数。可以看到,在USB连接建立阶段进行描述符枚举过程(进行控制传输),期间会发送很多标准请求。这些标准请求都属于USB命令的一部分,除了标准请求,还有类请求,厂商请求。不同的命令虽然有不同的数据和使用目的,但所有的USB命令结构是一样的。下表所示为USB命令的结构(偏移量低的先发送)。一共5个字段,不同字段含义不同,相互间不同的组合形成了不同的USB命令,其中包含了11个标准命令。厂商请求便是用于自定义控制传输的,现在应该明确,发起控制传输时,应携带参数(USB命令),具体应该打包一个厂商请求的命令帧。

2.2看不见的数据包

USB协议之所以庞杂,是因为替用户做了很多它“力所能及”的事情,例如数据打包的过程用户完全不可见,对于具体的实现USB的芯片Cyusb3014来说,该芯片做了一部分我们看不见的工作,USB也做了看不见的工作(具体是由USB驱动程序和操作系统完成)。前面的文章中介绍了事务、包、域的概念,前面提及,包(Packet)是USB系统中信息传输的基本单元(请始终记得这句话),所有数据都是经过打包后在总线上传输的。对于此处的USB命令也不例外,也是打包成包进行传输的。具体怎么回事,从控制传输过程的三个阶段聊起。

如下图所示,控制传输过程是分为了三个传输阶段,建立阶段(令牌阶段)、数据传送阶段、握手阶段。当主机发起控制传输时,此为建立阶段,或称为Setup事务。Setup事务与所有事务类型一样是由包(Package)组成的,包有多种类型,具体Setup事务是由令牌包中的Setup包、数据包、以及握手包组成。不同的包是由域字段中的标识域字段标识的。

对于USB命令,正是在Setup事务阶段完成打包的,Setup事务中的数据包中包含了“自定义的厂商请求命令”,在其中规定了控制传输内容,方向等(即USB命令中的5个字段)。那么需要传输的用户数据,则是在控制传输的第二阶段,数据阶段完成的。也就是说控制传输的参数在第一阶段(建立阶段)的Setup事务中的数据包中打包,而控制传输数据是在第二阶段数据传输阶段进行的。

2.3QT与FPGA端

首先需要指出,对于FPGA端来说,接收控制传输和Bulk传输的数据并无差别。主要取决于固件程序如何将数据转出,本次使用的方法,对于FPGA端的操作没有影响。

对于Qt端,发起控制传输和Bulk传输确有不同,关于二者的区别,后续讲到Qt篇的时候将会仔细说明,现在为了结构的完整性,一笔带过。需要在此说明的是,Cypress提供的库cyapi.lib中使用控制端点类中的六个成员属性,来下发配置USB命令中5个字段的具体值,具体是Target、ReqType、Direction、ReqCode、Value、 Index。 也就是说,我们只需要给这五个成员属性赋值,cyapi.lib帮我们完成命令的编码。

2.4固件中控制传输

① CyU3PUsbRegisterSetupCallback(CyFxSlFifoApplnUSBSetupCB, CyTrue);

/* The fast enumeration is the easiest way to setup a USB connection,* where all enumeration phase is handled by the library. Only the* class / vendor requests need to be handled by the application. *//* This function is used to register a USB setup request handler with the USB driver. The fastEnum parameter specifies whether this setup handler should be used only for unknown setup requests or for all USB setup requests.*/

该函数是一个回调函数,当有request从主机来的时候进入此函数。当设置第二个参数Cyture代表选择fast enumeration模式,这个模式是指库函数将会为你处理一些请求如标准请求,你需要处理的是类/厂商请求。第一个参数则指定了一个入口函数地址,当有类、厂商或者不认识的请求来的时候指定进入此函数地址进行处理。

CyFxSlFifoApplnUSBSetupCB(uint32_t setupdat0,uint32_t setupdat1) 

/* Callback to handle the USB setup requests. */

该函数是指定的USB请求处理入口,这两个参数中的值代表了USB命令中5个字段的值,具体怎么对应,将在第3小节控制传输的实现中讲到。将在这个函数执行获取控制传输数据的操作。

CyU3PUsbGetEP0Data(uint16_t count,uint8_t *buffer,uint16_t *readCount);

/*This function is used to get the OUT data associated with a USB controltransfer. */Count //The length of data to be read in bytesBuffer //Pointer to buffer where the data should be placedreadCount //Output parameter which will be filled with the actual size of data

该函数将EP0端点的主机OUT数据写入指定的内存空间中,即buffer中,返回实际写入值readCount。需要说明的是,当要写回In数据到主机的时候,用到CyU3PUsbSendEP0Data函数。

CyU3PDmaChannelSetupSendBuffer (

CyU3PDmaChannel *handle,   //< Handle to the DMA channel to be modified.

CyU3PDmaBuffer_t *buffer_p //< Pointer to structure containing address, size and status of the DMA buffer to be sent out. */);

/*This function initiates the sending of the content of a user provided buffer to the consumer of a DMA channel.*/

该函数将把指定内存空间中的数据传输到指定的DMA通道上,在使用DMA通道之前,应该先用CyU3PDmaBufferAlloc函数创建一条方向明确的DMA通道。进行发送操作后调用CyU3PDmaChannelWaitForCompletion函数阻塞等待传输完成。

阅读此小节,请结合数据流中的内容。使用以上1-4函数可以实现收到USB的请求并交给指定函数处理,那么在此处理函数中,可以将控制传输中的数据写入到指定的内存空间中,然后在把该内存空间中的数据转发到指定的DMA通道上,即可完成控制传输从发起到接收、转发在到FPGA的端到端的操作。结合上图,理解为什么选择使用函数④,也就是从指定空间转发到指定DMA通道上面。可以看到,从DMA缓冲区往左也就是数据从缓冲区到GPIF II与之前一样,使用自动DMA通道即可完成,因此FPGA端数据接收不受任何影响。那么对于数据流左侧则完全不一样了,数据从USB总线到了内存中,再由内存到DMA通道,因此DMA通道,缓冲区的大小,UIB套接字等都需要与上图不同的配置才能实现数据流通路。具体配置请看下一小节3.控制传输的实现。

3.控制传输的实现

(1)首先,从上位机先要发起请求命令,这个请求命令通常是伴随发送(接收)函数一起下发的。使用Qt开发或者自带的上位机软件Control Center均可以实现这个功能,后续Qt篇会介绍细节。

(2)固件中控制传输的实现基于AN65974做修改

①固件程序使用回调机制响应控制请求,在AN65974的工程中,CyFxSlFifoApplnInit函数中调用了回调函数CyU3PUsbRegisterSetupCallback并指定回调处理函数的入口为CyBool_t CyFxSlFifoApplnUSBSetupCB,当上位机下发命令请求时,自动进入这个函数。

②在CyFxSlFifoApplnUSBSetupCB函数之前,应做以下准备工作。

第一,自定义请求类型bType。

                        #define JY_DE_CODE_TYPE   (0xB0)

第二,在栈区声明一段内存空间,用于存储控制传输数据。

uint8_t jyEp0Buffer[32];

第三,在函数CyFxSlFifoApplnStart创建DMA手动通道,用于将数据

//DMA通道为控制传输创建CyU3PMemSet ((uint8_t *)&dmaCfg, 0, sizeof(dmaCfg));dmaCfg.size  = 32;//缓冲区大小为32BdmaCfg.count = 1;//缓冲区个数为1dmaCfg.prodSckId = CY_U3P_CPU_SOCKET_PROD;//此通道生产者是CPU套接字dmaCfg.consSckId =CY_FX_CONSUMER_PPORT_SOCKET;//通道消费者是UIB套接字dmaCfg.dmaMode = CY_U3P_DMA_MODE_BYTE;dmaCfg.notification = 0;dmaCfg.cb = NULL;dmaCfg.prodHeader = 0;dmaCfg.prodFooter = 0;dmaCfg.consHeader = 0;dmaCfg.prodAvailCount = 0;apiRetStatus = CyU3PDmaChannelCreate (&glChHandleSlFifoUtoP,CY_U3P_DMA_TYPE_MANUAL_OUT, &dmaCfg);//因需CPU参与数据处理,故创建手动DMA通道

③在CyFxSlFifoApplnUSBSetupCB函数中做以下几件事。

第一,获取USB厂商请求的五个字段,代码如下,以此分辨用户发起的控制传输。

 /* Decode the fields from the setup request. */bReqType = (setupdat0 & CY_U3P_USB_REQUEST_TYPE_MASK);bType    = (bReqType & CY_U3P_USB_TYPE_MASK);bTarget  = (bReqType & CY_U3P_USB_TARGET_MASK);bRequest = ((setupdat0 & CY_U3P_USB_REQUEST_MASK) >> CY_U3P_USB_REQUEST_POS);wValue   = ((setupdat0 & CY_U3P_USB_VALUE_MASK)   >> CY_U3P_USB_VALUE_POS);wIndex   = ((setupdat1 & CY_U3P_USB_INDEX_MASK)   >> CY_U3P_USB_INDEX_POS);
  • 第二,识别自定义控制传输,并获取控制传输数据到指定的内存空间,并将此空间中的数据转发到指定的DMA通道上。
/***************响应自定义控制请求代码************************/if(bType==CY_U3P_USB_VENDOR_RQT){isHandled = CyTrue;if(bRequest==JY_DE_CODE_TYPE){CyU3PUsbGetEP0Data(wLength, &jcEp0Buffer, readout);//获取wLength字节个数据到jcEp0Buffer中CyFxaaa(jyEp0Buffer);//my definedCyU3PUsbAckSetup ();}}

④第③步实现了从指定内存中转发数据到DMA通道上函数的调用,下面补充该函数的实现。

/*************自定义函数 完成DMA从buffer到套接字的传输***************/void CyFxaaa(uint8_t  *buffer){CyU3PDmaBuffer_t buf_p;//用于串口调试打印的状态变量,起到了关键作用CyU3PReturnStatus_t Info_Debug=CY_U3P_SUCCESS;buf_p.size = 0x20;    //这里是16进制值 需要注意buf_p.count = 0x20;buf_p.buffer = buffer;buf_p.status = 0;Info_Debug= CyU3PDmaChannelSetupSendBuffer (&glChHandleSlFifoUtoP, &buf_p);if(Info_Debug){CyU3PDebugPrint(4,"\r\n The status of Send Buffer is %x", Info_Debug);}Info_Debug=CyU3PDmaChannelWaitForCompletion(&glChHandleSlFifoUtoP,5000);if(Info_Debug){CyU3PDebugPrint(4,"\r\n The status of Send Buffer is %x", Info_Debug);}}

⑤注意,在使用DMA override模式的时候(上述使用DMA通道的方式即为override方式),禁止使用CyU3PDmaChannelSetXfer。应注释掉,另外做一些描述符上的适配修改,根据自己应用的需求改总线位宽等。

(3)FPGA端接收数据的方式与AN65974一致,在FPGA篇仔细阐述。

USB之Cyusb3014芯片原理之四控制传输实现原理(十二) 2022-04-01相关推荐

  1. USB之Cyusb3014芯片原理之三GPIF原理(十一) 2022-03-08

    Cyusb3014芯片原理之三GPIF原理 请参照GPIFII_Designer_User_Guide.AN65974第9节.AN87216以及(八)Cypress的技术支持之开发环境与应用架构学习关 ...

  2. 最优传输论文(十二):Extracting Relationships by Multi-Domain Matching论文原理

    目录 前言 Introduction Method Domain Adaptation with Relationship Extraction Combining the Loss Terms Co ...

  3. Android usb 控制传输,【android之USB通信】android之USB数据传输-Go语言中文社区

    因为老板认为wifi连接的方式传输数据太慢,想通过USB传输来实现与硬件的连接,所以通过android客户端作为主设备,终端硬件作为从设备.其中收到数据的处理和 下发设置帧的生成与wifi连接的方式都 ...

  4. USB Full-Speed 控制传输

    控制传输分三个阶段: 建立阶段 数据阶段 状态阶段 第一阶段:建立阶段: Token包: PID[3-0]:1101B 地址域(ADDR):低7位 高四位为端点号,LS最多3个端点,FS/HS最多16 ...

  5. USB之Cyusb3014开发经验总结 (十八)2022-04-17

    1.固件开发 1.1串口打印调试信息 在固件开发时,可以利用串口打印调试信息,获得代码执行情况的指示.固件中,用于打印调试信息的串口配置如下,其中波特率的设置为112500,停止位为1,无校验位.在程 ...

  6. GPIF II designer使用说明+CYUSB3014芯片基本信息介绍——英文文档学习记录

    这篇文章是基于之前FX3实现FPGA与USB3.0通信的内容.本人新手,写的不好如有错误请原谅.今天来记录一下官方文档的学习. 一.基本信息讲解 1.1 GPIF II Designer和CYUSB3 ...

  7. CYUSB3014设计方案|替代CYUSB3014芯片|方寸微T630可完全替代兼容CYPRESS CYUSB3014

    CYUSB3014设计方案|替代CYUSB3014芯片|方寸微T630可完全替代兼容CYPRESS CYUSB3014 赛普拉斯CYPRESS CYUSB3014是一款USB 3.0 PHY芯片,广泛 ...

  8. STM32F103系列芯片的地址和寄存器映射原理、LED轮流闪烁实现

    STM32F103系列芯片的地址和寄存器映射原理.LED轮流闪烁实现 文章目录 STM32F103系列芯片的地址和寄存器映射原理.LED轮流闪烁实现 1 51单片机和STM32的不同点 2 寄存器 2 ...

  9. USB电源过流保护芯片应用介绍

    USB电源过流保护芯片应用介绍 USB电源相关要求 USB应用的电压等级是5V,但是有个波动范围是4.75到5.25V之间:USB2.0的电流大小是500mA,USB3.0的电流大小是900mA,因为 ...

最新文章

  1. ASP.NET Core 使用UrlFirewall对请求进行过滤
  2. nssl1323,jzoj(初中)2107-交流【dfs,容斥,组合数】
  3. 程序代码错误检测_错误检测代码
  4. android服务的应用,Android学习指南之十四:Service详解及应用实例
  5. Leetcode每日一题:44.wildcard-matching(通配符匹配)
  6. NFS介绍,NFS服务端安装配置,NFS配置选项
  7. ubuntu 安装openproj-1.4-2.noarch.rpm
  8. Zint生成二维码及png操作
  9. antd使用g2plot统计图表(7)
  10. ffmpeg所有的解码器(decoders)
  11. 几个国内的 apple 相关社区
  12. Android应用市场和应用包名大全
  13. react报错:Uncaught Error: Element type is invalid: expected a string (for built-in components) or a ..
  14. 『TensorFlow』TFR数据预处理探究以及框架搭建
  15. 交流电中为什么要用相量法?
  16. 华硕ASUS FZ63VD fn快捷键失灵
  17. 手机突然电量消耗很快_手机电量突然消耗快是什么原因 教你解决
  18. echarts 中国地图 世界地图
  19. 大数据未来发展的七大趋势
  20. 高德地图看各省分界线_从高德采集最新的省市区三级坐标和行政区域边界,用js在浏览器中运行...

热门文章

  1. 卓帆宝库分享大学生如何轻松挣钱
  2. Windows环境下编译Airsim
  3. VBA入门到进阶常用知识代码总结40
  4. 数字电路和模拟电路-1基础知识
  5. 幻影坦克制作流程和步骤
  6. 分布式爬虫系统的设计与实现(SourceForge.net数据爬取)
  7. 生物统计分析之ROC曲线分析
  8. c# 学习笔记 第一天 ——刘铁猛老师
  9. 仿射密码 python实现
  10. Linux下文件(文件夹)的压缩和解压