20150429 S3C实现DMA驱动程序编写

20150429 S3C实现DMA驱动程序编写

2015-04-29 Lover雪儿

在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 src\n");
 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 dst\n");
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 <linux/module.h>
 2 #include <linux/kernel.h>
 3 #include <linux/fs.h>
 4 #include <linux/init.h>
 5 #include <linux/delay.h>
 6 #include <linux/irq.h>
 7 #include <asm/uaccess.h>
 8 #include <asm/irq.h>
 9 #include <asm/io.h>
10 #include <asm/arch/regs-gpio.h>
11 #include <asm/hardware.h>
12 #include <linux/poll.h>
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 src\n");
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 dst\n");
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.c

二.增加不使用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 OK\n");
16             }
17             else
18             {
19                 printk("MEM_CPY_DMA ERROR\n");
20             }
21             break;
22         }
23         case MEM_CPY_DMA :
24         {
25             break;
26         }
27     }
28
29     return 0;
30 }

如程序所示,再ioctl函数中不适用DMA的增加内存拷贝功能.

附上驱动程序2

  1 #include <linux/module.h>
  2 #include <linux/kernel.h>
  3 #include <linux/fs.h>
  4 #include <linux/init.h>
  5 #include <linux/delay.h>
  6 #include <linux/irq.h>
  7 #include <asm/uaccess.h>
  8 #include <asm/irq.h>
  9 #include <asm/io.h>
 10 #include <asm/arch/regs-gpio.h>
 11 #include <asm/hardware.h>
 12 #include <linux/poll.h>
 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 OK\n");
 45             }
 46             else
 47             {
 48                 printk("MEM_CPY_DMA ERROR\n");
 49             }
 50             break;
 51         }
 52
 53         case MEM_CPY_DMA :
 54         {
 55             break;
 56         }
 57     }
 58
 59     return 0;
 60 }
 61
 62 static struct file_operations dma_fops = {
 63     .owner  = THIS_MODULE,
 64     .ioctl  = s3c_dma_ioctl,
 65 };
 66
 67 static int s3c_dma_init(void)
 68 {
 69     /* 分配SRC, DST对应的缓冲区 */
 70     src = dma_alloc_writecombine(NULL, BUF_SIZE, &src_phys, GFP_KERNEL);
 71     if (NULL == src)
 72     {
 73         printk("can‘t alloc buffer for src\n");
 74         return -ENOMEM;
 75     }
 76
 77     dst = dma_alloc_writecombine(NULL, BUF_SIZE, &dst_phys, GFP_KERNEL);
 78     if (NULL == dst)
 79     {
 80         dma_free_writecombine(NULL, BUF_SIZE, src, src_phys);
 81         printk("can‘t alloc buffer for dst\n");
 82         return -ENOMEM;
 83     }
 84
 85     major = register_chrdev(0, "s3c_dma", &dma_fops);
 86
 87     /* 为了自动创建设备节点 */
 88     cls = class_create(THIS_MODULE, "s3c_dma");
 89     class_device_create(cls, NULL, MKDEV(major, 0), NULL, "dma"); /* /dev/dma */
 90
 91     return 0;
 92 }
 93
 94 static void s3c_dma_exit(void)
 95 {
 96     class_device_destroy(cls, MKDEV(major, 0));
 97     class_destroy(cls);
 98     unregister_chrdev(major, "s3c_dma");
 99     dma_free_writecombine(NULL, BUF_SIZE, src, src_phys);
100     dma_free_writecombine(NULL, BUF_SIZE, dst, dst_phys);
101 }
102
103 module_init(s3c_dma_init);
104 module_exit(s3c_dma_exit);
105
106 MODULE_LICENSE("GPL");

dma_2.c

