抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

整理了一下字符设备驱动的模版文件:

1 模版

1.1 字符驱动模版

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/ide.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/gpio.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_gpio.h>
#include <asm/mach/map.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <linux/atomic.h>

#define demo_CNT 1 /* 设备号个数 */
#define demo_NAME "dmeo" /* 名字 */

struct demo_dev
{
dev_t devid; /* 设备号 */
int major; /* 主设备号 */
int minor; /* 次设备号 */

struct cdev cdev; /* cdev */

struct class *class; /* 类 */
struct device *device; /* 设备 */
struct device_node *nd; /* 设备节点 */
int demo_gpio; /* 使用的GPIO编号 */
};

struct demo_dev demo;


static int demo_open(struct inode *inode, struct file *filp)
{
filp->private_data = &demo;
return 0;
}
static int demo_release(struct inode *inode,struct file *filp)
{

return 0;
}

static ssize_t demo_write(struct file *filp,const char __user *buf,size_t count,loff_t *offt)
{


return 0;
}

static ssize_t demo_read(struct file *filp,char __user *buf,size_t count,loff_t *ppos)
{
//struct demo_dev *dev = filp->private_data;

return 0;
}

/* 1.操作集 */
static const struct file_operations demo_fops =
{
.owner = THIS_MODULE,
.open = demo_open,
.release = demo_release,
.write = demo_write,
.read = demo_read,
};


static int __init demo_init(void)
{
int ret;

/* 1.注册字符设备驱动*/
demo.major = 0;
if (demo.major)
{
demo.devid = MKDEV(demo.major, 0);
register_chrdev_region(demo.devid,demo_CNT,demo_NAME);
}
else{
ret = alloc_chrdev_region(&demo.devid,0,demo_CNT,demo_NAME);
demo.major = MAJOR(demo.devid);
demo.minor = MINOR(demo.devid);
}
printk("major = %d,minor = %d\r\n",demo.major,demo.minor);

if(ret < 0)
{
printk("fail devid\r\n");
goto fail_devid;
}

/* 2.初始化cdev*/
demo.cdev.owner = THIS_MODULE;
cdev_init(&demo.cdev,&demo_fops);

/* 3.添加设备 */
ret = cdev_add(&demo.cdev,demo.devid,demo_CNT);
if (ret < 0)
{
printk("fail cdevadd\r\n");
goto fail_cdevadd;
}

/* 4.创建类 */
demo.class = class_create(THIS_MODULE,demo_NAME);
if (IS_ERR(demo.class))
{
printk("fail class\r\n");
ret = PTR_ERR(demo.class);
goto fail_class;
}

/* 5.创建设备 */
demo.device = device_create(demo.class,NULL,demo.devid,NULL,demo_NAME);
if (IS_ERR(demo.device))
{
printk("fail device\r\n");
ret = PTR_ERR(demo.device);
goto fail_device;
}
return 0;

fail_device:
class_destroy(demo.class);
fail_class:
cdev_del(&demo.cdev);
fail_cdevadd:
unregister_chrdev_region(demo.devid,demo_CNT);
fail_devid:
return ret;
}

static void __exit demo_exit(void)
{
//注销字符设备驱动
cdev_del(&demo.cdev);
unregister_chrdev_region(demo.devid,demo_CNT);
device_destroy(demo.class,demo.devid);
class_destroy(demo.class);

printk("demo exit!\r\n");
}

