提供一份基于kernel-3.18创建文件节点来分别控制4路GPIO输出高低电平的驱动代码
时间: 2024-03-23 13:39:00 浏览: 61
以下是一个简单的基于kernel-3.18的创建文件节点来分别控制4路GPIO输出高低电平的驱动代码示例:
```c
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/gpio.h>
#include <linux/fs.h>
#define DEVICE_NAME "gpiocontrol" // 设备名称
#define GPIO_NUM_1 17 // GPIO的编号
#define GPIO_NUM_2 18
#define GPIO_NUM_3 19
#define GPIO_NUM_4 20
static int gpiocontrol_open(struct inode *inode, struct file *filp)
{
return 0;
}
static int gpiocontrol_release(struct inode *inode, struct file *filp)
{
return 0;
}
static ssize_t gpiocontrol_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos)
{
char val;
if (copy_from_user(&val, buf, 1))
return -EFAULT;
if (filp->f_path.dentry->d_inode->i_ino == gpio_num_1_inode) {
if (val == '1')
gpio_set_value(GPIO_NUM_1, 1);
else
gpio_set_value(GPIO_NUM_1, 0);
} else if (filp->f_path.dentry->d_inode->i_ino == gpio_num_2_inode) {
if (val == '1')
gpio_set_value(GPIO_NUM_2, 1);
else
gpio_set_value(GPIO_NUM_2, 0);
} else if (filp->f_path.dentry->d_inode->i_ino == gpio_num_3_inode) {
if (val == '1')
gpio_set_value(GPIO_NUM_3, 1);
else
gpio_set_value(GPIO_NUM_3, 0);
} else if (filp->f_path.dentry->d_inode->i_ino == gpio_num_4_inode) {
if (val == '1')
gpio_set_value(GPIO_NUM_4, 1);
else
gpio_set_value(GPIO_NUM_4, 0);
}
return count;
}
static const struct file_operations gpiocontrol_fops = {
.owner = THIS_MODULE,
.open = gpiocontrol_open,
.release = gpiocontrol_release,
.write = gpiocontrol_write,
};
static int gpio_num_1_inode;
static int gpio_num_2_inode;
static int gpio_num_3_inode;
static int gpio_num_4_inode;
static int __init gpiocontrol_init(void)
{
int ret;
printk(KERN_INFO "gpiocontrol: initializing\n");
ret = gpio_request(GPIO_NUM_1, "gpiocontrol");
if (ret) {
printk(KERN_ALERT "gpiocontrol: unable to request GPIO %d\n", GPIO_NUM_1);
return ret;
}
gpio_direction_output(GPIO_NUM_1, 0);
gpio_num_1_inode = register_chrdev(0, DEVICE_NAME"-1", &gpiocontrol_fops);
if (gpio_num_1_inode < 0) {
printk(KERN_ALERT "gpiocontrol: unable to register device 1\n");
gpio_free(GPIO_NUM_1);
return gpio_num_1_inode;
}
ret = gpio_request(GPIO_NUM_2, "gpiocontrol");
if (ret) {
printk(KERN_ALERT "gpiocontrol: unable to request GPIO %d\n", GPIO_NUM_2);
unregister_chrdev(gpio_num_1_inode, DEVICE_NAME"-1");
gpio_free(GPIO_NUM_1);
return ret;
}
gpio_direction_output(GPIO_NUM_2, 0);
gpio_num_2_inode = register_chrdev(0, DEVICE_NAME"-2", &gpiocontrol_fops);
if (gpio_num_2_inode < 0) {
printk(KERN_ALERT "gpiocontrol: unable to register device 2\n");
gpio_free(GPIO_NUM_2);
unregister_chrdev(gpio_num_1_inode, DEVICE_NAME"-1");
gpio_free(GPIO_NUM_1);
return gpio_num_2_inode;
}
ret = gpio_request(GPIO_NUM_3, "gpiocontrol");
if (ret) {
printk(KERN_ALERT "gpiocontrol: unable to request GPIO %d\n", GPIO_NUM_3);
unregister_chrdev(gpio_num_2_inode, DEVICE_NAME"-2");
gpio_free(GPIO_NUM_2);
unregister_chrdev(gpio_num_1_inode, DEVICE_NAME"-1");
gpio_free(GPIO_NUM_1);
return ret;
}
gpio_direction_output(GPIO_NUM_3, 0);
gpio_num_3_inode = register_chrdev(0, DEVICE_NAME"-3", &gpiocontrol_fops);
if (gpio_num_3_inode < 0) {
printk(KERN_ALERT "gpiocontrol: unable to register device 3\n");
gpio_free(GPIO_NUM_3);
unregister_chrdev(gpio_num_2_inode, DEVICE_NAME"-2");
gpio_free(GPIO_NUM_2);
unregister_chrdev(gpio_num_1_inode, DEVICE_NAME"-1");
gpio_free(GPIO_NUM_1);
return gpio_num_3_inode;
}
ret = gpio_request(GPIO_NUM_4, "gpiocontrol");
if (ret) {
printk(KERN_ALERT "gpiocontrol: unable to request GPIO %d\n", GPIO_NUM_4);
unregister_chrdev(gpio_num_3_inode, DEVICE_NAME"-3");
gpio_free(GPIO_NUM_3);
unregister_chrdev(gpio_num_2_inode, DEVICE_NAME"-2");
gpio_free(GPIO_NUM_2);
unregister_chrdev(gpio_num_1_inode, DEVICE_NAME"-1");
gpio_free(GPIO_NUM_1);
return ret;
}
gpio_direction_output(GPIO_NUM_4, 0);
gpio_num_4_inode = register_chrdev(0, DEVICE_NAME"-4", &gpiocontrol_fops);
if (gpio_num_4_inode < 0) {
printk(KERN_ALERT "gpiocontrol: unable to register device 4\n");
gpio_free(GPIO_NUM_4);
unregister_chrdev(gpio_num_3_inode, DEVICE_NAME"-3");
gpio_free(GPIO_NUM_3);
unregister_chrdev(gpio_num_2_inode, DEVICE_NAME"-2");
gpio_free(GPIO_NUM_2);
unregister_chrdev(gpio_num_1_inode, DEVICE_NAME"-1");
gpio_free(GPIO_NUM_1);
return gpio_num_4_inode;
}
return 0;
}
static void __exit gpiocontrol_exit(void)
{
printk(KERN_INFO "gpiocontrol: exiting\n");
unregister_chrdev(gpio_num_4_inode, DEVICE_NAME"-4");
gpio_free(GPIO_NUM_4);
unregister_chrdev(gpio_num_3_inode, DEVICE_NAME"-3");
gpio_free(GPIO_NUM_3);
unregister_chrdev(gpio_num_2_inode, DEVICE_NAME"-2");
gpio_free(GPIO_NUM_2);
unregister_chrdev(gpio_num_1_inode, DEVICE_NAME"-1");
gpio_free(GPIO_NUM_1);
}
module_init(gpiocontrol_init);
module_exit(gpiocontrol_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Your Name <youremail@example.com>");
MODULE_DESCRIPTION("GPIO control driver");
```
在该示例中,与前面的示例不同的是,我们创建了4个名为`gpiocontrol-1`、`gpiocontrol-2`、`gpiocontrol-3`、`gpiocontrol-4`的设备节点,分别对应GPIO17、GPIO18、GPIO19、GPIO20。当用户向设备节点写入字符`1`时,对应的GPIO输出高电平,当用户向设备节点写入字符`0`时,对应的GPIO输出低电平。
该驱动程序的编译方式与一般的内核模块相同,可以使用Makefile编译。以下是一个简单的Makefile示例:
```makefile
obj-m += gpiocontrol.o
all:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
```
您可以将上述代码保存为`gpiocontrol.c`和`Makefile`,然后使用以下命令编译模块:
```sh
make
```
编译成功后,您可以使用以下命令加载模块:
```sh
sudo insmod gpiocontrol.ko
```
然后,您可以在`/dev`目录下找到名为`gpiocontrol-1`、`gpiocontrol-2`、`gpiocontrol-3`、`gpiocontrol-4`的设备节点。您可以使用`echo`命令向对应的设备节点写入字符,以控制对应的GPIO的电平。例如,以下命令将GPIO17输出高电平:
```sh
echo 1 > /dev/gpiocontrol-1
```
您可以使用以下命令卸载模块:
```sh
sudo rmmod gpiocontrol
```
希望这可以帮助您。
阅读全文