前言:
当前看官们对“linuxgpio驱动”可能比较注意,大家都想要知道一些“linuxgpio驱动”的相关内容。那么小编在网上收集了一些对于“linuxgpio驱动””的相关知识,希望姐妹们能喜欢,咱们快快来了解一下吧!l 首先在设备树中添加GPIO节点,比如添加LED
内核源码目录下arch/arm/boot/dts/system-top.dts 文件,打开该文件,在根节点”/”下创建led节点,修改为如下:
Led{
Compatible = “alientek,led”;
Status = “okay”;
Default-state = “on”;
Led-gpio = <&gpio0 7 GPIO_ACTIVE_HIGH>;
};
分析如下:led-gpio属性指定了LED灯使用的GPIO,这里使用的GPIO0的IOO7(我使用的ZYNQ平台),可以依据不同平台修改。
l 在proc/device-tree目录下,可以看到各个驱动节点。可以看到有一个led-gpio文件,就是新添加的属性。
l Gpio驱动
#define GPIOLED_CNT 1 /* 设备号个数 */
#define GPIOLED_NAME "gpioled" /* 名字 */
struct gpioled_dev {
dev_t devid; /* 设备号 */
struct cdev cdev; /* cdev */
struct class *class; /* 类 */
struct device *device; /* 设备 */
int major; /* 主设备号 */
int minor; /* 次设备号 */
struct device_node *nd; /* 设备节点 */
int led_gpio; /* LED 所使用的 GPIO 编号 */
};
static struct gpioled_dev gpioled;
45 /*
46 * @description : 打开设备
47 * @param – inode : 传递给驱动的 inode
48 * @param – filp : 设备文件, file 结构体有个叫做 private_data 的成员变量
49 * 一般在 open 的时候将 private_data 指向设备结构图。
50 * @return : 0 成功;其他 失败
51 */
52 static int led_open(struct inode *inode, struct file *filp)
53 {
54 filp->private_data = &gpioled; /* 设置私有数据 */
55 return 0;
56 }
static ssize_t led_read(struct file *filp, char __user *buf,
67 size_t cnt, loff_t *offt)
68 {
69 return 0;
70 }
71
72 /*
73 * @description : 向设备写数据
74 * @param – filp : 设备文件,表示打开的文件描述符
75 * @param – buf : 给设备写入的数据
76 * @param – cnt : 写入的数据长度
77 * @param – offt : 相对于文件首地址的偏移
78 * @return : 写入的字节数,如果为负值,表示写入失败
79 */
80 static ssize_t led_write(struct file *filp, const char __user *buf,
81 size_t cnt, loff_t *offt)
82 {
83 int ret;
84 char kern_buf[1];
85
86 ret = copy_from_user(kern_buf, buf, cnt); // 得到应用层传递过来的数据
87 if(0 > ret) {
88 printk(KERN_ERR "kernel write failed!\r\n");
89 return -EFAULT;
90 }
91
92 if (0 == kern_buf[0])
93 gpio_set_value(gpioled.led_gpio, 0); // 如果传递过来的数据是 0 则关闭 led
94 else if (1 == kern_buf[0])
95 gpio_set_value(gpioled.led_gpio, 1); // 如果传递过来的数据是 1 则点亮 led
96
97 return 0;
98 }
99
100 /*
101 * @description : 关闭/释放设备
102 * @param – filp : 关闭的设备文件(文件描述符)
103 * @return : 0 成功;其他 失败
104 */
105 static int led_release(struct inode *inode, struct file *filp)
106 {
107 return 0;
108 }
109
110 /* 设备操作函数 */
111 static struct file_operations gpioled_fops = {
112 .owner = THIS_MODULE,
113 .open = led_open,
114 .read = led_read,
115 .write = led_write,
116 .release = led_release,
117 };
118
119 static int __init led_init(void)
120 {
121 const char *str;
int ret;
124 /* 1.获取 led 设备节点 */
125 gpioled.nd = of_find_node_by_path("/led");
126 if(NULL == gpioled.nd) {
127 printk(KERN_ERR "gpioled: Failed to get /led node\n");
128 return -EINVAL;
129
}
130
131 /* 2.读取 status 属性 */
132 ret = of_property_read_string(gpioled.nd, "status", &str);
133 if(!ret) {
134 if (strcmp(str, "okay"))
135 return -EINVAL;
136
}
137
138 /* 2、获取 compatible 属性值并进行匹配 */
139 ret = of_property_read_string(gpioled.nd, "compatible", &str);
140 if(0 > ret) {
141 printk(KERN_ERR "gpioled: Failed to get compatible property\n");
142 return ret;
143
}
144
145 if (strcmp(str, "alientek,led")) {
146 printk(KERN_ERR "gpioled: Compatible match failed\n");
147 return -EINVAL;
148
}
149
150
printk(KERN_INFO "gpioled: device matching successful!\r\n");
151
152 /* 4.获取设备树中的 led-gpio 属性,得到 LED 所使用的 GPIO 编号 */
153 gpioled.led_gpio = of_get_named_gpio(gpioled.nd, "led-gpio", 0);
154 if(!gpio_is_valid(gpioled.led_gpio)) {
155 printk(KERN_ERR "gpioled: Failed to get led-gpio\n");
156 return -EINVAL;
157
}
158
159 printk(KERN_INFO "gpioled: led-gpio num = %d\r\n", gpioled.led_gpio);
160
161 /* 5.向 gpio 子系统申请使用 GPIO */
162 ret = gpio_request(gpioled.led_gpio, "LED-GPIO");
163 if (ret) {
164 printk(KERN_ERR "gpioled: Failed to request led-gpio\n");
165 return ret;
166
}
167
168 /* 6.将 led gpio 管脚设置为输出模式 */
169 gpio_direction_output(gpioled.led_gpio, 0);
170
171 /* 7.初始化 LED 的默认状态 */
172 ret = of_property_read_string(gpioled.nd, "default-state", &str);
173 if(!ret) {
174 if (!strcmp(str, "on"))
175 gpio_set_value(gpioled.led_gpio, 1);
176 else
177 gpio_set_value(gpioled.led_gpio, 0);
178 } else
179 gpio_set_value(gpioled.led_gpio, 0);
180
181 /* 8.注册字符设备驱动 */
182 /* 创建设备号 */
原子哥在线教学: 论坛:
727
183 if (gpioled.major) {
184 gpioled.devid = MKDEV(gpioled.major, 0);
185 ret = register_chrdev_region(gpioled.devid, GPIOLED_CNT, GPIOLED_NAME);
186 if (ret)
187 goto out1;
188 } else {
189 ret = alloc_chrdev_region(&gpioled.devid, 0, GPIOLED_CNT, GPIOLED_NAME);
190 if (ret)
191
goto out1;
192
193 gpioled.major = MAJOR(gpioled.devid);
194 gpioled.minor = MINOR(gpioled.devid);
195
}
196
197 printk("gpioled: major=%d,minor=%d\r\n",gpioled.major, gpioled.minor);
198
199 /* 初始化 cdev */
200 gpioled.cdev.owner = THIS_MODULE;
201
cdev_init(&gpioled.cdev, &gpioled_fops);
202
203 /* 添加一个 cdev */
204 ret = cdev_add(&gpioled.cdev, gpioled.devid, GPIOLED_CNT);
205 if (ret)
206
goto out2;
207
208 /* 创建类 */
209 gpioled.class = class_create(THIS_MODULE, GPIOLED_NAME);
210 if (IS_ERR(gpioled.class)) {
211 ret = PTR_ERR(gpioled.class);
212 goto out3;
213
}
214
215 /* 创建设备 */
216 gpioled.device = device_create(gpioled.class, NULL,
217 gpioled.devid, NULL, GPIOLED_NAME);
218 if (IS_ERR(gpioled.device)) {
219 ret = PTR_ERR(gpioled.device);
220 goto out4;
221
}
222
223 return 0;
标签: #linuxgpio驱动