就像学编程第一个范例helloworld一样,学嵌入式,单片机、fpga之类的第一个范例就是点亮一盏灯。对于庞大的linux系统,当然可以编写一个字符设备驱动来实现我们需要的led灯,也可以直接利用gpio口,应用程序来拉高拉低管脚控制。不过,既然linux系统自己本来就带有led子系统,那么就可以好好利用之。好处不用多说了,主要对于应用层来说,不同平台都用linux的led子系统,那么应用程序不用做任何的改变,就可以在新的平台上运行,可移植性好。

         linux的led子系统的源码路径:

  1. include/Linux/leds.h    //头文件
  2. drivers/leds              //led子系统相关源码以及API

 

首先看一下led子系统中的主要文件:

  1. # LED Core 
  2. obj-$(CONFIG_NEW_LEDS)                        +=led-core.o 
  3. obj-$(CONFIG_LEDS_CLASS)                 += led-class.o 
  4. obj-$(CONFIG_LEDS_TRIGGERS)              +=led-triggers.o 
  5. # LED PlatformDrivers 
  6. obj-$(CONFIG_LEDS_GPIO)                        += leds-gpio.o 
  7. # LED Triggers 
  8. obj-$(CONFIG_LEDS_TRIGGER_TIMER) +=ledtrig-timer.o 
  9. obj-$(CONFIG_LEDS_TRIGGER_IDE_DISK)      +=ledtrig-ide-disk.o 
  10. obj-$(CONFIG_LEDS_TRIGGER_HEARTBEAT) +=ledtrig-heartbeat.o 
  11. obj-$(CONFIG_LEDS_TRIGGER_BACKLIGHT) +=ledtrig-backlight.o 
  12. obj-$(CONFIG_LEDS_TRIGGER_GPIO)              +=ledtrig-gpio.o 
  13. obj-$(CONFIG_LEDS_TRIGGER_DEFAULT_ON)        += ledtrig-default-on.o 

主要由leds.h、led-core.c、led-class.c、led-triggers.c,其中led-triggers又分为了timer、ide-disk、heartbeat、backlight、gpio、default-on等算法。

例子程序是leds-gpio,接下去会主要分析这个驱动实现。

首先简单看一下主要的文件

leds.h

Led的亮度,分为三等级,关、中间、最亮。

enum led_brightness {
    LED_OFF        = 0,        //全暗
    LED_HALF    = 127,        //一半亮度
    LED_FULL    = 255,        //最大亮度
};

 

 

struct led_classdev {
    const char        *name;         //led名字
    int             brightness;    //当前亮度
    int             max_brightness;//参考值,最大亮度
    int             flags;            //标志,目前只支持 LED_SUSPENDED和LED_CORE_SUSPENDRESUME

    /* Lower 16 bits reflect status */
#define LED_SUSPENDED        (1 << 0)
    /* Upper 16 bits reflect control information */
#define LED_CORE_SUSPENDRESUME    (1 << 16)

    /* Set LED brightness level */
    /* Must not sleep, use a workqueue if needed */
    //核心回调函数,当设置/sys/class/leds/下的led接口里的brightness(亮度)属性文件时,会回调该函数
    void        (*brightness_set)(struct led_classdev *led_cdev,
                      enum led_brightness brightness); //亮度设置函数指针
    /* Get LED brightness level */
    //核心回调函数,当获得led当前亮度值时会调用
    enum led_brightness (*brightness_get)(struct led_classdev *led_cdev);//获取亮度函数指针

    /*
     * Activate hardware accelerated blink, delays are in milliseconds
     * and if both are zero then a sensible default should be chosen.
     * The call should adjust the timings in that case and if it can't
     * match the values specified exactly.
     * Deactivate blinking again when the brightness is set to a fixed
     * value via the brightness_set() callback.
     */
    /* 激活硬件加速的闪烁 */
    int        (*blink_set)(struct led_classdev *led_cdev,
                     unsigned long *delay_on,
                     unsigned long *delay_off);//闪烁时点亮和熄灭的时间设置 
    //嵌入的标准设备模型
    struct device        *dev;
    /* 所有已经注册的led_class dev使用这个节点串联起来 */
    struct list_head     node;            /* LED Device list */ //leds-list的node
    /* 默认触发器 */
    const char        *default_trigger;    /* Trigger to use */ //默认trigger的名字

    unsigned long         blink_delay_on, blink_delay_off;     //闪烁的开关时间 
    struct timer_list     blink_timer;                          //闪烁的定时器链表
    int             blink_brightness;                                //闪烁的亮度
//如果配置内核时使能了触发器功能,才会编译下面一段
#ifdef CONFIG_LEDS_TRIGGERS
    /* Protects the trigger data below */
    struct rw_semaphore     trigger_lock; /* 这个读写锁保护下面的触发器数据 */

