DMA数据传输

  SD主控制器与系统存储空间进行数据传输时使用SDMA或ADMA2传输方式,需要配置的参数包括:一次传输的数据块数、每块数据大小、传输边界、传输方向、传输数据首地址、DMA传输模式等信息
(1)单DMA传输(SDMA)
单DMA传输的流程图如下图所示,在这种模式下,数据搬运通过SDMA完成,无需处理器参与,释放了CPU资源。在SDMA模式下, System Address存储的是数据传输的实际地址 。因此SDMA传输可以从任何字节开始,对地址没有限制。数据传输块大小的定义需要根据FIFO深度来设置,其大小不能超过FIFO数据容量,一次连续传输数据块数与传输的数据量有关。
当传输达到SDMA存储边界时,SDMA控制器将停止当前传输并产生中断给CPU,需要CPU对SDMA数据传输首地址进行更新才能继续进行数据传输,降低数据传输速度!比如系统边界4KB的条件下,传输32KB的数据需要产生的8次中断才能完成数据的传输。
操作步骤:
  1. 系统内存的数据位置被设置为SDMA系统地址寄存器。
  2. 设置BlockSize寄存器,对CMD17, CMD18, CMD24, CMD25访问有效,仅在未发生传输时可以修改。
  3. 设置BlockCount寄存器,仅在多块传输模式下有效,控制器在每传输完一块后自减,只有在空闲时可以修改。设置Argument寄存器,该寄存器需写入SD访问CMD的bit[39:8];
  4. 设置Transfer Mode寄存器,主机驱动选择多块还是单块,使能块计数,数据传输的方向,自动使能CMD12和使能DMA。
  5. 设置Command寄存器。注意:写入命令寄存器的高字节[3]时,发出SD命令并启动SDMA。
  6. 然后等待中断命令完成。
  7. 向中断状态寄存器位写‘1’清除中断位;
  8. 读Response响应寄存器获取从SD卡得到的相关信息;
  9. 等待传输完成中断和DMA中断。
  10. 如果传输完成设置为1,则如果DMA中断设置为1,则转到步骤(14),否则转到步骤(12).Transfer Complete比DMA Interrupt高。
  11. Normal Interrupt Status寄存器的DMA中断中写入1清除该位。
  12. 将下一个数据位置的下一个System Address设置到System Address寄存器并转到步骤(10)。
  13. 在Normal Interrupt Status寄存器中向传输完成和DMA中断写入1,以清除此位。
注意:步骤(2)和步骤(3)可以同时执行。步骤(5)和步骤(6)也可以同时执行。


(2)ADMA2传输
使用ADMA数据传输没有存储边界,不需要产生CPU中断,提高数据数据传输速度。使用ADMA传输时,ADMA System Address寄存器里建立一张描述链表(descriptor table),SD主控制器通过使用ADMA系统地址确定描述链表的首地址,从而访问链表中的每一个描述项内容。ADMA2描述表中每个描述项包含64位,高32位用于保存完整的数据传输首地址,其后的16位用于定义存放在以高32位为首地址存储空间内的数据长度,表述项对应的操作用两位ACT来定义,低三位标志位为数据有效标志位VAL、结束标志位END和中断标志位INT。

typedef  struct  adma2 {
    CPU_INT16U wAttribute;
    CPU_INT16U wLen;
    CPU_INT32U dwAddress;
} ADMA2;

    ADMA2    *AdmaDes;
    AdmaDes = (ADMA2*)(ATCM_ROM+0x2000);
    regh = (SDHOST_REG*)SDHOST_BSP__BASE;
    regh->SDH_CLOCK_CONTROL = 0x0805;
    regh->SDH_INT_ENABLE = 0xFFFFFFFF;
    regh->SDH_SIGNAL_ENABLE = 0xFFFFFFFF;
    AdmaDes[0].dwAddress = 0x40000000+(ATCM_ROM+0x1000);//CPU访问地址和DMA访问地址相差0x40000000
    AdmaDes[0].wLen = 0x200;//分段大小必须为BlockSize的整数倍
    AdmaDes[0].wAttribute = 0x21;
    
    AdmaDes[1].dwAddress = 0x40000000+(ATCM_ROM+0x1700);
    AdmaDes[1].wLen = 0x200;
    AdmaDes[1].wAttribute = 0x23;
  ADMA采用分散—聚集的DMA算法,通过描述表来控制数据传输,不需要在每一次地址边界向CPU发送中断信号。使用ADMA1模式进行数据传输时必须以4KB作为最小页面地址的限制,降低了存储空间的利用率;ADMA2模式解除了这一限制,AMDA2模式的传输策略与ADMA1相同,使用描述链表来控制DMA传输过程中数据在系统存储空间的存取位置和规模。
操作步骤:
  1. 在系统内存中为ADMA创建描述符表。
  2. 在ADMA System Address寄存器中设置ADMA的描述符地址。
  3. 设置Block Count寄存器对应于一个块的执行数据字节长度的值。
  4. 设置Block Count寄存器与执行的数据块数相对应的值。
如果在Transfer Mode寄存器中启用的块数设置为1,那么总数据长度可以由Block Count寄存器和描述符表指定。这两个参数表示相同的数据长度。但是,传输长度受到Block Count寄存器的限制。
如果Transfer Mode寄存器中启用的块计数设置为0,则总数据长度不是Block Count寄存器指定,而是描述符表。在这种情况下,ADMA读取的数据要多于从SD卡中编写的长度。太多的读操作会异步地终止,当ADMA完成时,额外的读取数据就会被丢弃。
  1. 将参数值设置为参数1寄存器。
  2. 设置Transfer Mode寄存器。主机驱动程序决定多个/单个块选择、块数启用、数据传输方向、自动CMD12启用和DMA启用。
  3. 设置Command寄存器。
注意:写入Command寄存器的高字节[3]时,发出SD命令,并启动DMA。
  1. 然后等待中断命令完成。
  2. 将Normal Interrupt Status寄存器中的命令完成写入1清除该位。
  3. 读Response响应寄存器获取从SD卡得到的相关信息;
  4. 等待传输完成中断和ADMA错误中断。
  5. 如果传输完成设置为1,则转到步骤(13);如果ADMA错误中断设置为1,则转到步骤(14)。
  6. 将Normal Interrupt Status寄存器中的传送完成状态写入1清除位。
  7. 将1写入错误中断状态寄存器中的ADMA错误中断状态,以清除该错误位。
  8. 中止ADMA操作。SD卡操作应该通过发出中止命令来停止。如果需要时,主机驱动程序检查ADMA错误状态寄存器,以检测ADMA产生错误的原因。
 
注意:步骤(3)和步骤(4)可以同时执行。步骤(6)和步骤(7)也可以同时执行。

下载

linux S3C2440 DMA驱动开发



猜你喜欢

转载自blog.csdn.net/u010872301/article/details/80435536