module_init(demo_init);
module_exit(demo_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("zwl");

2 模块模版

2.1 led

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
static int led_init(struct  timer_dev *dev)
{
int ret = 0;

dev->nd = of_find_node_by_path("/gpioled");

if (dev->nd == NULL)
{
printk("can't find node\r\n");
ret = -EINVAL;
goto fail_nd;
}

dev->led_gpio = of_get_named_gpio(dev->nd,"led-gpios",0);

if(dev->led_gpio < 0)
{
printk("can't find gpio\r\n");
ret = -EINVAL;
goto fail_gpio;
}

ret = gpio_request(dev->led_gpio,"led");
if (ret)
{
printk("can't request gpio %d\r\n",dev->led_gpio);
ret = -EBUSY;
goto fail_request;
}

ret = gpio_direction_output(dev->led_gpio,1); //关灯
if (ret < 0)
{
printk("can't set gpio\r\n");
ret = -EINVAL;
goto fail_set;
}
return 0;

fail_set:
gpio_free(dev->led_gpio);
fail_request:
fail_gpio:
fail_nd:
return ret;
}

2.2 key

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
static int keyio_init(struct im6uirq_dev *dev)
{
int ret;
int i;
/* 1.按键初始化 */
dev->nd = of_find_node_by_path("/key");
if (dev->nd == NULL)
{
printk("fail find nd\r\n");
ret = -EINVAL;
goto fail_nd;
}

for (i = 0; i < KEY_NUM; i++)
{
ret = dev->irq_key[i].gpio = of_get_named_gpio(dev->nd,"key-gpios",i);
if (ret < 0){
printk("can't get key%d\r\n",i);
goto fail_get_gpio;
}
}

for (i = 0; i < KEY_NUM; i++)
{
memset(dev->irq_key[i].name,0,sizeof(dev->irq_key[i].name)); /* 缓冲区清零 */
sprintf(dev->irq_key[i].name,"key%d",i);
gpio_request(dev->irq_key[i].gpio,dev->irq_key[i].name);
gpio_direction_input(dev->irq_key[i].gpio);

dev->irq_key[i].irqnum = gpio_to_irq(dev->irq_key[i].gpio); /* 获取中断号 */
#if 0
dev->irq_key[i].irqnum = irq_of_parse_and_map(dev->nd,i);
#endif
}

dev->irq_key[0].handler = key0_irq_handler;
dev->irq_key[0].value = KEY0VALUE;
/* 2.按键中断初始化 */
for(i = 0; i < KEY_NUM; i++)
{
ret = request_irq(dev->irq_key[i].irqnum,dev->irq_key[i].handler,
IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
dev->irq_key[i].name,&im6uirq);

if (ret)
{
printk("request %d irq failed\r\n",dev->irq_key[i].irqnum);
ret = -EINVAL;
goto fail_requese_irq;
}
tasklet_init(&dev->irq_key[0].tasklet,key_tasklet,(unsigned long)dev);
}


init_timer(&dev->timer);
dev->timer.function = timer_func;

return 0;
fail_requese_irq:
for (i = 0; i < KEY_NUM; i++){
gpio_free(dev->irq_key[i].gpio);
}
fail_get_gpio:
fail_nd:
return ret;
}

2.3 TIMER

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
    init_timer(&timer.timer);
timer.timerperiod = 500;
timer.timer.function = timer_func;
timer.timer.expires = jiffies + msecs_to_jiffies(timer.timerperiod); //500ms
timer.timer.data = (unsigned long)&timer;
add_timer(&timer.timer);

/*定时器处理函数*/
static void timer_func(unsigned long arg)
{
struct timer_dev *dev = (struct timer_dev *)arg;
static int sta = 1;
sta = !sta;

gpio_set_value(dev->led_gpio,sta);

mod_timer(&dev->timer,jiffies + msecs_to_jiffies(dev->timerperiod));
}

2.4 IRQ

1
2
3
4
5
6
7
8
9
10
11
12
13

//中断处理函数
static irqreturn_t key0_irq_handler(int irq,void *dev_id)
{
struct im6uirq_dev *dev = dev_id;

// dev->timer.data = (volatile unsigned long)dev_id;
// mod_timer(&dev->timer, jiffies + msecs_to_jiffies(20)); //20ms

tasklet_schedule(&dev->irq_key[0].tasklet);

return IRQ_HANDLED;
}

评论