美文网首页
Raspberry: a gpio driver based o

Raspberry: a gpio driver based o

作者: star_walker | 来源:发表于2021-09-11 16:36 被阅读0次

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

相关文章

网友评论

      本文标题:Raspberry: a gpio driver based o

      本文链接:https://www.haomeiwen.com/subject/jhxywltx.html