附上测试程序2.

 1 #include <stdio.h>
 2 #include <sys/types.h>
 3 #include <sys/stat.h>
 4 #include <fcntl.h>
 5 #include <sys/ioctl.h>
 6 #include <string.h>
 7
 8 /* ./dma_test nodma
 9  * ./dma_test dma
10  */
11 #define MEM_CPY_NO_DMA  0
12 #define MEM_CPY_DMA     1
13
14 void print_usage(char *name)
15 {
16     printf("Usage:\n");
17     printf("%s <nodma | dma>\n", name);
18 }
19
20
21 int main(int argc, char **argv)
22 {
23     int fd;
24
25      if (argc != 2)
26     {
27         print_usage(argv[0]);
28         return -1;
29     }
30
31     fd = open("/dev/dma", O_RDWR);
32     if (fd < 0)
33     {
34         printf("can‘t open /dev/dma\n");
35         return -1;
36     }
37
38     if (strcmp(argv[1], "nodma") == 0)
39     {
40         while (1)
41         {
42             ioctl(fd, MEM_CPY_NO_DMA);
43         }
44     }
45     else if (strcmp(argv[1], "dma") == 0)
46     {
47         while (1)
48         {
49             ioctl(fd, MEM_CPY_DMA);
50         }
51     }
52     else
53     {
54         print_usage(argv[0]);
55         return -1;
56     }
57     return 0;
58 }

dma_test.c

三.映射s3c的DMA内存地址

测试程序时,不知道大家有没有发现,当我们运行test测试程序时,我们的拷贝进程占用了全部的CPU,以至于我们想运行一条命令都要等好久才能实现,

为了解决它,我们就引入了DMA,接下来,我们就真正开始DMA的编程

 1 #define DMA0_BASE_ADDR  0x4B000000
 2 #define DMA1_BASE_ADDR  0x4B000040
 3 #define DMA2_BASE_ADDR  0x4B000080
 4 #define DMA3_BASE_ADDR  0x4B0000C0
 5
 6 struct s3c_dma_regs {
 7     unsigned long disrc;
 8     unsigned long disrcc;
 9     unsigned long didst;
10     unsigned long didstc;
11     unsigned long dcon;
12     unsigned long dstat;
13     unsigned long dcsrc;
14     unsigned long dcdst;
15     unsigned long dmasktrig;
16 };

如程序中所示:首先定义DMA的四个通道的基地址,接着定义一个s3c的dma的寄存器结构体.

分别再入口函数中映射DMA的内存IO端口,此处我们使用DMA0,当然如果要使用其他的DMA,类似.

在入口函数中映射:

dma_regs = ioremap(DMA0_BASE_ADDR, sizeof(struct s3c_dma_regs));

在出口函数中解除DMA映射.

iounmap(dma_regs);

四.注册DMA中断

前面我们已经映好DMA的内存地址了.

接下来,要想DMA工作,还需要对齐进行注册DMA中断和DMA配置.

在入口函数中注册DMA中断,再出口函数中释放DMA中断

在入口函数中注册中断:

1 if (request_irq(IRQ_DMA3, s3c_dma_irq, 0, "s3c_dma", 1))
2     {
3         printk("can‘t request_irq for DMA\n");
4         return -EBUSY;
5     }

在出口函数中释放中断:

free_irq(IRQ_DMA3, 1);

当用户程序中定义为 MEM_CPY_DMA 使用DMA传输时,便会在ioctl函数中进入case MEM_CPY_DMA :中.

接着我们便在其中配置号DMA的源.目的参数,接着便启动传输,CPU则进入休眠状态,让出CPU供其他进程使用.当DMA拷贝完成时,便会触发中断,从而唤醒.

