您现在的位置: USB开发网 > USB技术文档 > USB芯片应用
- USB芯片应用

USB 接口芯片 PDIUSBD12 DMA 模式应用说明

------分隔线----------------------------

什么是DMA

  DMA的英文拼写是“Direct Memory Access”,汉语的意思就是直接内存访问,是一种不经过CPU而直接从内存了存取数据的数据交换模式,直接存储器存取(DMA)控制器是一种在系统内部转移数据的独特外设,可以将其视为一种能够通过一组专用总线将内部和外部存储器与每个具有DMA能力的外设连接起来的控制器。通常只有数据流量较大(kBps或者更高)的外设才需要支持DMA能力。

  一般而言,DMA控制器将包括一条地址总线、一条数据总线和控制寄存器。高效率的DMA控制器将具有访问其所需要的任意资源的能力,而无须处理器本身的介入,它必须能产生中断。最后,它必须能在控制器内部计算出地址。  

  因为你通常会在代码初始化过程中对DMA控制器进行配置,内核就只需要在数据传输完成后对中断做出响应即可。你可以对DMA控制进行编程,让其与内核并行地移动数据,而同时让内核执行其基本的处理任务—那些应该让它专注完成的工作。

USB 接口芯片 PDIUSBD12 的 DMA 模式应用说明

  PDIUSBD12 的主端点(端点2)支持DMA传输,使用DMA控制器,PDIUSBD12 的主端点和本地共享存储器间的数据传输可自主进行而不需要本地CPU的干预。在基于协议的 DMA 操作中,主机应用程序询问器件的固件以通过由控制端点发送的厂商请求建立DMA传输,然后在主端点上执行实际的批量数据传输,在 DMA控制器建立之后主机可向器件传输最多为64k字节的数据而不需要任何固件的干预。

  要处理任何DMA传输,本地CPU从主机接收必要的SETUP信息并对DMA控制器进行相应的编程,典型的,对DMA控制器的传输模式,字节计数寄存器和地址计数器进行正确的编程,在该模式下 PDIUSBD12发出请求时开始传输,当字节计数器减少为零时终止,在DMA控制器编程之后,本地 CPU 在初始化传输时将 PDIUSBD12 中的 DMA使能位置位。

  一个完整的 DMA传输要求以下两个步骤 :

1)通过主管道发送一个请求,并允许器件用 DMA 传输方向,起始地址和传输规格对 DMAC 进行编程 。

2)在主端点上发送或接收数据包。

 PDIUSBD12器件DMA 状态

  建立DMA请求通过控制管道作为厂商请求从主机发出,器件的响应和动作依赖于DMA 操作的状态 。

 

PDIUSBD12 器件DMA状态机
 
  上图所示为器件中 DMA 的 3 种状态,IDLE RUNNING 和 PENDING 如果没有运行或推迟 DMA 操作,器件处于 IDLE 状态,那么建立 DMA 请求由 ACK 进行响应。如果器件在 DMA 传输的过程中就是RUNNING状态,建立 DMA 请求由 NAK 进行响应并导致器件进入PENDING状态,这表示有一个推迟的建立 DMA请求,如果器件在 PENDING状态中接收到另一个建立 DMA请求,新的请求将覆盖旧的请求。
 
下图为固件处理建立 DMA请求和 EOT的程序流程图
 
固件处理建立 DMA请求和 EOT的程序流程图(pdiusbd12)
 
DMA 配置寄存器

  D12 的 DMA操作由其 DMA配置寄存器进行控制,该寄存器由设置 DMA 命令设置,寄存器中不是所有的位都和DMA操作有关。位4(中断脚模式)和位7( 时钟分频系数)控制 D12 的中断源 。

