x210項目重新回顧之九led驅動程序

1.)menuconfig 添加led支持,這裏我編譯成模塊,後面手工加載該內核模塊

 >make 

>make modules ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi-

> make modules_install ARCH=arm  CROSS_COMPILE=arm-none-linux-gnueabi-  INSTALL_MOD_PATH=/tftpboot/nfs

安裝到開發板上/lib/modules/2.6.35.7+/kernel/drivers/leds

 

開發板上>cd /lib/modules/2.6.35.7+/kernel/drivers/leds
/lib/modules/2.6.35.7+/kernel/drivers/leds # ls
led-class.ko  leds-gpio.ko(安裝模塊得來)


#代碼中用到gpio_request(GPIO_LED1, "led1_gpj0.3"),即通過gpio資源統一管理,驅動中用gpio_request調用,所以要加載leds-gpio.ko 模塊

>insmod leds-gpio.ko 


>insmod led-class.ko      

2.)去/sys/class/查看安裝的模塊類

/sys/class/leds # ls
led1  led2  led3

 

3)編譯安裝led設備驅動leds-s5pv210

代碼路徑~/news5pv210/study/zhulaoshi/code/linux_driver/4.LEDDriver/5.4.16

>  make

>sudo cp leds-s5pv210.ko /tftpboot/nfs/driver_test

開發板上driver_test>insmod leds-s5pv210.ko   

 >lsmod
leds_s5pv210 1221 0 - Live 0xbf01e000
led_class 2494 1 leds_s5pv210, Live 0xbf000000
 

4) 測試

/sys/class/leds # cd led1


/sys/devices/virtual/leds/led1 # ls
brightness      max_brightness  power           subsystem       uevent


/sys/devices/virtual/leds/led1 # echo  1 > brightness
[ 2800.294451] s5pv210_led1_set

i

注意:如果不添加led內核框架模塊支持,直接運行朱老師的insmod leds-s5pv210.ko,會報沒找到led_class_*相關注冊類
 

附錄:leds-s5pv210.c

#include <linux/module.h>        // module_init  module_exit
#include <linux/init.h>            // __init   __exit
#include <linux/fs.h>
#include <linux/leds.h>
#include <mach/regs-gpio.h>
#include <mach/gpio-bank.h>
#include <linux/io.h>
#include <linux/ioport.h>
#include <mach/gpio.h>


#define GPIO_LED1    S5PV210_GPJ0(3)
#define GPIO_LED2    S5PV210_GPJ0(4)
#define GPIO_LED3    S5PV210_GPJ0(5)

#define X210_LED_OFF    1            // X210中LED是正極接電源,負極節GPIO
#define X210_LED_ON        0            // 所以1是滅,0是亮


static struct led_classdev mydev1;            // 定義結構體變量
static struct led_classdev mydev2;            // 定義結構體變量
static struct led_classdev mydev3;            // 定義結構體變量

// 這個函數就是要去完成具體的硬件讀寫任務的
static void s5pv210_led1_set(struct led_classdev *led_cdev,
                enum led_brightness value)
{
    printk(KERN_INFO "s5pv210_led1_set\n");
    
    //writel(0x11111111, GPJ0CON);
    
    // 在這裏根據用戶設置的值來操作硬件
    // 用戶設置的值就是value
    if (value == LED_OFF)
    {
        // 用戶給了個0,希望LED滅
        //writel(0x11111111, GPJ0CON);
        // 讀改寫三部曲
        //writel((readl(GPJ0DAT) | (1<<3)), GPJ0DAT);
        gpio_set_value(GPIO_LED1, X210_LED_OFF);  //通過gpio庫統一訪問
    }
    else
    {
        // 用戶給的是非0,希望LED亮
        //writel(0x11111111, GPJ0CON);
        //writel((readl(GPJ0DAT) & ~(1<<3)), GPJ0DAT);
        gpio_set_value(GPIO_LED1, X210_LED_ON);
    }
}

