4月「掘金·日新计划」第22天
2.4、gpiolib库
2.4.1、概念及接口
-
gpiolib库的作用是对所有的gpio实行统一管理,因为驱动在工作的时候,会出现好几个驱动共同使用同一个gpio的情况,这样会造成混乱, 所以内核提供了一些方法来管理gpio资源
-
目录/sys/class/gpio/有很多gpio设备文件
-
文件目录drivers/gpio/gpiolib.c
-
接口函数
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、使用
-
查看gpio使用情况
-
mount -t debugfs debugfs /tmp 挂载 umount /tmp 卸载
-
需要进入管理员模式 sudo su exit
-
使用cat gpio查看 /tmp下面
-
查看输出,gpio readall
-
-
框架+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"); // 描述模块的别名信息