gpio子系统在sysfs中构建leds类
Posted 正在起飞的蜗牛
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了gpio子系统在sysfs中构建leds类相关的知识,希望对你有一定的参考价值。
1、内核配置
CONFIG_GPIO_SYSFS=y
CONFIG_GPIOLIB=y
(1)CONFIG_GPIO_SYSFS:决定sysfs是否支持gpio子系统,也就是能否在"/sys/class/“目录下看到gpio类;
(2)CONFIG_GPIOLIB:决定是否将”/drivers/gpio/gpiolib.c"编译进内核,如果选择否则在内核和驱动中不能使用gpio子系统相关的函数接口;
总结:CONFIG_GPIOLIB一般都是选择y,因为其他驱动会用到内核gpio子系统;CONFIG_GPIO_SYSFS根据自己的需求来进行选择,如果你不需要通过"/sys/class/gpio"目录下的文件来操作gpio口,就不需要开启;
2、gpio类创建过程
2.1、函数调用关系
gpiolib_sysfs_init()
class_register(&gpio_class); //创建gpio类
gpiochip_export()
sysfs_create_group() //设置设备的属性
2.2、gpio类创建
2.2.1、postcore_initcall宏
#define __define_initcall(level,fn,id) \\
static initcall_t __initcall_##fn##id __used \\
__attribute__((__section__(".initcall" level ".init"))) = fn
#define postcore_initcall(fn) __define_initcall("2",fn,2)
postcore_initcall(gpiolib_sysfs_init);
(1)gpiolib_sysfs_init()函数是创建gpio类的函数,内部调用class_register()函数进行创建;
(2)相当于定义了一个类型为initcall_t的静态局部变量__initcall_gpiolib_sysfs_init2,变量被赋值为gpiolib_sysfs_init函数指针,变量被赋予段属性".initcall2.init"。这样会保证在内核启动过程中自动调用gpiolib_sysfs_init()函数,创建好gpio类。
2.2.2、gpio_class 全局变量
//类属性
static struct class_attribute gpio_class_attrs[] =
__ATTR(export, 0200, NULL, export_store),
__ATTR(unexport, 0200, NULL, unexport_store),
__ATTR_NULL,
;
//类的信息
static struct class gpio_class =
.name = "gpio", //类的名字
.owner = THIS_MODULE, //类的所有者
.class_attrs = gpio_class_attrs, //类的属性
;
//调用关系
gpiolib_sysfs_init()
class_register(&gpio_class); //创建gpio类
(1)gpio_class变量类型是struct class结构体,所以调用class_register()函数创建类后,会看到/sys/class/gpio目录;
(2)/sys/class/gpio目录下有export和unexport文件,是因为在创建gpio类时,给类属性赋值了(gpio_class_attr[]变量);
(3)export和unexport是用于导出、撤销gpio口的,详情参见博客:《应用层通过/sys/class/gpio文件操作gpio口》;
2.3、gpio类的设备属性设置
2.3.1、DEVICE_ATTR宏定义
#define __ATTR(_name,_mode,_show,_store) \\
.attr = .name = __stringify(_name), .mode = _mode , \\
.show = _show, \\
.store = _store, \\
#define DEVICE_ATTR(_name, _mode, _show, _store) \\
struct device_attribute dev_attr_##_name = __ATTR(_name, _mode, _show, _store)
用来定义一个struct device_attribute结构体变量,该类型的变量表示设备的属性,也就是将来在gpio类下的设备都有哪些文件夹;
2.3.3、DEVICE_ATTR宏定义展开分析
static DEVICE_ATTR(ngpio, 0444, chip_ngpio_show, NULL);
展开:
struct device_attribute dev_attr_ngpio = \\
.attr = .name = ngpio, .mode = 0444 , \\
.show = chip_ngpio_show, \\
.store = NULL, \\
定义了struct device_attribute类型的变量dev_attr_ngpio,将来gpio类的设备目录里会看到ngpio文件,权限是0444,读ngpio文件调用函数chip_ngpio_show,因为store是NULL,所以ngpio文件不可写。
2.3.4、gpiochip_attr_group 全局变量
static const struct attribute *gpiochip_attrs[] =
&dev_attr_base.attr,
&dev_attr_label.attr,
&dev_attr_ngpio.attr,
NULL,
;
static const struct attribute_group gpiochip_attr_group =
.attrs = (struct attribute **) gpiochip_attrs,
;
gpiochip_attr_group变量是个struct attribute 结构体指针数组,每一个成员都是gpio设备的一个属性,sysfs_create_group()函数
会读取gpiochip_attr_group变量去给gpio类的设备创建一系列属性;
3、把gpio端口创建为gpio类下的设备
函数调用关系
//在注册gpio资源时创建
gpiochip_add()
gpiochip_export
//在创建gpio类时创建
gpiolib_sysfs_init()
class_register(&gpio_class); //创建gpio类
gpiochip_export()
(1)在两个地方会为每个gpio端口创建gpio类的设备,一个是注册gpio端口资源时,另一个是在初始化gpio框架的sysfs时;
(2)struct gpio_chip结构体的exported变量是用来标记该端口的状态,gpio端口在初始化后exported变量会被置1,在创建的时候回去检查标志位, 所以不用担心重复创建;
以上是关于gpio子系统在sysfs中构建leds类的主要内容,如果未能解决你的问题,请参考以下文章