我在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设置通过中断模式进行验证。
答案 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通道。