forked from ruhua-xu/Linux-driver-31
-
Notifications
You must be signed in to change notification settings - Fork 0
/
myled.c
executable file
·153 lines (116 loc) · 2.98 KB
/
myled.c
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
#define CNAME "myled"
#define RED_PHY_BASE 0xc001a000 //a28
#define BLUE_PHY_BASE 0xc001b000 //b12
#define GREEN_PHY_BASE 0xc001e000 //e13
#define OUT 0
#define OUTENB 1
#define ALTFN0 8
#define ALTFN1 9
int major = 0;
char kbuf[2] = {0};
//映射之后产生的虚拟地址
unsigned int *red_virt_base = NULL;
unsigned int *green_virt_base = NULL;
unsigned int *blue_virt_base = NULL;
enum RGB_LED{
RED,
GREEN,
BULE,
};
int myled_open(struct inode *inode, struct file *file)
{
printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);
return 0;
}
ssize_t myled_read(struct file *file,
char __user *ubuf, size_t size, loff_t *offs)
{
printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);
return 0;
}
ssize_t myled_write (struct file *file,
const char __user *ubuf, size_t size, loff_t *offs)
{
int ret;
printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);
//1.拷贝用户空间的数据
if(size > sizeof(kbuf)) size = sizeof(kbuf);
ret = copy_from_user(kbuf,ubuf,size);
if(ret){
printk("copy data from user error\n");
return -EIO;
}
//2.根据用户空间的数据进行点灯
switch(kbuf[0]){
case RED:
kbuf[1]?on:off;
break;
case GREEN:
kbuf[1]?on:off;
break;
case BLUE:
kbuf[1]?on:off;
break;
}
return size;
}
int myled_close(struct inode *inode, struct file *file)
{
printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);
return 0;
}
const struct file_operations fops = {
.open = myled_open,
.read = myled_read,
.write = myled_write,
.release = myled_close,
};
static int __init myled_init(void)
{
//1.注册字符设备驱动
major = register_chrdev(0,CNAME,&fops);
if(major < 0){
printk("register chrdev error\n");
return major;
}
//2.映射RGB_LED灯的地址
red_virt_base = ioremap(RED_PHY_BASE,40);
if(red_virt_base == NULL){
printk("ioremap red led addr error\n");
return -ENOMEM;
}
green_virt_base = ioremap(GREEN_PHY_BASE,40);
if(green_virt_base == NULL){
printk("ioremap green led addr error\n");
return -ENOMEM;
}
blue_virt_base = ioremap(BLUE_PHY_BASE,40);
if(blue_virt_base == NULL){
printk("ioremap blue led addr error\n");
return -ENOMEM;
}
//3.RGB_LED INIT ALL OFF
*(red_virt_base + ALTFN1) &= ~(3<<24); //altfn1 24:25 gpio
*(red_virt_base + OUTENB) |= (1<<28); //outenb 28 输出
*(red_virt_base + OUT ) &= ~(1<<28); //out 28 low
*(blue_virt_base + ALTFN0) &= ~(3<<24);
*(blue_virt_base + ALTFN0) |= (2<<24);
*(blue_virt_base + OUTENB) |= (1<<12);
*(blue_virt_base + OUT ) &= ~(1<<12);
*(green_virt_base + ALTFN0) &= ~(3<<26);
*(green_virt_base + OUTENB) |= (1<<13);
*(green_virt_base + OUT ) &= ~(1<<13);
return 0;
}
static void __exit myled_exit(void)
{
//1.注销字符设备驱动
unregister_chrdev(major,CNAME);
//2.取消映射
iounmap(red_virt_base);
iounmap(blue_virt_base);
iounmap(green_virt_base);
}
module_init(myled_init);
module_exit(myled_exit);
MODULE_LICENSE("GPL");