在IMX257上只有SDMA,SDMA比DMA的功能更加强大,但是为了学习的目的,如果直接学习SDMA,可能会不能消化,
所以,此处,我们从简单到复杂,从S3C2440的DMA驱动程序开始学习,等学懂它之后,我们再进军IMX257的SDMA.
一.一个简单的程序框架
1.定义一些指针
1 static int major = 0;
2
3 #define MEM_CPY_NO_DMA 0
4 #define MEM_CPY_DMA 1
5
6 static char *src;
7 static u32 src_phys;
8
9 static char *dst;
10 static u32 dst_phys;
11
12 static struct class *cls;
13
14 #define BUF_SIZE (512*1024)
上面代码中主要定义了主设备号,目的地址,源地址等.
2.定义字符设备的file_operation结构体
1 static int s3c_dma_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
2 {
3 switch (cmd)
4 {
5 case MEM_CPY_NO_DMA :
6 {
7 break;
8 }
9 case MEM_CPY_DMA :
10 {
11 break;
12 }
13 }
14 return 0;
15 }
16
17 static struct file_operations dma_fops = {
18 .owner = THIS_MODULE,
19 .ioctl = s3c_dma_ioctl,
20 };
在case中,分别定义CPU拷贝数据和DMA拷贝数据两种情况.
3.入口函数
1 static int s3c_dma_init(void)
2 {
3 /* 分配SRC, DST对应的缓冲区 */
4 src = dma_alloc_writecombine(NULL, BUF_SIZE, &src_phys, GFP_KERNEL);
5 if (NULL == src)
6 {
7 printk('can't alloc buffer for srcn');
8 return -ENOMEM;
9 }
10
11 dst = dma_alloc_writecombine(NULL, BUF_SIZE, &dst_phys, GFP_KERNEL);
12 if (NULL == dst)
13 {
14 dma_free_writecombine(NULL, BUF_SIZE, src, src_phys);
15 printk('can't alloc buffer for dstn');
16 return -ENOMEM;
17 }
18
19 major = register_chrdev(0, 's3c_dma', &dma_fops);
20
21 /* 为了自动创建设备节点 */
22 cls = class_create(THIS_MODULE, 's3c_dma');
23 class_device_create(cls, NULL, MKDEV(major, 0), NULL, 'dma'); /* /dev/dma */
24
25 return 0;
26 }
上面代码中:首先分配了源.目的地址的内存缓冲区,接着就是申请字符设备,自动创建字符设备节点.
4.出口函数
1 static void s3c_dma_exit(void)
2 {
3 class_device_destroy(cls, MKDEV(major, 0));
4 class_destroy(cls);
5 unregister_chrdev(major, 's3c_dma');
6 dma_free_writecombine(NULL, BUF_SIZE, src, src_phys);
7 dma_free_writecombine(NULL, BUF_SIZE, dst, dst_phys);
8 }
销毁字符设备的类,卸载字符设备,接着就是释放前面申请的源.目的地址的内存.
附上驱动代码1:
1 #include 2 #include 3 #include 4 #include 5 #include 6 #include 7 #include 8 #include 9 #include 10 #include 11 #include 12 #include 13 14 static int major = 0; 15 16 #define MEM_CPY_NO_DMA 0 17 #define MEM_CPY_DMA 1 18 19 static char *src; 20 static u32 src_phys; 21 22 static char *dst; 23 static u32 dst_phys; 24 25 static struct class *cls; 26 27 #define BUF_SIZE (512*1024) 28 29 static int s3c_dma_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) 30 { 31 switch (cmd) 32 { 33 case MEM_CPY_NO_DMA : 34 { 35 break; 36 } 37 38 case MEM_CPY_DMA : 39 { 40 break; 41 } 42 } 43 44 return 0; 45 } 46 47 static struct file_operations dma_fops = { 48 .owner = THIS_MODULE, 49 .ioctl = s3c_dma_ioctl, 50 }; 51 52 static int s3c_dma_init(void) 53 { 54 /* 分配SRC, DST对应的缓冲区 */ 55 src = dma_alloc_writecombine(NULL, BUF_SIZE, &src_phys, GFP_KERNEL); 56 if (NULL == src) 57 { 58 printk('can't alloc buffer for srcn'); 59 return -ENOMEM; 60 } 61 62 dst = dma_alloc_writecombine(NULL, BUF_SIZE, &dst_phys, GFP_KERNEL); 63 if (NULL == dst) 64 { 65 dma_free_writecombine(NULL, BUF_SIZE, src, src_phys); 66 printk('can't alloc buffer for dstn'); 67 return -ENOMEM; 68 } 69 70 major = register_chrdev(0, 's3c_dma', &dma_fops); 71 72 /* 为了自动创建设备节点 */ 73 cls = class_create(THIS_MODULE, 's3c_dma'); 74 class_device_create(cls, NULL, MKDEV(major, 0), NULL, 'dma'); /* /dev/dma */ 75 76 return 0; 77 } 78 79 static void s3c_dma_exit(void) 80 { 81 class_device_destroy(cls, MKDEV(major, 0)); 82 class_destroy(cls); 83 unregister_chrdev(major, 's3c_dma'); 84 dma_free_writecombine(NULL, BUF_SIZE, src, src_phys); 85 dma_free_writecombine(NULL, BUF_SIZE, dst, dst_phys); 86 } 87 88 module_init(s3c_dma_init); 89 module_exit(s3c_dma_exit); 90 91 MODULE_LICENSE('GPL'); 二.增加不使用DMA的内存拷贝功能. 1 static int s3c_dma_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) 2 { 3 int i; 4 memset(src, 0xAA, BUF_SIZE); 5 memset(dst, 0x55, BUF_SIZE); 6 7 switch (cmd) 8 { 9 case MEM_CPY_NO_DMA : 10 { 11 for (i = 0; i < BUF_SIZE; i++) 12 dst[i] = src[i]; 13 if (memcmp(src, dst, BUF_SIZE) == 0) 14 { 15 printk('MEM_CPY_NO_DMA OKn'); 16 } 17 else 18 { 19 printk('MEM_CPY_DMA ERRORn'); 20 } 21 break; 22 } 23 case MEM_CPY_DMA : 24 { 25 break; 26 } 27 } 28 29 return 0; 30 } 如程序所示,再ioctl函数中不适用DMA的增加内存拷贝功能. 附上驱动程序2 1 #include 2 #include 3 #include 4 #include 5 #include 6 #include 7 #include 8 #include 9 #include 10 #include 11 #include 12 #include 13 14 static int major = 0; 15 16 #define MEM_CPY_NO_DMA 0 17 #define MEM_CPY_DMA 1 18 19 static char *src; 20 static u32 src_phys; 21 22 static char *dst; 23 static u32 dst_phys; 24 25 static struct class *cls; 26 27 #define BUF_SIZE (512*1024) 28 29 static int s3c_dma_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) 30 { 31 int i; 32 33 memset(src, 0xAA, BUF_SIZE); 34 memset(dst, 0x55, BUF_SIZE); 35 36 switch (cmd) 37 { 38 case MEM_CPY_NO_DMA : 39 { 40 for (i = 0; i < BUF_SIZE; i++) 41 dst[i] = src[i]; 42 if (memcmp(src, dst, BUF_SIZE) == 0) 43 { 44 printk('MEM_CPY_NO_DMA OKn'); 45 } 46 else 47 { 48 printk('MEM_CPY_DMA ERRORn'); 49 } 50 break; 51 } 52 53 case MEM_CPY_DMA :
上一篇:S3C2440实现dm9000网卡驱动程序移植
下一篇:S3C2440 nand_flash驱动程序
推荐阅读最新更新时间:2024-11-05 13:15
设计资源 培训 开发板 精华推荐
- LTC4055 具有电源路径控制的独立 USB 锂离子电池充电器
- AM2G-4809SH30Z 9V 2 瓦 DC-DC 转换器的典型应用
- 【训练营】四足机器狗
- LTC3633AIFE-1 1.5V 1MHz 双相降压稳压器的典型应用电路
- KSZ8081MLX 10Base-T/100Base-TX物理层收发器典型应用
- 使用 Diodes Incorporated 的 ZLDO330 的参考设计
- CPU复位电路AZ7045RTR电压检测器典型应用电路
- 1W,一个 LED 大功率 LED 驱动器,用于 LCD 背光
- #第六届立创电赛#TPA3116数字功放
- 【涂鸦智能】DIY多模网关(WiFi+蓝牙+Zigbee)