    struct led_trigger    *trigger;         //触发器指针
    struct list_head     trig_list;        //触发器使用的链表节点,用来连接同一触发器上的所有led_classdev
    void            *trigger_data;        //触发器使用的私有数据
#endif
};

 

 

struct led_trigger {
    const char     *name;             //trigger名字
    void        (*activate)(struct led_classdev *led_cdev);//激活led,led_classdev和触发器建立连接时会调用这个方法。
    void        (*deactivate)(struct led_classdev *led_cdev);//取消激活。led_classdev和触发器取消连接时会调用这个方法。

    /* LEDs under control by this trigger (for simple triggers) */
     /* 本触发器控制之下的led链表 */
    rwlock_t      leddev_list_lock; //保护链表的锁
    struct list_head  led_cdevs;    //链表头

    /* Link to next registered trigger */
    struct list_head  next_trig; /* 连接下一个已注册触发器的链表节点 ,所有已注册的触发器都会被加入一个全局链表*/
};

 

//平台设备相关的led数据结构
struct led_info {
    const char    *name;
    const char    *default_trigger;
    int        flags;
};

struct led_platform_data {
    int        num_leds;
    struct led_info    *leds;
};

/* For the leds-gpio driver */
//平台设备相关的gpio led数据结构
struct gpio_led {
    const char *name;                //led的名字 
    const char *default_trigger;     //默认的trigger 
    unsigned     gpio;                 //gpio口
    unsigned    active_low : 1;
    unsigned    retain_state_suspended : 1;
    unsigned    default_state : 2;
    /* default_state should be one of LEDS_GPIO_DEFSTATE_(ON|OFF|KEEP) */
};
#define LEDS_GPIO_DEFSTATE_OFF        0
#define LEDS_GPIO_DEFSTATE_ON        1
#define LEDS_GPIO_DEFSTATE_KEEP        2

struct gpio_led_platform_data {
    int         num_leds;            //led的个数
    const struct gpio_led *leds;    //平台设备相关的gpio led数据结构

#define GPIO_LED_NO_BLINK_LOW    0    /* No blink GPIO state low */
#define GPIO_LED_NO_BLINK_HIGH    1    /* No blink GPIO state high */
#define GPIO_LED_BLINK        2    /* Please, blink */
    int        (*gpio_blink_set)(unsigned gpio, int state,
                    unsigned long *delay_on,
                    unsigned long *delay_off);
};

 

 

led-core.c

//主要声明led的链表和锁
22 DECLARE_RWSEM(leds_list_lock);
23 EXPORT_SYMBOL_GPL(leds_list_lock);
25 LIST_HEAD(leds_list);
26 EXPORT_SYMBOL_GPL(leds_list);
                      

led-class.c

1、  leds_init

主要是创建leds_class,赋值suspend和resume以及dev_attrs。

led_class_attrs

84 static struct device_attribute led_class_attrs[] = {
85     __ATTR(brightness, 0644, led_brightness_show, led_brightness_store),
86     __ATTR(max_brightness, 0444, led_max_brightness_show, NULL),
87 #ifdef CONFIG_LEDS_TRIGGERS
88     __ATTR(trigger, 0644, led_trigger_show, led_trigger_store),
89 #endif
90     __ATTR_NULL,
91 };

2、led_classdev_register

         创建classdev设备,也即Leds_class类中实例化一个对象,类似于c++的new一个对象,leds有很多种,而这里是注册一个特定的led,内核中的面向对象思想也极其丰富。

         加到leds_list链表中,初始化blinktimer,指定blink_timer的function和data,设置trigger,然后一个新的led设备就注册好了,就可以使用了。

led-triggers.c

1、led_trigger_register

         扫描trigger链表中是否有同名的trigger,接着把当前trigger加入到链表中,如果led_classdev中有默认的trigger,那么就设置这个默认的。

好了,简单看了下led子系统中比较重要的结构体和函数,那么接下去就可以通过leds-gpio这个驱动来进一步了解led子系统了。

