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类的主要内容,如果未能解决你的问题,请参考以下文章

Linux系统GPIO应用编程

11_GPIO子系统的sysfs接口

应用层通过/sys/class/gpio文件操作gpio口

Linux 基于sysfs的GPIO读写操作

Linux 基于sysfs的GPIO读写操作

sysfs方式访问gpio