ioctl函数的部分程序如下面所示:

 1         case MEM_CPY_DMA :
 2         {
 3             ev_dma = 0;
 4
 5             /* 把源,目的,长度告诉DMA */
 6             dma_regs->disrc      = src_phys;        /* 源的物理地址 */
 7             dma_regs->disrcc     = (0<<1) | (0<<0); /* 源位于AHB总线, 源地址递增 */
 8             dma_regs->didst      = dst_phys;        /* 目的的物理地址 */
 9             dma_regs->didstc     = (0<<2) | (0<<1) | (0<<0); /* 目的位于AHB总线, 目的地址递增 */
10             dma_regs->dcon       = (1<<30)|(1<<29)|(0<<28)|(1<<27)|(0<<23)|(0<<20)|(BUF_SIZE<<0);  /* 使能中断,单个传输,软件触发, */
11
12             /* 启动DMA */
13             dma_regs->dmasktrig  = (1<<1) | (1<<0);
14
15             /* 如何知道DMA什么时候完成? */
16             /* 休眠 */
17             wait_event_interruptible(dma_waitq, ev_dma);
18
19             if (memcmp(src, dst, BUF_SIZE) == 0)
20             {
21                 printk("MEM_CPY_DMA OK\n");
22             }
23             else
24             {
25                 printk("MEM_CPY_DMA ERROR\n");
26             }
27
28             break;
29         }

中断服务程序:

1 static irqreturn_t s3c_dma_irq(int irq, void *devid)
2 {
3     /* 唤醒 */
4     ev_dma = 1;
5     wake_up_interruptible(&dma_waitq);   /* 唤醒休眠的进程 */
6     return IRQ_HANDLED;
7 }