static void s5pv210_led2_set(struct led_classdev *led_cdev,
                enum led_brightness value)
{
    printk(KERN_INFO "s5pv2102_led_set\n");
    
    //writel(0x11111111, GPJ0CON);
    
    // 在這裏根據用戶設置的值來操作硬件
    // 用戶設置的值就是value
    if (value == LED_OFF)
    {
        // 用戶給了個0,希望LED滅
        //writel(0x11111111, GPJ0CON);
        // 讀改寫三部曲
        //writel((readl(GPJ0DAT) | (1<<4)), GPJ0DAT);
    }
    else
    {
        // 用戶給的是非0,希望LED亮
        //writel(0x11111111, GPJ0CON);
        //writel((readl(GPJ0DAT) & ~(1<<4)), GPJ0DAT);
    }
}

static void s5pv210_led3_set(struct led_classdev *led_cdev,
                enum led_brightness value)
{
    printk(KERN_INFO "s5pv210_led3_set\n");
    
    //writel(0x11111111, GPJ0CON);
    
    // 在這裏根據用戶設置的值來操作硬件
    // 用戶設置的值就是value
    if (value == LED_OFF)
    {
        // 用戶給了個0,希望LED滅
        //writel(0x11111111, GPJ0CON);
        // 讀改寫三部曲
        //writel((readl(GPJ0DAT) | (1<<5)), GPJ0DAT);
    }
    else
    {
        // 用戶給的是非0,希望LED亮
        //writel(0x11111111, GPJ0CON);
        //writel((readl(GPJ0DAT) & ~(1<<5)), GPJ0DAT);
    }
}


static int __init s5pv210_led_init(void)
{
    // 用戶insmod安裝驅動模塊時會調用該函數
    // 該函數的主要任務就是去使用led驅動框架提供的設備註冊函數來註冊一個設備
    int ret = -1;
    
    // 在這裏去申請驅動用到的各種資源,當前驅動中就是GPIO資源
    if (gpio_request(GPIO_LED1, "led1_gpj0.3")) 
    {
        printk(KERN_ERR "gpio_request failed\n");
    } 
    else 
    {
        // 設置爲輸出模式,並且默認輸出1讓LED燈滅
        gpio_direction_output(GPIO_LED1, 1);   //通過gpio庫統一訪問
    }
    
    
    
    // led1
    mydev1.name = "led1";
    mydev1.brightness = 0;    
    mydev1.brightness_set = s5pv210_led1_set;
    
    ret = led_classdev_register(NULL, &mydev1);
    if (ret < 0) {
        printk(KERN_ERR "led_classdev_register failed\n");
        return ret;
    }
    
    // led2
    mydev2.name = "led2";
    mydev2.brightness = 0;    
    mydev2.brightness_set = s5pv210_led2_set;
    
    ret = led_classdev_register(NULL, &mydev2);
    if (ret < 0) {
        printk(KERN_ERR "led_classdev_register failed\n");
        return ret;
    }
    
    // led3
    mydev3.name = "led3";
    mydev3.brightness = 0;    
    mydev3.brightness_set = s5pv210_led3_set;
    
    ret = led_classdev_register(NULL, &mydev3);
    if (ret < 0) {
        printk(KERN_ERR "led_classdev_register failed\n");
        return ret;
    }
    
    return 0;
}

static void __exit s5pv210_led_exit(void)
{
    led_classdev_unregister(&mydev1);
    led_classdev_unregister(&mydev2);
    led_classdev_unregister(&mydev3);
    
    gpio_free(GPIO_LED1);
}


module_init(s5pv210_led_init);
module_exit(s5pv210_led_exit);

// MODULE_xxx這種宏作用是用來添加模塊描述信息
MODULE_LICENSE("GPL");                            // 描述模塊的許可證
MODULE_AUTHOR("aston <[email protected]>");        // 描述模塊的作者
MODULE_DESCRIPTION("s5pv210 led driver");        // 描述模塊的介紹信息
MODULE_ALIAS("s5pv210_led");                    // 描述模塊的別名信息


 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章