DMA缓冲区大小是否应与UART FIFO大小相同?

时间:2014-06-12 09:21:09

标签: linux-device-driver uart dma

我在Linux平台上运行的omap4460熊猫板上为UART编写了一个驱动程序。我在UART中启用了FIFO模式的DMA。我的用户应用程序将100个字节的数据从用户空间传输到内核缓冲区(DMA缓冲区)。 / p>

一旦启用DMA通道,DMA缓冲区的数据就会复制到FIFO,然后传输到UART的TSR。由于我的FIFO大小为64字节,因此只有64字节传输到TSR。

如何将剩余字节从DMA缓冲区传输到FIFO?/ IS是否发生溢出?

编辑:添加了部分配置 下面的代码表示UART配置

/* Software reset */
    iowrite32(0x2,uart_vbaddr + UART_SYSC);
    while((ioread32(uart_vbaddr + UART_SYSS) & 0x1)== 0);

    /* FIFOs and DMA Settings */
    lcr = ioread32(uart_vbaddr + UART_LCR);
    iowrite32(UART_MODE_B,uart_vbaddr + UART_LCR);
    efr = ioread32(uart_vbaddr + UART_EFR);
    iowrite32(0x10,uart_vbaddr + UART_EFR);/
    iowrite32(UART_MODE_A,uart_vbaddr + UART_LCR);
    mcr = ioread32(uart_vbaddr + UART_MCR);
    iowrite32(0x40,uart_vbaddr + UART_MCR);
    iowrite32(0x09,uart_vbaddr + UART_FCR);//FIFO not getting enabled here
    iowrite32(UART_MODE_B,uart_vbaddr + UART_LCR);
    iowrite32(0x2,uart_vbaddr + UART_TLR);//to set for 8 spaces
    iowrite32(0x0,uart_vbaddr + UART_SCR);
    iowrite32(efr,uart_vbaddr + UART_EFR);
    iowrite32(UART_MODE_A,uart_vbaddr + UART_LCR);
    iowrite32(mcr,uart_vbaddr + UART_MCR);
    iowrite32(lcr,uart_vbaddr + UART_LCR);

    /* Protocol Baudrate and interrupt settings */
    dll = divisor & 0xFF;
    dlh = divisor >> 8;
    iowrite32(0x7, uart_vbaddr + UART_MDR1);
    mdrdelay();
    iowrite32(UART_MODE_B, uart_vbaddr + UART_LCR);
    iowrite32(dll,uart_vbaddr);
    iowrite32(dlh,uart_vbaddr + UART_DLH);
    iowrite32(lcr_val , uart_vbaddr + UART_LCR);
    iowrite32(0, uart_vbaddr + UART_MDR1);
    mdrdelay();

    iowrite32(0x09,uart_vbaddr + UART_FCR);//So renabling the FIFO again

DMA配置为HW SYNC模式。对于BS = 0和FS = 0.ie,为每个DMA请求逐个元素地传输。

下面的代码给出了DMA配置

/* Set the Read Port & Write Port access in CSDP */
csdp_val &= 0x00000000;
iowrite32(csdp_val,dma_map + DMA_CSDP(dma_cha_line));

/* Set the Channel Source & Destination start address */
iowrite32(bus_addr,dma_map + DMA_CSSA(dma_cha_line));
iowrite32(UART4_BASE,dma_map + DMA_CSDA(dma_cha_line));

/* CCR configuration */ 
ccr_val=ioread32(dma_map+DMA_CCR(dma_cha_line))     
ccr_val |=  (0x1 << 24);//Source triggers on the DMA 

/*Frame(5) and Block(18) Synchronisation */
ccr_val &= ~(0x1 << 5);//FS
ccr_val &= ~(0x1 << 18);//BS
ccr_val |= (0x17);//CCR[4:0]
ccr_val |=  (0x1 << 19);//CCR [19:20] 
ccr_val &=  ~(0x1 << 20);//CCR [19:20] 
ccr_val |= (0x1 << 12);//source - post incremented 12:13 
ccr_val &= ~(0x1 << 13);    
ccr_val &= ~(0x3 << 14);//destination- constant address mode 14:15
iowrite32(ccr_val,dma_map + DMA_CCR(dma_cha_line));
ccr_val = ioread32(dma_map + DMA_CCR(dma_cha_line));  
Finally after this initialiasitation.channel is enabled.

请建议我初始化是否有任何错误,因为我只得到64字节,我也无法在[TRM] http://www.ti.com/lit/ug/swpu235ab/swpu235ab.pdf

中给出的任何模式下触发DMA请求

编辑:修改了元素同步的代码。 1.在TRM中经常观察到这句话。有什么设置?

  

DMA设置必须与系统LH DMA控制器相对应   设置以确保正确操作此逻辑。

2.这个配置是否正确? :

ccr_val |=  (0x1 << 24);//Source triggers on the DMA
To regenrate the DMA request again,shouldn't I configure the DMA as destination triggered instead of source
ccr_val |=  (0x1 << 24);//Destination triggers on the DMA ?

我曾尝试过两种方法,遗憾的是结果相同

3.有三种方法可以配置FIFO.ie FCR / TLR / MDR3寄存器的触发电平。

在此代码中,我使用TLR寄存器进行了设置。此TLR设置通过中断模式进行验证。

1 个答案:

答案 0 :(得分:2)

  

DMA配置为...块同步。

这是一个根本性的错误 块同步适用于块设备,例如具有扇区缓冲区的HDD,用于接收完整块,因为数据通过SATA(或PATA)总线传输一次操作。
UART是字符设备,每个操作传输一个字符。存在FIFO以确保可以接收数据(防止溢出)并且数据可用于传输(最小化空闲线路时间)。串行链路的另一端具有未知的缓冲能力。如果它的缓冲有限,则应采用流量控制(使用硬件RTS / CTS或软件XON / XOFF)。
块设备不会使用流量控制。一旦开始块传输,就必须完成传输。你不能暂停&#34;使用角色设备进行传输。

在串行链路上传输数据之前,必须将数据从存储器传输到UART(在这种情况下,Tx FIFO是发送寄存器的中间接口)。您可以使用PIO或DMA执行此传输 对于DMA传输,FIFO和DMA控制器必须配置为同意DMA请求的时间(和频率)以及每个DMA响应的大小。
请注意,DMA响应的大小与DMA缓冲区的大小(在您的问题标题中)或存储在计数寄存器中的DMA传输大小不同。

  

DMA配置为HW SYNC模式。在BS = 1和FS = 0.ie时,在发出DMA请求时传输完整块

假设发送的DMA传输设置为100的计数和正确的DMA缓冲区的地址,似乎Tx FIFO正在发出DMA请求。
然后,第一个DMA响应是针对100字节的块大小,其中FIFO实际上只捕获了64个字节。可能会丢弃第一个DMA响应的剩余字节 当Tx FIFO耗尽时,如果它发出另一个DMA请求,则无法满足该新请求,因为DMAC认为传输&#34;完成&#34;。您可以通过检查DMAC计数寄存器来检查此情况。 DMAC计数寄存器是零还是36,丢失的数量(100 - 64)字节?

  

如何将剩余字节从DMA缓冲区传输到FIFO?/ IS是否发生溢出?

要配置DMA控制器,请遵循TRM第16.5.3节“硬件同步传输”(第3627页)中概述的十个步骤,了解如何配置LCh以按每个DMA请求传输一个元素

总之,设置Tx FIFO以在至少有8个空格时发出DMA请求,并使用1个字节的单个元素响应DMA通道。