linux uart寄存器 代替 printk,启用了DMA的UART Tx模式

我已经为传输模式下的DMA写入了一个简单的设备驱动程序,并启用了DMA以及中断。 我使用的硬件是带有Linux 3.4的omap 4460 pandaboard。启用了DMA的UART Tx模式

下面我分享了代码的相关部分。 在打开相:

dma_map = ioremap(UART4_DMA_REG,0x1350);

if(dma_map == NULL) {

printk(KERN_INFO " unable to io_remap DMA region\n");

return -ENOMEM;

}

printk(KERN_INFO "DMA mapping successful\n");

irq_val = request_irq(45,uart_handler,IRQF_DISABLED,"uart_int",NULL);

if(irq_val) {

printk(KERN_INFO "cannot assign the requested irq\n");

return -1;

}

else {

printk(KERN_INFO "Requested irq successful\n");

}

其中UART4_DMA_REG是DMA的基地址寄存器0x4a056000和请求IRQ是45,其线SDMA的1中断。 在此UART寄存器初始化和DMA启用后。 现在用户调用write函数将100个字节的数据复制到内核空间的缓冲区中。

下面的代码显示的写功能:

ssize_t uart_write(struct file *filp,const char __user *buff, size_t count, loff_t *offp)

{

int no_of_bytes;

int maxbytes;

struct device *udevice = &devi;

int ret_mask;

char *kbuf = kmalloc(100,GFP_KERNEL|GFP_DMA);

maxbytes = BUFF_SIZE - *offp;

if(count > maxbytes)//overflow of buffer

no_of_bytes = maxbytes;

else

no_of_bytes = count;

if(no_of_bytes == 0)

printk(KERN_INFO "Nothing is there to write to device\n");

bytes_written = no_of_bytes - copy_from_user(kbuf,buff,no_of_bytes);//copy_from_user()returns remaining bytes.

printk(KERN_INFO "Write Completed\n");

Uindex = 0;

*offp += bytes_written;

ret_mask = dma_set_coherent_mask(udevice,DMA_BIT_MASK(32));

if(!ret_mask)

printk(KERN_INFO "set mask success \n");

else

printk(KERN_INFO "SET MASK NOT SUCCESS \n");

bus_addr = dma_map_single(udevice,kbuf,size,DMA_TO_DEVICE);

printk(KERN_INFO "dma_map_single completed");

dma_init();

return bytes_written;

}

dma_init();此函数初始化DMA寄存器,使在软件触发模式中的信道。

void dma_init()

{

unsigned int ccr_val;

unsigned int csdp_val;

irq_line = 1; //for tx line 1 is considered

dma_cha_line = 0; //for tx line 0 is considered

/* Interrupt Enabled in DMA4_IRQENABLE_Lj and DMA4_CICRi registers */

iowrite32(0x1,(dma_map + 0x0018 + (4 * irq_line)));//to unmask the interrupt DMA4_IRQENABLE_Lj

iowrite32(0x8,(dma_map + 0x0088 + (0x60 * dma_cha_line)));//condition to generate interrupt CICR reg

/* Set the Read Port & Write Port access in CSDP */

csdp_val = ioread32(dma_map + 0x0090 + (0x60 * dma_cha_line));

csdp_val &= ~(0x3 << 7);//Source

csdp_val &= ~(0x3 << 14);//Destination

csdp_val &= ~(0x3 << 16);//Writing mode without posted

csdp_val &= ~(0x1 << 21);//little endian source

csdp_val &= ~(0x1 << 19);//little endian destination

csdp_val &= ~(0x1 << 13);//destination not packed

csdp_val &= ~(0x1 << 6);//source not packed

csdp_val &= ~(0x3);//ES is set to 8 bits

iowrite32(csdp_val,(dma_map + 0x0090 + (0x60 * dma_cha_line)));

/* CEN register configuration */

iowrite32(100,(dma_map + 0x0094 +(0x60 * dma_cha_line)));//EN is set to 1

/* CFN register configuration */

iowrite32(1,(dma_map + 0x0098 +(0x60 * dma_cha_line)));//FN is set to 1

/* Set the Channel Source & Destination start address */

iowrite32(bus_addr,(dma_map + 0x009C + (0x60 * dma_cha_line)));//Source

iowrite32(io_map,(dma_map + 0x00a0 + (0x60 * dma_cha_line)));//Destination

/* CCR configuration */

ccr_val = ioread32(dma_map + 0x0080 + (0x60 * dma_cha_line));

/* Set the Read Port & Write Port addressing mode in CCR */

/*

ccr_val &= ~(0x3 << 12);//Source - constant address mode

ccr_val |= (0x1 << 14);//Destination - post incremented address mode-set 14th bit and clear 15th bit

ccr_val &= ~(0x1 << 15);

*/

ccr_val |= (0x1 << 12);//source - post incremented address mode-set 12th bit and clear 13th bit

ccr_val &= ~(0x1 << 13);

ccr_val &= ~(0x3 << 14);//destination- constant address mode - clear 14 and 15th bit

ccr_val |= (0x1 << 26);//high priority on write

ccr_val &= ~(0x1 << 6);//low priority on read

ccr_val &= ~(0x1f);//CCR[4:0]

ccr_val &= ~(0x3 << 19);//CCR [19:20] to 0

ccr_val |= (0x1 << 7);// Set the channel enable bit in CCR

iowrite32(ccr_val,(dma_map + 0x0080 + (0x60 * dma_cha_line)));

/*CSEI,CSFI,CDEI,CDFI*/

iowrite32(1,(dma_map + 0x00a4 +(0x60 * dma_cha_line)));

iowrite32(1,(dma_map + 0x00a8 +(0x60 * dma_cha_line)));

iowrite32(1,(dma_map + 0x00ac +(0x60 * dma_cha_line)));

iowrite32(1,(dma_map + 0x00b0 +(0x60 * dma_cha_line)));

printk(KERN_INFO "DMA registers configured\n");

}

现在的问题是:一旦通道被使能(只是调用dma_init后()),ISR(处理)被调用,进入无限循环。我的ISR应该在写模式下包含什么?

2014-05-21

ddpd

+0

您可以添加ISR代码吗?另外,你说通道在dma_init()调用后启用,但在dma_init()之后只有一个返回。 –

+0

@ScottLawson:谢谢你的回复。但我已经解决了这些问题。首先,由于这是一个字符设备,所以DMA传输必须每个DMA请求发生1个元素。我已经将它配置为每个DMA请求传送1块。其次,按照元素传输编程指南,不需要配置DMA4_CEN和DMA4_CFN寄存器。但它只在配置这些寄存器时才起作用。 –

+0

酷!你应该发布这个答案并接受它。鼓励你回答你自己的问题。 –

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值