附上驱动程序3:

  1 #include <linux/module.h>
  2 #include <linux/kernel.h>
  3 #include <linux/fs.h>
  4 #include <linux/init.h>
  5 #include <linux/delay.h>
  6 #include <linux/irq.h>
  7 #include <asm/uaccess.h>
  8 #include <asm/irq.h>
  9 #include <asm/io.h>
 10 #include <asm/arch/regs-gpio.h>
 11 #include <asm/hardware.h>
 12 #include <linux/poll.h>
 13 #include <linux/dma-mapping.h>
 14
 15 #define MEM_CPY_NO_DMA  0
 16 #define MEM_CPY_DMA     1
 17
 18 #define BUF_SIZE  (512*1024)
 19
 20 #define DMA0_BASE_ADDR  0x4B000000
 21 #define DMA1_BASE_ADDR  0x4B000040
 22 #define DMA2_BASE_ADDR  0x4B000080
 23 #define DMA3_BASE_ADDR  0x4B0000C0
 24
 25 struct s3c_dma_regs {
 26     unsigned long disrc;
 27     unsigned long disrcc;
 28     unsigned long didst;
 29     unsigned long didstc;
 30     unsigned long dcon;
 31     unsigned long dstat;
 32     unsigned long dcsrc;
 33     unsigned long dcdst;
 34     unsigned long dmasktrig;
 35 };
 36
 37
 38 static int major = 0;
 39
 40 static char *src;
 41 static u32 src_phys;
 42
 43 static char *dst;
 44 static u32 dst_phys;
 45
 46 static struct class *cls;
 47
 48 static volatile struct s3c_dma_regs *dma_regs;
 49
 50 static DECLARE_WAIT_QUEUE_HEAD(dma_waitq);
 51 /* 中断事件标志, 中断服务程序将它置1,ioctl将它清0 */
 52 static volatile int ev_dma = 0;
 53
 54 static int s3c_dma_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
 55 {
 56     int i;
 57
 58     memset(src, 0xAA, BUF_SIZE);
 59     memset(dst, 0x55, BUF_SIZE);
 60
 61     switch (cmd)
 62     {
 63         case MEM_CPY_NO_DMA :
 64         {
 65             for (i = 0; i < BUF_SIZE; i++)
 66                 dst[i] = src[i];
 67             if (memcmp(src, dst, BUF_SIZE) == 0)
 68             {
 69                 printk("MEM_CPY_NO_DMA OK\n");
 70             }
 71             else
 72             {
 73                 printk("MEM_CPY_DMA ERROR\n");
 74             }
 75             break;
 76         }
 77
 78         case MEM_CPY_DMA :
 79         {
 80             ev_dma = 0;
 81
 82             /* 把源,目的,长度告诉DMA */
 83             dma_regs->disrc      = src_phys;        /* 源的物理地址 */
 84             dma_regs->disrcc     = (0<<1) | (0<<0); /* 源位于AHB总线, 源地址递增 */
 85             dma_regs->didst      = dst_phys;        /* 目的的物理地址 */
 86             dma_regs->didstc     = (0<<2) | (0<<1) | (0<<0); /* 目的位于AHB总线, 目的地址递增 */
 87             dma_regs->dcon       = (1<<30)|(1<<29)|(0<<28)|(1<<27)|(0<<23)|(0<<20)|(BUF_SIZE<<0);  /* 使能中断,单个传输,软件触发, */
 88
 89             /* 启动DMA */
 90             dma_regs->dmasktrig  = (1<<1) | (1<<0);
 91
 92             /* 如何知道DMA什么时候完成? */
 93             /* 休眠 */
 94             wait_event_interruptible(dma_waitq, ev_dma);
 95
 96             if (memcmp(src, dst, BUF_SIZE) == 0)
 97             {
 98                 printk("MEM_CPY_DMA OK\n");
 99             }
100             else
101             {
102                 printk("MEM_CPY_DMA ERROR\n");
103             }
104
105             break;
106         }
107     }
108
109     return 0;
110 }
111
112 static struct file_operations dma_fops = {
113     .owner  = THIS_MODULE,
114     .ioctl  = s3c_dma_ioctl,
115 };
116
117 static irqreturn_t s3c_dma_irq(int irq, void *devid)
118 {
119     /* 唤醒 */
120     ev_dma = 1;
121     wake_up_interruptible(&dma_waitq);   /* 唤醒休眠的进程 */
122     return IRQ_HANDLED;
123 }
124
125 static int s3c_dma_init(void)
126 {
127     if (request_irq(IRQ_DMA3, s3c_dma_irq, 0, "s3c_dma", 1))
128     {
129         printk("can‘t request_irq for DMA\n");
130         return -EBUSY;
131     }
132
133     /* 分配SRC, DST对应的缓冲区 */
134     src = dma_alloc_writecombine(NULL, BUF_SIZE, &src_phys, GFP_KERNEL);
135     if (NULL == src)
136     {
137         printk("can‘t alloc buffer for src\n");
138         free_irq(IRQ_DMA3, 1);
139         return -ENOMEM;
140     }
141
142     dst = dma_alloc_writecombine(NULL, BUF_SIZE, &dst_phys, GFP_KERNEL);
143     if (NULL == dst)
144     {
145         free_irq(IRQ_DMA3, 1);
146         dma_free_writecombine(NULL, BUF_SIZE, src, src_phys);
147         printk("can‘t alloc buffer for dst\n");
148         return -ENOMEM;
149     }
150
151     major = register_chrdev(0, "s3c_dma", &dma_fops);
152
153     /* 为了自动创建设备节点 */
154     cls = class_create(THIS_MODULE, "s3c_dma");
155     class_device_create(cls, NULL, MKDEV(major, 0), NULL, "dma"); /* /dev/dma */
156
157     dma_regs = ioremap(DMA3_BASE_ADDR, sizeof(struct s3c_dma_regs));
158
159     return 0;
160 }
161
162 static void s3c_dma_exit(void)
163 {
164     iounmap(dma_regs);
165     class_device_destroy(cls, MKDEV(major, 0));
166     class_destroy(cls);
167     unregister_chrdev(major, "s3c_dma");
168     dma_free_writecombine(NULL, BUF_SIZE, src, src_phys);
169     dma_free_writecombine(NULL, BUF_SIZE, dst, dst_phys);
170     free_irq(IRQ_DMA3, 1);
171 }
172
173 module_init(s3c_dma_init);
174 module_exit(s3c_dma_exit);
175
176 MODULE_LICENSE("GPL");