linux led子系统(一)的更多相关文章

  1. linux led子系统(二)

    对于led子系统中,有那么多得trigger,下面就来简单了解下. 1.default-on static void defon_trig_activate(struct led_classdev * ...

  2. (linux)LED子系统

    数据结构(/include/linux/leds.h) enum led_brightness { LED_OFF = 0, LED_HALF = 127, LED_FULL = 255, }; le ...

  3. 初探linux子系统集之led子系统(二)

    巴西世界杯,德国7比1东道主,那个惨不忍睹啊,早上起来看新闻,第一眼看到7:1还以为点球也能踢成这样,后来想想,点球对多嘛6比1啊,接着就是各种新闻铺天盖地的来了.其实失败并没有什么,人生若是能够成功 ...

  4. 初探linux子系统集之led子系统(一)

    就像学编程第一个范例helloworld一样,学嵌入式,单片机.fpga之类的第一个范例就是点亮一盏灯.对于庞大的linux系统,当然可以编写一个字符设备驱动来实现我们需要的led灯,也可以直接利用g ...

  5. arm Linux 驱动LED子系统 测试

    Linux内核在3.0以上引入了设备树概念(具体哪个版本不清楚)在编译内核后需要将与之对应的dtb文件也下载人板子上才能使内核与硬件关联起来. dtb文件是有dts文件编译后生成的:例如 /* * C ...

  6. 初探linux子系统集之led子系统(二)【转】

    本文转载自:http://blog.csdn.net/eastmoon502136/article/details/37606487 巴西世界杯,德国7比1东道主,那个惨不忍睹啊,早上起来看新闻,第一 ...

  7. 初探linux子系统集之led子系统(一)【转】

    本文转载自:http://blog.csdn.net/eastmoon502136/article/details/37569789 就像学编程第一个范例helloworld一样,学嵌入式,单片机.f ...

  8. 【linux】led子系统

    目录 前言 linux子系统 led子系统 led子系统实战-系统调用-ARM平台 前言 接下来记录的是 led子系统 目前不涉及驱动源码 linux子系统 在 Linux 系统中 绝大多数硬件设备都 ...

  9. 初探linux子系统集之led子系统(三)

    世界杯结束了,德国战车夺得了大力神杯,阿根廷最终还是失败了.也许3年,5年,或者10年后,人们就不知道巴西世界杯的亚军是谁,但是总是会记得冠军是谁.就像什么考试,比赛,第一永远会被人们所记住,所以我们 ...

随机推荐

  1. vc调试大全

    一.调试基础 调试快捷键 F5:  开始调试 Shift+F5: 停止调试 F10:   调试到下一句,这里是单步跟踪 F11:   调试到下一句,跟进函数内部 Shift+F11:  从当前函数中跳 ...

  2. vmware的vmdk格式虚拟机转换为qcow2格式

      今天应其他部门的需求,把一个笔记本里的vmware的window2008的虚拟机转换为qcow2格式,在公司服务器上运行. 第一次做,用了许多时间 首先: 虚拟机的镜像分为多个vmdk文件,所以我 ...

  3. conda管理包

    清理 conda clean --lock --tarball --package (安装包) 安装或更新包 conda install numpy=1.9.3 conda update numpy= ...

  4. hlg 1580 tell me the length

    智力题,观察上一行,有几个数字. 比如,S[1]=1; S[2]=11; S[3]=21; S[4]=1211; 这样就可以观察出来,序列一是1个1 --->  S[2] = 11 ; 序列二是 ...

  5. BZOJ 2194 快速傅立叶之二 ——FFT

    [题目分析] 咦,这不是卷积裸题. 敲敲敲,结果样例也没过. 看看看,卧槽i和k怎么反了. 艹艹艹,把B数组取个反. 靠靠靠,怎么全是零. 算算算,最终的取值范围算错了. 交交交,总算是A掉了. [代 ...

  6. mode(BZOJ 2456)

    Description 给你一个n个数的数列,其中某个数出现了超过n div 2次即众数,请你找出那个数. Input 第1行一个正整数n.第2行n个正整数用空格隔开. Output 一行一个正整数表 ...

  7. Gauss 高斯消元

    高斯消元…… (裸的暴力) 如果你有一个n元的方程组你会怎么办? Ans:直接用初中的解方程组的方法呀! 没错,直接暴力加减消元.那什么是“高斯消元”?说白了,就是普通的加减消元罢了. 本人再考场上打 ...

  8. 自动化测试框架之robot framework的应用分析

    序言:很多人都对自动化测试框架痴迷,我曾经也痴迷过一段时间,以前觉得自己对框架说的头头是道,现在回过头来看以前,说归说,但在如何应用还是欠缺,这一段时间,自己经历了一系列框架的构建和应用的时期,所以, ...

  9. NOJ 1111 保险箱的密码 【大红】 [区间dp]

    传送门 保险箱的密码 [大红] 时间限制(普通/Java) : 1000 MS/ 3000 MS          运行内存限制 : 65536 KByte总提交 : 118            测 ...

  10. Ajax && json(原始)

    function findSend() { $.ajax({ // async: false, // cache: true, type: "POST", url: "I ...