1 Learn before read:
https://blog.csdn.net/weixin_44021648/article/details/113839882
https://blog.csdn.net/zhoutaopower/article/details/98082006
2 The main functions of gpiolib
** include/linux/gpio.h
/**
* struct gpio - a structure describing a GPIO with configuration
* @gpio: the GPIO number
* @flags: GPIO configuration as specified by GPIOF_*
* @label: a literal description string of this GPIO
*/
struct gpio {
unsigned gpio;
unsigned long flags;
const char *label;
};
#ifdef CONFIG_GPIOLIB
#ifdef CONFIG_ARCH_HAVE_CUSTOM_GPIO_H
#include <asm/gpio.h>
#else
#include <asm-generic/gpio.h>
static inline int gpio_get_value(unsigned int gpio)
static inline void gpio_set_value(unsigned int gpio, int value)
static inline int gpio_to_irq(unsigned int gpio)
int devm_gpio_request(struct device *dev, unsigned gpio, const char *label);
int devm_gpio_request_one(struct device *dev, unsigned gpio,
unsigned long flags, const char *label);
void devm_gpio_free(struct device *dev, unsigned int gpio);
static inline bool gpio_is_valid(int number)
static inline int gpio_request(unsigned gpio, const char *label)
static inline int gpio_direction_input(unsigned gpio)
static inline int gpio_direction_output(unsigned gpio, int value)
3 The sample code to use these functions
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/input.h>
#include <linux/platform_device.h>
#include <linux/gpio.h>
#include <linux/sysfs.h>
MODULE_LICENSE("GPL");
static int major = 56; // Major device number
static int minor = 0; // Minor device number
static dev_t devno;
static struct cdev cdev1;
struct class *hello_class;
#define LIGHTSENSORGPIO 23
#define MICSENSORGPIO 24
static int hello_open(struct inode *inodep, struct file *filep)
{
printk(KERN_ALERT "hello are opened \r\n");
return 0;
}
static struct file_operations hello_ops = {
.open = hello_open,
};
static char mybuf[100]="123";
static ssize_t show_my_device(struct device *dev,
struct device_attribute *attr, char *buf)
{
int gpio_val;
gpio_val = gpio_get_value(LIGHTSENSORGPIO);
if (gpio_val == 1)
strcpy(mybuf, "high");
else
strcpy(mybuf, "low");
return sprintf(buf, "%s\n", mybuf);
}
static ssize_t set_my_device(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t len)
{
sprintf(mybuf, "%s", buf);
printk(KERN_ERR "hello: set_my_dev, %s\n", mybuf);
if (!strncmp(mybuf, "hi", 2)) {
gpio_set_value(LIGHTSENSORGPIO,1);
} else if (!strncmp(mybuf, "lo", 2)) {
gpio_set_value(LIGHTSENSORGPIO,0);
} else {
printk(KERN_ERR "hello: set_my_dev, invalid parameter\n");
}
return len;
}
static DEVICE_ATTR(my_device_test, S_IWUSR|S_IRUSR, show_my_device, set_my_device);
static int __init hello_world_init(void)
{
int ret;
struct device *mydev;
printk(KERN_DEBUG "hello world!!!\n");
devno = MKDEV(major, minor);
ret = register_chrdev_region(devno, 1, "hello");
if (ret < 0)
{
printk(KERN_ERR "my register_chrdev_region fail \r\n");
goto error1;
}
printk(KERN_INFO "register_chrdev_region success\n");
cdev_init(&cdev1, &hello_ops);
ret = cdev_add(&cdev1, devno, 1);
if (ret < 0)
{
printk(KERN_ERR "Uable to add dev\n");
return ret;
}
printk(KERN_INFO "cdev_add success\n");
hello_class = class_create(THIS_MODULE, "hello");
mydev = device_create(hello_class, NULL, devno, NULL, "hello");
printk(KERN_INFO "device created success\n");
if(sysfs_create_file(&(mydev->kobj), &dev_attr_my_device_test.attr)){
goto error2;
}
ret = gpio_request(LIGHTSENSORGPIO, "LightSensorIrq");
if (ret < 0) {
printk(KERN_ERR "hello: request gpio failed\n");
goto error3;
}
ret = gpio_direction_output(LIGHTSENSORGPIO, 1);
if (ret < 0) {
printk(KERN_ERR "hello: set gpio direction failed\n");
goto error3;
}
return 0;
error3:
gpio_free(LIGHTSENSORGPIO);
error2:
device_destroy(hello_class, devno);
class_destroy(hello_class);
cdev_del(&cdev1);
error1:
unregister_chrdev_region(devno, 1);
return -1;
}
static void __exit hello_world_exit(void)
{
gpio_free(LIGHTSENSORGPIO);
device_destroy(hello_class, devno);
class_destroy(hello_class);
cdev_del(&cdev1);
unregister_chrdev_region(devno, 1);
printk(KERN_ALERT "hell_exit\r\n");
}
module_init(hello_world_init);
module_exit(hello_world_exit);
4 Check how it works with multimeter
// The pin16 of Raspberry pi 4B is gpio23, use multimeter to test this pin
root@l:/sys/class/hello/hello# echo low > my_device_test
[ 2226.393388] hello: set_my_dev, low // The multimeter shows 3.3V
root@l:/sys/class/hello/hello# echo high > my_device_test
[ 2240.396673] hello: set_my_dev, high // The multimeter show 0.0V
网友评论