dma_3.c

附上测试程序3:

 1 #include <stdio.h>
 2 #include <sys/types.h>
 3 #include <sys/stat.h>
 4 #include <fcntl.h>
 5 #include <sys/ioctl.h>
 6 #include <string.h>
 7
 8 /* ./dma_test nodma
 9  * ./dma_test dma
10  */
11 #define MEM_CPY_NO_DMA  0
12 #define MEM_CPY_DMA     1
13
14 void print_usage(char *name)
15 {
16     printf("Usage:\n");
17     printf("%s <nodma | dma>\n", name);
18 }
19
20
21 int main(int argc, char **argv)
22 {
23     int fd;
24
25      if (argc != 2)
26     {
27         print_usage(argv[0]);
28         return -1;
29     }
30
31     fd = open("/dev/dma", O_RDWR);
32     if (fd < 0)
33     {
34         printf("can‘t open /dev/dma\n");
35         return -1;
36     }
37
38     if (strcmp(argv[1], "nodma") == 0)
39     {
40         while (1)
41         {
42             ioctl(fd, MEM_CPY_NO_DMA);
43         }
44     }
45     else if (strcmp(argv[1], "dma") == 0)
46     {
47         while (1)
48         {
49             ioctl(fd, MEM_CPY_DMA);
50         }
51     }
52     else
53     {
54         print_usage(argv[0]);
55         return -1;
56     }
57     return 0;
58 }

dma_test.c

五.总结DMA工作流程.

简单来说,我觉得DMA编程总共分为配置和运行两个步骤.

配置:

①注册中断

②分配供模拟拷贝数据的源.目的地址的内存空间.

③注册字符设备

④映射ioremapDMA的IO空间

运行:

①应用程序调用ioctl(fd,MEM_CPY_DMA),进入case语句

②在case语句中配置号DMA传输数据所需要的源,目的,大小,便启动DMA传输.

③启动DMA传输后,程序进入可中断的休眠,让出CPU

④一旦DMA传输完毕,便会触发中断,再中断中唤醒,然后打印MEM_CPY_DMA OK告诉应用程序DMA传输成功了.

时间: 2024-10-10 04:59:01

20150429 S3C实现DMA驱动程序编写的相关文章

转:Linux网卡驱动程序编写

Linux网卡驱动程序编写 [摘自 LinuxAID] 工作需要写了我们公司一块网卡的Linux驱动程序.经历一个从无到有的过程,深感技术交流的重要.Linux作为挑战微软垄断的强有力武器,日益受到大家的喜爱.真希望她能在中国迅速成长.把程序文档贴出来,希望和大家探讨Linux技术和应用,促进Linux在中国的普及. Linux操作系统网络驱动程序编写 一.Linux系统设备驱动程序概述 1.1 Linux设备驱动程序分类 1.2 编写驱动程序的一些基本概念 二.Linux系统网络设备驱动程序

ok6410之led驱动程序编写

led驱动程序编写 本文主要包含三部分,led驱动程序led.c编写,编译驱动程序的makefile的编写,以及使用驱动程序的应用程序led_app的编写 一.led.c编写 1 #include <linux/module.h> 2 #include <linux/init.h> 3 #include <linux/cdev.h> 4 #include <linux/fs.h> 5 #include <linux/io.h> 6 #includ

20150409 IMX257 USB鼠标驱动程序编写

20150409 IMX257 USB鼠标驱动程序编写 2015-03-14 Lover雪儿 USB驱动程序包括为USB总线驱动程序以及USB设备驱动程序. USB总线驱动程序的功能是: 1.识别 2.找到匹配的设备驱动程序 3.提供USB读写函数(不知道数据的含义) USB设备驱动程序功能是: 分析USB的数据,上报相应的事件 今天,我们来实现一个USB鼠标的设备驱动程序,让鼠标的左键模拟为键盘的L键,鼠标的右键模拟为键盘的S键,鼠标的中键模拟为键盘的ENTER键,接下来我们先来实现一个简单程

