led子系统

Linux内核发展迅速,作为一名驱动工程师,掌握驱动框架尤为重要。以前写单片机程序或者上手linux驱动程序的时候,都把点灯作为入门程序。可是linux实在做的太好了,都把点灯这么简单的东西都封装好框架。而用户只需要调用LED子系统相关的API就可以实现LED操作。

Led子系统源码路径位于driver/leds下,驱动文件位于driver/leds/leds-gpio.c,关于led子系统的核心文件是led-class.c和led-core.c

从drivers/leds/Makefile中可以看到LED子系统的主要文件有几类: LED核心:leds.h、led-core.c、led-class.c、led-

triggers.c(其中led-triggers又分为了timer、ide-disk、heartbeat、backlight、gpio、default-on等) 

include/linux/leds.h

 24 enum led_brightness {
 25     LED_OFF     = 0,
 26     LED_HALF    = 127,
 27     LED_FULL    = 255,
 28 };

led_classdev 结构:

 30 struct led_classdev {
 31     const char      *name;
 32     int          brightness;
 33     int          flags;
 34     
 35 #define LED_SUSPENDED       (1 << 0)
 36 
 37     /* Set LED brightness level */
 38     void        (*brightness_set)(struct led_classdev *led_cdev,
 39                       enum led_brightness brightness);
 40                       
 41     struct class_device *class_dev;
 42     struct list_head     node;          /* LED Device list */
 43     char            *default_trigger;   /* Trigger to use */
 44     
 45 #ifdef CONFIG_LEDS_TRIGGERS
 46     /* Protects the trigger data below */
 47     rwlock_t         trigger_lock;
 48     
 49     struct led_trigger  *trigger;
 50     struct list_head     trig_list;
 51     void            *trigger_data;
 52 #endif
 53 };

LED_TRIGGER

 68 struct led_trigger {
 69     /* Trigger Properties */
 70     const char   *name;
 71     void        (*activate)(struct led_classdev *led_cdev);
 72     void        (*deactivate)(struct led_classdev *led_cdev);
 73 
 74     /* LEDs under control by this trigger (for simple triggers) */
 75     rwlock_t      leddev_list_lock;
 76     struct list_head  led_cdevs;
 77 
 78     /* Link to next registered trigger */
 79     struct list_head  next_trig;
 80 };

相关文件:

(1)led-class.c和led-core.c,这两个文件加起来属于LED驱动框架的第一部分,这两个文件是内核开发者提供的,他们描述的是内核中所有厂家的不同LED硬件的相同部分的逻辑,是LED子系统的核心层

(2)leds-xxxx.c,这个文件是LED驱动框架的第二部分,是由驱动工程师编写添加完成的,驱动工程师结合自己公司的硬件的不同情况来对LED进行操作,使用第一部分提供的接口来和驱动框架进行交互,最终实现驱动的功能

以leds-s3c24xx.c为例。leds-s3c24xx.c中通过调用led_classdev_register来完成LED驱动的注册,而led_classdev_register是在drivers/leds/led-class.c中定义的。厂商的驱动工程师是调用内核开发者在驱动框架中提供的接口来实现自己的驱动的。

使用led-class中的框架写出一个led子系统的驱动程序,根据Linux驱动编写的经验,就是分配,设置。注册led_classdev

1. 分配led_classdev
2. 设置 : 
led_cdev->max_brightness
led_cdev->brightness_set
led_cdev->flags
led_cdev->brightness
led_cdev->name
3. 注册 : led_classdev_register

 

 68 static int s3c24xx_led_init()
 69 {
 70     int ret;
 71     mydev.name="myled";
 72     mydev.brightness=255;
 73     mydev.brightness_set=my_led_set;
 74     ret=led_classdev_register(NULL,&mydev);
 75     if(ret<0)
 76     {
 77         printk("register led_dev fail!\n");
 78         return ret;
 79     }
 80     gpbcon=(volatile unsigned long *)ioremap(0x56000010,16);//映射物理地址 16表示结束大小 
 81       //0x56000010表示gpbcon 0x56000014代表gpbdat  0x56000018代表gpbup 0x5600001c 保留
 82     gpbdat=gpbcon+1;
 83 
 84     //return platform_driver_register(&my_led_driver);
 85     return 0;
 86 }

 41 static void my_led_set(struct led_classdev *led_cdev,enum led_brightness value)
 42 {   
 43     printk("2440_led_set\n");
 44     *gpbcon =0x00111400;    // 设置GPB5 GPB6 GPB8 GPB10  为输出口, 位[9:8]=0b01
 45     if(value==LED_OFF)//灭灯
 46     {   
 47         *gpbdat&=~((1<<5)|(1<<6)|(1<<8)|(1<<10));
 48     }
 49     else//亮灯
 50     {   
 51         *gpbdat|=(1<<5)|(1<<6)|(1<<8)|(1<<10);
 52     }
 53 }

加载模块时发现led_sys: Unknown symbol led_classdev_unregister

led_sys: Unknown symbol led_classdev_register

可能是内核没有支持LEDS_CLASS

make muconfig 看一下

   确实是编译成ko文件了,make module生成相应的ko文件 把led-class.ko文件上传到开发板文件系统中去

然后insmod 注册了一个led设备

 

 写的驱动能够工作了,被加载了,/sys/class/leds/目录下多出来了一个表示设备的文件夹。文件夹里面有相应的操控led硬件的2个属性brightness和max_brightness

echo 0 >/sys/class/leds/myled/brightness 
echo 1 >/sys/class/leds/myled/brightness 

就可以操作led了,led-class.c中brightness方法有一个show方法和store方法,当echo 1 > brightness时,实际就会执行led_brightness_store函数

分析echo 1 brightness

led_brightness_store
    led_set_brightness(led_cdev,state) 
        led_cdev->brightness(led_cdev,value))
             my_led_set(struct led_classdev *led_cdev,enum led_brightness value)   

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值