驱动框架之LED

一、什么是驱动框架?

1、驱动是谁写的?

(1)驱动开发工程师;

(2)内核维护者;

2、驱动编程协作要求

(1)接口标准化;

(2)内核开发者应该尽量降低驱动开发者难度;

3、到底什么是驱动框架?

(1)驱动框架

  • 内核中驱动部分维护者,针对每个种类(比如LED、LCD、蜂鸣器等等)的设备,都设计有一套成熟的、标准的、典型的驱动实现;
  • 它是把不同厂家的同类硬件驱动中相同的部分抽出来自己实现好,再把不同部分留出接口给具体的驱动开发工程师来实现。
  • 降低了难度,也标准化。

(2)内核维护者在内核中设计了一些(统一管控系统资源的)体系

  • 这些体系让内核能够(对资源在各个驱动之间的使用)统一协调和分配,保证整个内核的稳定健康运行。
  • 譬如系统中所有的GPIO就属于系统资源,每个驱动模块如果要使用某个GPIO就要先调用特殊的接口先申请,申请到后使用,使用完后要释放。
  • 又譬如中断号也是一种资源,驱动在使用前也必须去申请。
  • 这体系也是驱动框架的组成部分。

(3)一些特定的接口函数、一些特定的数据结构,这些是驱动框架的直接表现。

二、内核驱动框架中LED的基本情况

1、相关文件

(1)drivers/leds目录

  • 这个目录就是驱动框架规定的LED这种硬件的驱动应该待的地方。

(2)drivers/leds目录下有led-class.c和led-core.c

  • 这两个文件加起来属于LED驱动框架的第一部分,这两个文件是内核开发者提供的,他们描述的是内核中所有厂家的不同LED硬件的相同部分的逻辑。

(3)此目录下有leds-xxxx.c

  • 这个文件是LED驱动框架的第2部分,是由不同厂商的驱动工程师编写添加的;
  • 厂商驱动工程师结合自己公司的硬件的不同情况来对LED进行操作,使用第一部分提供的接口来和驱动框架进行交互,最终实现驱动的功能。

2、典型的驱动开发行业现状

(1)内核开发者对驱动框架进行开发和维护、升级,对应led-class.c和led-core.c;

(2)SoC厂商的驱动工程师对设备驱动源码进行编写、调试,提供参考版本,对应leds-s3c24xx.c;

(3)做产品的厂商的驱动工程师以SoC厂商提供的驱动源码为基础,来做移植和调试;

二、内核添加led驱动框架支持

当前内核中没有LED驱动框架,要去添加它。(/sys/class目录下没有此类,因此要去添加此类)

配置内核,make menuconfig

Device Drivers  --->
    [*] LED Support  --->
        <*>   LED Class Support

三、内核驱动框架中LED的接口

1、led_classdev_register设备注册函数

int led_classdev_register(struct device *parent, struct led_classdev *led_cdev)
  • led_classdev_register函数创建一个属于leds这个类的一个设备,其实就是去注册一个设备。
  • 这个函数是led驱动框架中,内核开发者提供给SoC厂家驱动开发者的一个注册驱动的接口。
  • 当使用led驱动框架去编写驱动的时候,这个led_classdev_register函数的作用类似于之前使用file_operations方式去注册字符设备驱动时的register_chrdev函数。
  • 之前使用file_operations方式时,在sys/class目录下创建一个类,然后再创建属于这个类的一个设备。

2、led_classdev结构体

看一下led_classdev中的主要成员
struct led_classdev {
	const char *name;                            //设备名字
	int brightness;                              //当前亮度值
	int max_brightness;                          //最大亮度值
	...
	void (*brightness_set)(struct led_classdev *led_cdev, enum led_brightness brightness);    /* 设置led亮度值 */
	...
};

四、基于驱动框架写led驱动

完整的led驱动

#include <linux/module.h>
#include <linux/init.h>
#include <linux/leds.h>

static struct led_classdev mydev;

/* led设置接口 */
static void s5pv210_led_set(struct led_classdev *led_cdev, enum led_brightness value)
{
	printk(KERN_INFO "s5pv210_led_set\n");
}

static int __init s5pv210_led_init(void)
{
	int ret = -1;

	mydev.name = "led";
	mydev.brightness = 0;	
	mydev.brightness_set = s5pv210_led_set;
	
    /* 注册led设备 */
	ret = led_classdev_register(NULL, &mydev);
	if (ret < 0) {
		printk(KERN_ERR "led_classdev_register failed\n");
		return ret;
	}
	
	return 0;
}

static void __exit s5pv210_led_exit(void)
{
    /* 注销led设备 */
	led_classdev_unregister(&mydev);
}

module_init(s5pv210_led_init);
module_exit(s5pv210_led_exit);

// MODULE_xxx这种宏作用是用来添加模块描述信息
MODULE_LICENSE("GPL");							// 描述模块的许可证
MODULE_AUTHOR("lsm");							// 描述模块的作者
MODULE_DESCRIPTION("s5pv210 led driver");		// 描述模块的介绍信息
MODULE_ALIAS("s5pv210_led");					// 描述模块的别名信息

五、查看led设备

安装好led驱动之后,进入/sys/class/leds/led

打印出s5pv210_led_set,表示使用led框架成功。

猜你喜欢

转载自blog.csdn.net/lushoumin/article/details/86498427