DM9000C网卡驱动程序编写与测试

一般网卡驱动程序厂商会给我们提供一份模板驱动,我们的工作就是需要根据自己的需要更改这个模板驱动 1.DM9000C的硬件连接 硬件连接图如下所示:它接在S3C2440的BANK4内存控制器上,它只占用8个字节的长度,并且是16bit的位宽. 下面介绍一下DM9000C的主要引脚的功能:SD0-SD15位16bit的数据引脚接口:IOR为读使能信号,低电平有效:IOW为写使能信号,低电平有效:CS为片选信号,低电平有效:CMD为数据与索引选择信号,高电平表数据,低电平表索引,它连接到S3C2440

20150424 adapter实现i2c驱动程序编写

2015-04-24 Lover雪儿 i2c的驱动程序可以由旧探测方法(adapt)和新探测方法(probe)这两种方法实现. 在i2c_driver中,adapt老方法使用的是attach_adapter作为探测函数,而在新方法中使用的是probe作为探测函数. 1 I2C设备驱动结构: 2 struct i2c_driver { 3 unsigned int class; 4 5 /* 添加和卸载I2C设备,老版本*/ 6 int (*attach_adapter)(struct i2c_a

IMX257实现Ramblock驱动程序编写

2015-04-12 Lover雪儿 记得以前三月份就开始学习块设备,但是一直弄不出来,今天我们接着以前写的块设备驱动,抱着坚定的信心把它实现. 今天,我们再内存中申请一片内存,模拟作为块设备,程序如下: 程序一:简单的一个小程序 1.定义gendisk结构体与request_queue请求队列结构体,以及file-operation结构体 gendisk结构体,主要是用于定义与内核,硬件有关的一些重要信息,还有就是,告诉内核定义请求队列的结构体以及操作函数的结构体. 请求队列:主要是提供读写能

Linux中断处理驱动程序编写

本章节我们一起来探讨一下Linux中的中断: http://blog.csdn.net/gotosola/article/details/7422072 中断处理 http://www.cnblogs.com/tianshuai11/archive/2012/04/20/2477168.html 里边有自动探测中断号: http://blog.csdn.net/en_wang/article/details/6726421 当目标设备有能力告知驱动它要使用的中断号时,自动探测中断号只是意味着探测

Linux下编写驱动程序(VFS)

转:http://hi.baidu.com/firstm25/item/8fe022155e1fa78988a9568f 摘要:设备驱动程序是操作系统内核与机器硬件之间的接口.设备驱动程序为应用程序屏蔽了硬件的细节.那么驱动程序如何书写实现这一接口功能是本文讨论的重点,并以一简单的驱动程序介绍书写细节. 在用户进程调用驱动程序时,系统进入核心态,这时不再是抢先式调度.(应用程序一般是在用户态下进行)也就是说系统必须在驱动程序的子函数返回后才能进行其它的工作,即驱动程序不能进入死循环. 字符型设备

戴文的Linux内核专题:03 驱动程序【转】

转自:http://www.lai18.com/content/432194.html 驱动程序是使内核能够沟通和操作硬件或协议(规则和标准)的小程序.没有驱动程序,内核不知道如何与硬件沟通或者处理协议(内核实际上先发送指令给BIOS,然后BIOS传给硬件). Linux的内核代码在驱动程序文件夹中以源代码的形式包含了许多驱动程序.驱动文件夹中的每个文件夹会在下面说明.在配置和 编译内核时,这样有助于你了解驱动程序.否则,用户可能会在编译时加入不必要的或者漏掉重要的驱动.驱动代码通常会包含一个单