当前位置: 技术问答>linux和unix
有关LINUX DMA驱动的问题
来源: 互联网 发布时间:2016-07-29
本文导语: 本帖最后由 guan323333 于 2010-01-06 09:24:22 编辑 小弟最近在学习写驱动,写了个最简单的DMA驱动但是用不起来,查了很久都不知道哪里有问题,贴出来大家看看哈.由于问题比较长也比较复杂,给50分.格式好难弄,大家将就...
编程步骤如下:(以下是初始化,一切结果表现的正常)结果是buff_des还是DESDESDESDES,没有变成I AM THE SRC~~~~~~~~",哪里有问题呢,高手指点下
…………
result = register_chrdev(210,"mydma",&dmatest_fops);
…………
Csr_Addr = DMA_ADDR_BASE+0x24;
Csr_Addr = (unsigned long)ioremap(Csr_Addr,4);
Sy_Addr = (unsigned long)ioremap(DMA_ADDR_BASE+0x28,4);
Cn_CFG_Addr = (unsigned long)ioremap(DMA_ADDR_BASE+0x1E4,4);
Cn_LLP_Addr = (unsigned long)ioremap(DMA_ADDR_BASE+0x1F0,4);
Cn_Size_Addr = (unsigned long)ioremap(DMA_ADDR_BASE+0x1f4,4);
Cn_Csr_Addr = (unsigned long)ioremap(DMA_ADDR_BASE+0x1e0,4);
(*(volatile unsigned long *)Csr_Addr) = 0x0001; //设置地址格式为小端,同时ENABLEDMA控制器
(*(volatile unsigned long *)Sy_Addr) = 0x0080; //设置同步模式
(*(volatile unsigned long *)Cn_CFG_Addr) = 0x00000003; //设置允许中断
(*(volatile unsigned long *)Cn_LLP_Addr) = 0x00000000; //设置LLP为0,这个我也不知道为什么,不过编程手册上这么写的
(*(volatile unsigned long *)Cn_Size_Addr) = 0x00000400; //设置传输大小为1K
(*(volatile unsigned long *)Cn_Csr_Addr) = 0x80fc1204; //设置权限、单次传输大小等
…………
以下是ioctl的内容:
……
Cn_SrcAddr = (unsigned long)ioremap(DMA_ADDR_BASE+0x1e8,4);
Cn_DesAddr = (unsigned long)ioremap(DMA_ADDR_BASE+0x1ec,4);
switch(cmd)
{
case SETSRC:
(*(volatile unsigned long *)Cn_SrcAddr) = arg; //设置源地址
break;
case SETDES:
(*(volatile unsigned long *)Cn_DesAddr) = arg; //设置目标地址
break;
case STARTDMA:
(*(volatile unsigned long *)Cn_Csr_Addr) |= 0x01; //开始DMA传输
break ;
case STOPDMA:
(*(volatile unsigned long *)Cn_Csr_Addr) &= 0xfffffffe; //结束DMA传输
break ;
}
接着在应用程序里:
int ret;
int fileno;
char buff_src[32] = {"I AM THE SRC~~~~~~~~"};
char buff_des[32] = {"DESDESDESDES"};
fileno = open("/dev/mydma",O_RDWR);
…………
ret = ioctl(fileno,SETSRC,&buff_src);
ret = ioctl(fileno,SETDES,&buff_des);
ret = ioctl(fileno,STARTDMA,NULL);
ret = ioctl(fileno,STOPDMA,NULL);
…………
|
ret = ioctl(fileno,STARTDMA,NULL);
ret = ioctl(fileno,STOPDMA,NULL);
~~~~~~~~~~~~~~~~~~~~~~
你应该根据DMA传输结束中断来判断DMA结束了没有,而不是不分青红皂白的给它来个stop。
ret = ioctl(fileno,STOPDMA,NULL);
~~~~~~~~~~~~~~~~~~~~~~
你应该根据DMA传输结束中断来判断DMA结束了没有,而不是不分青红皂白的给它来个stop。
|
做完ioremap,往地址写值最好用writeb,writew writel
|
不知道DMA中断有没有判断和提取
|
不知道