下表所示为推荐的寄存器编程汇总:


 

  默认情况下,D12 和 DMAC 都不处于自动重装模式,不想让器件的 DMA 自动重新启动,是因为这是一个协议层的操作,也就是说在主机的控制之下,在 EOT D12 和 DMA 控制器的 DMA 都被禁止,固件需要重新使能以使它们在接收到主机的建立,DMA请求时重新启动 DMA传输。 

  需要注意的是,在 DMA模式中来自端点 4 和5 的中断被禁止,这些端点上的中断服务是不必要的,而且使 DMA传输中有潜在的缺陷,DMA可以看作是最高级的中断 可以在任意两条 CPU指令之间执行,甚至在 ISR 中,由于在传输当中 DMA 的状态任何时候都有可能改变,因此任何想要用来检测 DMA 状态的程序都是不可靠的  。

  以下是一个 IN  标志 DMA传输编程示例,dma_dir 和 dma_transfer_size已通过建立 DMA请求设置 。

  1. dma_start(dma_dir, MainDmaBuf, dma_transfer_size, 3);   
  2. dma.bits.dma_burst = 3;   
  3. dma.bits.dma_enable = 1;   
  4. dma.bits.dma_direction = dma_dir;   
  5. dma.bits.auto_reload = 0;   
  6. dma.bits.normal_plus_sof = 0;   
  7. dma.bits.endp_4_interrupt_enable = 0;   
  8. dma.bits.endp_5_interrupt_enable = 0;   
  9. D12_SetDMA(dma);  

建立 DMA 请求

  建立 DMA 请求是一个通过控制管道发送的厂商请求 在 PDIUSBD12 采样固件和小应用程序中,这
些是由 IOCTL_WRITE_REGISTER(由微软 Windows 98 DDK 中的静态图像USB 接口定义)完成的。

器件请求描述如下:

pdiusbd12 DMA 模式请求
 

   在器件请求之后,DMA 操作的具体请求在数据阶段发送,采样固件和小应用程序使用专有的定义如下所示 :

PDIUSBD12 DMA 专有定义
 

主机端编程注意事项

  USB 器件不是决定传输速率的唯一标准,主机端的应用程序在整个系统的性能占有更重要的地位,因为主机一直在控制 USB 的处理。

  DMA 传输是一个包括了控制端点和主端点的连续操作,由于下一步操作由前一操作的结果决定,所
以协作非常重要,虽然多线程可用于对不同管道进行访问以增加系统的性能,但使用单线程却使处理建立DMA请求(IOCTL)和数据传输(写文件/读文件)操作的编程容易许多。

  IOCTL_WRITE_REGISTER 和 IOCTL_READ_REGISTER 使用结构,IO_BLOCK 与器件驱动器进行数据交换。下面所示的结构定义是微软静态图像 USB 接口的一部分。  

  1. typedef struct _IO_BLOCK {   
  2.     IN   unsigned uOffset;   
  3.     IN   unsigned uLength;   
  4.     IN OUT PUCHAR pbyData;   
  5.     IN   unsigned uIndex;   
  6. } IO_BLOCK, *PIO_BL 

IO_REQUEST  结构是一个专有的定义,包含了建立DMA请求的细节。

  1. typedef struct _IO_REQUEST {   
  2.     unsigned short    uAddressL;   
  3.     unsigned char    bAddressH;   
  4.     unsigned short    uSize;   
  5.     unsigned char    bCommand;   
  6. } IO_REQUEST, *PIO_RE 

 举例程序如下 :

 

  1. ioRequest.uAddressL = 0;   
  2. ioRequest.bAddressH = 0;   
  3. ioRequest.uSize = transfer_size;   
  4. ioRequest.bCommand = 0x80; //start, write   
  5. ioBlock.uOffset = 0;   
  6. ioBlock.uLength = sizeof(IO_REQUEST);   
  7. ioBlock.pbyData = (PUCHAR)&ioRequest;   
  8. ioBlock.uIndex = 0x471;   
  9. bResult = DeviceIoControl(hDevice,   
  10.                           IOCTL_WRITE_REGISTERS,   
  11.                           (PVOID)&ioBlock,   
  12.                           sizeof(IO_BLOCK),   
  13.                           NULL,   
  14.                           0,   
  15.                           &nBytes,   
  16.                           NULL);   
  17. if (bResult != TRUE)  
  18. {   
  19.     testDlg->MessageBox("Setup DMA request failed!""Test Error");   
  20.     return;   
  21. }   
  22. bResult = WriteFile(hFile,   
  23.                     pcIoBuffer,   
  24.                     transfer_size,   
  25.                     &nBytes,   
  26.                     NULL);  

 

------分隔线----------------------------
  • 上一篇:没有了
  • 下一篇:没有了
联系我们
  • Q Q: 1148374829 点击这里给我发消息
  • 旺旺:jhoneqhsieh 点击这里给我发消息
  • 电话:(0)15923141204
  • 淘宝网店
USB开源项目