Cyusb3014芯片原理之一数据流
1.FX3芯片架构
如图所示,FX3 拥有一个片上 32 位 200 MHz ARM926EJ-S 内核 CPU。该内核能直接访问 16 KB 的指令紧耦合存储器(TCM)和8 KB 的数据紧耦合存储器。ARM926EJ-S 内核还提供了用于固件调试的 JTAG 接口。FX3 集成了 512 KB 或 256 KB 的嵌入式 SRAM(取决于所选择的设备型号),并支持四种启动代码的方法(USB、GPIF II、I2C 或者 SPI)。FX3 能在多种外设(如 USB、GPIF II、I2S、SPI 以及 UART)间实现高效灵活的 DMA 连接。FX3 固件配置外设间的数据访问后,DMA 结构将管理传输,而不需要 ARM9 内核参与。比起(八)Cypress的技术支持之开发环境中的应用场景图,这个图展示了更多的FX3芯片内部细节。本篇文章后半部分着重介绍的就是在芯片内部,数据是如何从GPIF II传输到Eps的,这个通路我将其称之为数据流。还要说明的是,在数据流过程中涉及的概念和术语,数据流对应的数据通道对应的配置在哪里完成,以及通道各处不同配置将会有更多的选择。
2.芯片应用架构
图1
图2
比起(八)Cypress的技术支持之开发环境中的应用场景图这两个图展示了更多上下位机的细节。如图1所示,通过高速并行 GPIF II 接口,某些应用可以将 FPGA 或 ASIC 连接到 FX3。作为数据的源端或汇端的其它设备则被连接到 FPGA 或 ASIC。这样的应用包括数据采集设备、打印机、扫描仪和成像设备等等。在上述应用中,FX3 作为与 USB 主机进行数据发送和接收的快速数据管道。对于这些应用,FX3 到 FPGA/ASIC 的接口通常是同步从设备 FIFO 接口(指的是GPIF II的一种连接模式)。如图2所示,FX3直接与图像传感器相连,通过通用IO控制复位,通过I2C接口完成传感器的相关配置,将可编程接口配置成DVP接口获取图像数据。在FX3内部添加帧头,将数据打包成UVC数据,直接传输到上位机,这是典型的UVC应用。
3.FX3数据流
首先需要说明的是,图中DDR应该是独立的芯片,为了便于表示,将其话在了FPGA内部,此处仅代表逻辑上的含义。还有上图注重的是FX3内部和外围连接的示意,其余部分真实连接更为复杂,均为示意。另外,下面讨论的数据流部分,全部基于一套特定的配置。怎么理解呢?举一个例子。假设数据通道有ABCDE五个地方需要配置,那么只有当A=A1,B=B2,C=C3,D=D4,E=E5的时候,下述关于数据流的讨论才会成立,但是对于该数据通道的应用,绝大多数都是基于这一套配置,因此先默认是这套配置。那么具体是哪些配置项要设置成什么样的值呢?不用急,Follow me,一切将会迎刃而解。
如图所示,整体的数据流是从左侧到右侧(数据上行)或者从右侧到左侧(数据下行)。例如,下行数据,从上位机到下位机的数据流向,典型的是(基于所谓的某套配置),上位机界面软件,调用CyAPI函数,该函数通过操作系统调用cysys驱动程序完成和硬件接口的匹配,将数据进行下发;该数据经过数据编码变成特定格式的数据后,在由此变成物理连线上电平的高低信号;FX3芯片接收到上位数据保存在端点FIFO中,当接收到和DMA缓冲区一样大小的数据量时,或者接收到短数据包(指的是小于1024B的数据包),会触发commit操作,此时会将端点FIFO中的数据写入到UIB(usb接口块)的套接字上;UIB套接字会自动写入到DMA缓冲区中,当UIB套接字写入到DMA的缓冲区时,缓冲区会将对应的专用线程标志和水印值置位;当与GPIF II接口相连的外部主控制器接收到标志和水印值产生的信号之后,会产生相应GPIF II接口时序(即引脚产生高低电平),请求去DMA缓冲区读取数据;产生的接口时序,会让可编程状态机GPIF II跳转状态,例如跳转到读状态,在进行design GPIF II时,在读状态中写入IN_ADDR 命令(输入地址),通过 IN_ADDR 操作,GPIF 硬件采样来自地址总线的值,并使用它选择 DMA 线程;选择线程之后,N_DATA (输入数据)操作对来自数据总线的数据进行采样,然后将其转移到所指定的位置(可以是 DMA 通道,也可以是固件应用)如果将 Data Sink 设置为 Register ,可以使用 CyU3PGpifReadDataWords() API 将数据转移到固件内;而线程和套接字的映射绑定在固件程序中;在一个是PIB和UIB套接字的绑定是通过固件程序中设定的DMA自动通道时指定两端的套接字来进行的,并通过配置该通道的生产套接字(produce)和消费套接字来确认这个通道的方向是从GPIF到UIB还是从UIB到GPIF。
整个系统对于数据流的应用是,蓝色方框内是FX3 CyUSB3014芯片,左边是FPGA+DDR3+image Sensor,右边是PC端。FPGA对CMOS进行必要的配置,生成RAW Data(图像原始数据),数据流经FPGA DDR(弹性的缓存机制),FPGA通过异步从设备方式与FX3 GPIF II接口连接(包含了读写控制与32位数据总线),数据流由此进入FX3,GPIF II接口上的线程控制器(thread controler)根据FPGA的控制信号的状态(addr[1:0])来让GPIF II 状态机选择一个有效的 GPIF 线程(Tr0、1、2)来传输数据,数据流由此进入DMA Adapter,根据固件程序中物理线程与套接字的对应关系(有默认映射),将线程上的数据流转移到PIB的套接字上,根据固件程序中DMA通道的设置(缓冲区的大小、个数、方向),数据从套接字转移到对应的DMA缓冲区中,根据固件程序中DMA通道的配置(连接两个数据流方向固定的套接字),缓冲区中的数据流由此进入对应的UIB套接字中,而UIB Sockets与USB的端点具有对应关系,端点又是设备硬件上具有一定大小的数据缓冲区,即数据流从DMA缓冲区转移到UIB套接字在转移到USB端点中。上位机软件调用USB驱动,去端点的缓冲区中读取数据,由此实现数据从CMOS(源端)到PC端的传输,并最终将这个图像视频流数据显示在上位机。
红线和绿线完整的描述了上行USB数据的流程;红线代表逻辑上的FPGA–>CY的写操作,绿线代表PC–>CY的读操作。
4.FX3数据流的映射关系
按照上行或者下行数据的流向的先后顺序来描述映射关系,并且指出配置的位置和关键函数,并且会在“配置位置与可选配置”一栏解释清楚“一套配置”究竟是哪些配置项是可配置的,而具体的配置的值会在系列中讲到该处原理时提到,此处仅提醒这个地方可以配置。又为了完整性,此处例举的是上行数据与第3节数据流中的数据流方向相反。
5.概念术语解读
套接字
套接字是外设硬件模块和 FX3 RAM之间的连接点。FX3上的每个外设硬件模块(如 USB、GPIF、UART和SPI)具有各自固定的套接字数量。流经外设的独立数据流数量等于该外设上的套接字数量。套接字的实现包括一组寄存器,用于指向有效的DMA描述符,并使能或置位与该套接字相关的中断。套接字列表的运行方式关注AN75705第8页(请关注)。
将数据写入 DMA 缓冲区内的套接字被称作发送套接字。从 DMA 缓冲区内读取数据的套接字被称作接收套接字。套接字使用存储在 DMA 描述符上的 DMA 缓冲区地址、DMA 缓冲区大小和 DMA 描述符链的值来管理数据。套接字写满或读空 DMA 缓冲区后,需要经过一段时间(几微秒)从一个 DMA 描述符转移到另一个描述符。转移过程中,套接字不能传输数据。对于没有流量控制的接口,该延迟是一个问题。(对于没有流控制的GPIF主设备,通常将flag写入到GPIF的状态机里面,然后使用双线程的方式规避该延迟造成的数据丢失)。
DMA描述符
DMA描述符是一组位于FX3 RAM中的寄存器。它保存了DMA缓冲区的地址和大小,以及指向下一个DMA描述符的指针。这些指针构建成了DMA描述符链。
DMA缓冲区
DMA缓冲区是RAM的一部分,用于存储通过FX3设备传输的中间数据。通过FX3固件,可将部分RAM空间分配给DMA缓冲区。这些缓冲区的地址被存储在DMA描述符中。
线程
GPIF线程是 GPIFII模块内的专用数据路径,用于将外部数据引脚同套接字连接起来。
DMA通道
套接字可通过各个事件来互相发出信号,或者它们可通过中断向 FX3 CPU 发出信号。该操作由固件配置的。例如,将数据流从 GPIF II 模块传输给 USB 模块。GPIF 套接字可以通知 USB 套接字它已经向 DMA 缓冲区写满了数据,或者USB 套接字可以通知 GPIF 套接字该 DMA 缓冲区目前为空。该操作被称为自动 DMA 通道。当 FX3 CPU 不用修改数据流中的任何数据时,通常会使用自动 DMA 通道。或者,GPIF 套接字可以向 FX3 CPU 发送一个中断,来通知 GPIF 套接字已经写满了 DMA 缓冲区。FX3 CPU 可将该信息传递给USB套接字。USB套接字会向FX3 CPU发送一个中断,来通知USB套接字已经读空了DMA缓冲区。此时,FX3 CPU 可将该信息反馈给 GPIF 套接字。该操作被称为手动 DMA 通道实现。FX3 CPU 需要添加、删除或修改数据流中的数据时,通常需要执行该操作。
使用标志
标志用于流控制,标志与特定线程或当前寻址的线程相关联,用于表示映射到该线程的套接字状态。标志可被配置为空、满、一部分空或一部分满信号。标志将根据(初始化套接字过程中所配置的)套接字方向来指示空或满状态。因此,如果从套接字读取数据,标志将表示空/未空状态;如果对套接字写入数据,标志将表示满/未满状态。
在应用中,我们使用到的是专用线程标志和水印值的组合。需要注意的是,水印值是用来判断部分满(将要满)或者将要空的,(官方手册中明确说到)水印值为0代表即将满(或者即将空),但是当水印值为1时不能代表可以读或者可以写,是否可以读或者可以写是要通过专用标志来判断的,这就是配合使用的意义所在。
标志与线程的映射关系是通过GPIF状态机进行配置的。标志表示的具体含义是部分满还是将要空是由线程所映射的套接字的方向所决定的。而水印值的配置是通过固件中,CyU3PGpifSocketConfigure(0,CY_U3P_PIB_SOCKET_0,6,CyFalse,1);所确定的。其中,数字6确定了水印值的大小,套接字的方向确定了指示数据流的方向,具体的状态是线程0确定的。
而水印值的用法主要是关乎到外部控制器与GPIF II接口经行数据交互时进行数据流控制,避免空读缓冲区或者使缓冲区溢出。在官方手册中,提到了,当水印值表示部分满的时候,即上行数据,从外部控制器到PC端传输。此时对应的管控信号时slwr,即控制写信号,当外部主设备对同步从设备 FIFO 进行写入时:(a) 时钟沿到来(这时,对处于低电平的局部标志进行采样)后将要写入的数据字的数量 = 水印值 x (32/总线宽度) – 4 标绿部分的含义是,当进行写操作时,水印值拉低之后,slwr需要在采样标志之后,保持两个周期。注意采样的含义是使用非阻塞赋值延迟一个周期。
而当水印值代表的是即将空的时候,表示此时的数据流向是下行数据,即外部控制器需要去DMA缓冲区中读取这个数据。此时对应的管控信号有两个,一个是sloe,另一个是slrd。当外部主设备对同步从设备 FIFO 进行读取时:(a) 时钟沿到来(这时,对处于激活状态的局部标志进行采样)后可用于读取的数据字的数量(SLOE#维持激活时) = 水印值 x (32/总线宽度) – 1(b) 已包含从 SLRD#置低到数据在总线上有效的两个周期的延迟。 因此,时钟沿到来(这时,对处于激活状态的局部标志进行采样)后维持激活 SLRD#的周期数 = 水印值 x (32/总线宽度)– 3。 标绿部分是来自官方文档,给出了水印值置位之后,经采样后,各信号需要保持的时长。因此做程序设计的时候应该严格按照这个时序进行读写操作。