DMA是数据传输的快速通道,不经过CPU,只占用总线周期。主要是根据DATASHEET配置DMA
现写一驱动程序:设置需要用到DMA通道传输数据的源、目的、长度等参数,让DMA自行传输,
传输完毕后,比较源、目的的最终数据,检验是否传输完整并正确。
2012-05-10 16:05 发表于百度空间,今搬至CU。
阅读(79) | 评论(0) | 转发(0) |
<script type=text/javascript charset=utf-8 src="http://static.bshare.cn/b/buttonLite.js#style=-1&uuid=&pophcol=3&lang=zh"></script> <script type=text/javascript charset=utf-8 src="http://static.bshare.cn/b/bshareC0.js"></script>
现写一驱动程序:设置需要用到DMA通道传输数据的源、目的、长度等参数,让DMA自行传输,
传输完毕后,比较源、目的的最终数据,检验是否传输完整并正确。
点击(此处)折叠或打开
- #include <linux/module.h>
- #include <linux/init.h>
- #include <linux/device.h>
- #include <linux/cdev.h>
- #include <linux/fs.h>
- #include <linux/sched.h>
- #include <linux/wait.h>
- #include <linux/dma-mapping.h>
- #include <linux/string.h>
- #include <linux/interrupt.h>
- #include <mach/irqs.h>
-
-
- #define BUF_SZ 512*1024
- #define NO_DMA 0
- #define USE_DMA 1
- #define DMA0_BASE_ADDR 0x4B000000
- #define DMA1_BASE_ADDR 0x4B000040
- #define DMA2_BASE_ADDR 0x4B000080
- #define DMA3_BASE_ADDR 0x4B0000C0
-
- struct dma_regs {
- unsigned long disrc;
- unsigned long disrcc;
- unsigned long didst;
- unsigned long didstc;
- unsigned long dcon;
- unsigned long dstat;
- unsigned long dcsrc;
- unsigned long dcdst;
- unsigned long dmasktrig;
- };
-
- static DECLARE_WAIT_QUEUE_HEAD(dma_waith);
-
- volatile struct dma_regs *dma_regs;
- static dma_addr_t src_phys;
- static dma_addr_t dst_phys;
- static char *src;
- static char *dst;
- static struct cdev cdev;
- static int major;
- static struct class *cls;
- static volatile int ev_dma = 0;
-
- static int dma_ioctl (struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
- {
- int i;
-
- memset(src, 1, BUF_SZ);
- memset(dst, 0, BUF_SZ);
- switch (cmd) {
- case NO_DMA:
- {
- for(i=0; i<BUF_SZ; i++)
- dst[i] = src[i];
- if (0 == memcmp(src, dst, BUF_SZ))
- printk("(NO_DMA)Success to memcpy from source to destination.n");
- else
- printk("(NO_DMA)Failed to memcpy from source to destination.n");
- }
- break;
-
- case USE_DMA:
- {
- ev_dma = 1;
- /* 设置DMA相关寄存器 */
- * DISRC[30:0]= src_phys:base address of source data to transfer
- * DIDST[30:0]= dst_phys:base address of destination for the transfer
- * DISRCC[1] = 0 : the source is in the system bus (AHB)
- * DISRCC[0] = 0 : select the address increment.
- * DIDSTC[2] = 0 : interrupt will occur when TC reaches 0
- * DIDSTC[1] = 0 : the destination is in the system bus (AHB)
- * DIDSTC[0] = 0 : select the address increment
- * DCON[31] = 0 : demand mode will be selected
- * DCON[30] = 1 : DREQ and DACK are synchronized to HCLK (AHB clock)
- * DCON[29] = 1 : interrupt request is generated when all the transfer is done
- * DCON[28] = 0 : a unit transfer is performed
- * DCON[27] = 1 : whole service mode
- * DCON[26:24]=000: select DMA request source for each DMA
- * DCON[23] = 0 : S/W request mode is selected
- * DCON[22] = 0 : auto reload
- * DCON[21:20]= 00: data size(byte) to be transferred.
- * DCON[19:0] = BUF_SZ : initial transfer count
- * DMASKTRIG[1] = 1 : DMA channel is turned on
- * DMASKTRIG[0] = 1 : trigger the DMA channel in S/W request mode.
- */
- dma_regs->disrc = src_phys;
- dma_regs->didst = dst_phys;
- dma_regs->disrcc = (0<<1)|(0<<0);
- dma_regs->didstc = (0<<2)|(0<<1)|(0<<0);
- dma_regs->dcon = (0<<31)|(1<<30)|(1<<29)|(0<<28)|(1<<27)|(0<<24)|
- (0<<23)|(0<<22)|(0<<20)|(BUF_SZ<<0);
- /* 启动DMA */
- dma_regs->dmasktrig = (1<<1)|(1<<0);
- /* 休眠等待数据传输 */
- wait_event_interruptible(dma_waith, ev_dma);
- if (0 == memcmp(src, dst, BUF_SZ))
- printk("(USE_DMA)Success to memcpy from source to destination.n");
- else
- printk("(USE_DMA)Failed to memcpy from source to destination.n");
- }
- break;
- }
- return 0;
- }
-
- static struct file_operations fops =
- {
- .ioctl = dma_ioctl,
- };
-
- static irqreturn_t mydma_irq(int irq, void *dat)
- {
- ev_dma = 1;
- /* 数据传输完毕唤醒队列 */
- wake_up_interruptible(&dma_waith);
-
- return IRQ_HANDLED;
- }
-
- static int mydma_init(void)
- {
-
- dev_t devt;
- /* 分配源、目的 缓冲区 */
- src = dma_alloc_writecombine(NULL, BUF_SZ, &src_phys,GFP_KERNEL);
- if (NULL == src)
- {
- printk("src-dma alloc failed!n");
- return -ENOMEM;
- }
- dst = dma_alloc_writecombine(NULL, BUF_SZ, &dst_phys, GFP_KERNEL);
- if (NULL == dst)
- {
- printk("dst-dma alloc failedn");
- dma_free_writecombine(NULL, BUF_SZ, src, src_phys);
- return -ENOMEM;
- }
- /* 动态申请字符设备区域 */
- alloc_chrdev_region(&devt, 0, 1, "mydma");
- /* MAJOR得到主设备号*/
- major = MAJOR(devt);
- /* 初始化并添加字符设备 */
- cdev_init(&cdev, &fops);
- cdev_add(&cdev, devt, 1);
- /* 创建类 */
- cls = class_create(THIS_MODULE, "mycls");
- /* 创建类下的设备 */
- device_create(cls, NULL, devt, NULL, "mydma");
- /* 映射DMA寄存器 */
- dma_regs = ioremap(DMA3_BASE_ADDR, sizeof(struct dma_regs));
- /* 申请DMA中断*/
- request_irq(IRQ_DMA3, mydma_irq, 0, "dma3", 1);
-
- return 0;
-
- }
-
- static void mydma_exit(void)
- {
- free_irq(IRQ_DMA3, 1);
- iounmap(dma_regs);
- device_destroy(cls, MKDEV(major, 0));
- class_destroy(cls);
- cdev_del(&cdev);
- unregister_chrdev_region(MKDEV(major, 0), 1);
- dma_free_writecombine(NULL, BUF_SZ, src, src_phys);
- dma_free_writecombine(NULL, BUF_SZ, dst, dst_phys);
- return ;
- }
-
- module_init(mydma_init);
- module_exit(mydma_exit);
-
- MODULE_LICENSE("GPL");
测试程序:
点击(此处)折叠或打开
- #include <stdio.h>
- #include <string.h>
- #include <fcntl.h>
-
- #define NO_DMA 0
- #define USE_DMA 1
-
- int main(int argc, char *argv[])
- {
- int cmd, fd;
-
- if (argc != 2)
- {
- printf("%s <nodma | usedma>n", argv[0]);
- return -1;
- }
- fd = open("/dev/mydma", O_RDWR);
- if(fd < 0)
- printf("can not open /dev/mydman");
- if(0 == strcmp(argv[1], "nodma"))
- {
- cmd = NO_DMA;
- }
- else if(0 == strcmp(argv[1], "usedma"))
- {
- cmd = USE_DMA;
- }
- else
- {
- printf("%s <nodma | usedma>n", argv[0]);
- return -1;
- }
- while(1)
- {
- ioctl(fd, cmd);
- }
- return 0;
- }
2012-05-10 16:05 发表于百度空间,今搬至CU。
相关热门文章
给主人留下些什么吧!~~
评论热议