驱动框架之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框架成功。
總結
- 上一篇: 抱歉!我不太会修电脑 | 2018年中国
- 下一篇: 正弦稳态电路的分析