gpiolib库

82 阅读2分钟

4月「掘金·日新计划」第22天

2.4、gpiolib库

2.4.1、概念及接口

  1. gpiolib库的作用是对所有的gpio实行统一管理,因为驱动在工作的时候,会出现好几个驱动共同使用同一个gpio的情况,这样会造成混乱, 所以内核提供了一些方法来管理gpio资源

  2. 目录/sys/class/gpio/有很多gpio设备文件

  3. 文件目录drivers/gpio/gpiolib.c

  4. 接口函数

    1. gpio_request/gpio_free: 申请释放,返回0成功
        参数gpio号,名字随便填
    2. gpio_request_one/gpio_request_array多个同时申请
    3. gpio_direction_input/gpio_direction_out:设置gpio输入/输出模式
        gpio号,高低电平
    4. gpio_get_value/gpio_set_value:读取设置gpio的值
        gpio号,高低电平
    5. gpiochip_is_request:判断是否占用gpio
    6. gpio_to_desc: 获取gpio实例
    7. gpio_to_irq:获取gpio中断号,方便注册中断
    

2.4.2、使用

  1. 查看gpio使用情况

    1. mount -t debugfs debugfs /tmp 挂载 umount /tmp 卸载

    2. 需要进入管理员模式 sudo su exit

    3. 使用cat gpio查看 /tmp下面

    4. 查看输出,gpio readall

  2. 框架+gpio

#include <linux/module.h>       // module_init  module_exit
#include <linux/init.h>         // __init   __exit
#include <linux/fs.h>
#include <linux/leds.h>
#include <linux/io.h>
#include <linux/ioport.h>
#include <linux/gpio.h>#define GPIO_LED1   17#define X210_LED_OFF    0           // X210中LED是正极接电源,负极节GPIO
#define X210_LED_ON 1               // 所以1是灭,0是亮
​
​
static struct led_classdev mydev1;          // 定义结构体变量// 这个函数就是要去完成具体的硬件读写任务的
static void s5pv210_led1_set(struct led_classdev *led_cdev,
                enum led_brightness value)
{
    printk(KERN_INFO "s5pv210_led1_set\n");
​
    //writel(0x11111111, GPJ0CON);
​
    // 在这里根据用户设置的值来操作硬件
    // 用户设置的值就是value
    if (value == LED_OFF)
    {
        // 用户给了个0,希望LED灭
        //writel(0x11111111, GPJ0CON);
        // 读改写三部曲
        //writel((readl(GPJ0DAT) | (1<<3)), GPJ0DAT);
        gpio_set_value(GPIO_LED1, X210_LED_OFF);
    }
    else
    {
        // 用户给的是非0,希望LED亮
        //writel(0x11111111, GPJ0CON);
        //writel((readl(GPJ0DAT) & ~(1<<3)), GPJ0DAT);
        gpio_set_value(GPIO_LED1, X210_LED_ON);
    }
}
​
static int __init s5pv210_led_init(void)
{
    // 用户insmod安装驱动模块时会调用该函数
    // 该函数的主要任务就是去使用led驱动框架提供的设备注册函数来注册一个设备
    int ret = -1;
​
    // 在这里去申请驱动用到的各种资源,当前驱动中就是GPIO资源
    if (gpio_request(GPIO_LED1, "led1_gpio_0"))
    {
        printk(KERN_ERR "gpio_request failed\n");
    }
    else
    {
        // 设置为输出模式,并且默认输出1让LED灯灭
        gpio_direction_output(GPIO_LED1, 1);
    }
​
​
​
    // led1
    mydev1.name = "led1";
    mydev1.brightness = 0;
    mydev1.brightness_set = s5pv210_led1_set;
​
    ret = led_classdev_register(NULL, &mydev1);
    if (ret < 0) {
        printk(KERN_ERR "led_classdev_register failed\n");
        return ret;
    }
​
    return 0;
}
​
static void __exit s5pv210_led_exit(void)
{
    led_classdev_unregister(&mydev1);
    gpio_free(GPIO_LED1);
}
​
​
module_init(s5pv210_led_init);
module_exit(s5pv210_led_exit);
​
// MODULE_xxx这种宏作用是用来添加模块描述信息
MODULE_LICENSE("GPL");                          // 描述模块的许可证
MODULE_AUTHOR("aston <1264671872@qq.com>");     // 描述模块的作者
MODULE_DESCRIPTION("s5pv210 led driver");       // 描述模块的介绍信息
MODULE_ALIAS("s5pv210_led");                    // 描述模块的别名信息