led驱动编写-使用驱动框架

前言

驱动开发框架由内核开发人员提供,SOC开发人员根据内核提供的驱动框架编写适合的硬件驱动,开发板厂商负责移植驱动到自己生产的开发板上,三者分工不同。

1 框架源码

文件路径: x210_kernel\drivers\leds
在这里插入图片描述
上面两个C源码文件由内核开发人员提供,简化了驱动开发的过程,例如:mknod /dev/名字 c 200 0

创建设备绑定主次设备号,这个步骤已经被包含在了框架里面,不需要自己在命令行中手动绑定。

框架中还提供了更加简便的字符设备注册函数,对注册的步骤进行了封装。

使用框架可以快速的进行驱动开发,和不使用框架开发实现的功能是相同的。

2 驱动源码

源码位置: kernel/drivers/leds/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>
#include <linux/platform_device.h>

#define GPIO_LED1       S5PV210_GPJ0(3)  //虚拟地址


#define X210_LED_OFF    1                       // X210中LED是正极接电源,负极节GPIO
#define X210_LED_ON             0                       // 所以1是灭,0是亮

//框架中的函数,在两个.C文件的其中之一中
static struct led_classdev mydev1;                      // 定义结构体变量




// 这个函数就是要去完成具体的硬件读写任务的
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
        //框架中使用枚举对0和255和非0且非255进行了枚举类型转换
        if (value == LED_OFF) //对应0
        {
                // 用户给了个0,希望LED灭
                //writel(0x11111111, GPJ0CON);
                // 读改写三部曲
                //writel((readl(GPJ0DAT) | (1<<3)), GPJ0DAT);
                //使用gpio库进行io寄存器设置
                gpio_set_value(GPIO_LED1, X210_LED_OFF);
        }
        else
        {
                // 用户给的是非0,希望LED亮
                //writel(0x11111111, GPJ0CON);
                //writel((readl(GPJ0DAT) & ~(1<<3)), GPJ0DAT);
                gpio_set_value(GPIO_LED1, X210_LED_ON);
        }
}


static int s5pv210_led_probe(struct platform_device *dev)
{
        // 用户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);
        }
        // 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;
        }
        return 0;
}

static int s5pv210_led_remove(struct platform_device *dev)
{
        led_classdev_unregister(&mydev1);
        gpio_free(GPIO_LED1);
        return  0;
}
static struct platform_driver s5pv210_led_driver = {
        .probe          = s5pv210_led_probe,
        .remove         = s5pv210_led_remove,
        .driver         = {
        		//这个名字要和注册的device名字形同
                .name           = "s5pv210_led",
                .owner          = THIS_MODULE,
        },
};
static int __init s5pv210_led_init(void)
{
		/*使用平台总线的形式进行驱动注册,当前内核中注册了平台总线
		设备才能成功的注册平台总线驱动,两者注册的顺序没有现后之分,					
		两者注册的时候,都会寻找对方进行匹配*/
        return platform_driver_register(&s5pv210_led_driver);
}

static void __exit s5pv210_led_exit(void)
{
        platform_driver_unregister(&s5pv210_led_driver);
}


module_init(s5pv210_led_init);
module_exit(s5pv210_led_exit);

// MODULE_xxx这种宏作用是用来添加模块描述信息

这个驱动中使用了gpio_request这个IO口申请函数,且九鼎自己实现的led驱动,也使用了这个函数,所以需要使用menuconfig取消对leds-x210.c这个文件的编译。一个IO口只能被申请一次,内核会进行记录。
在这里插入图片描述
上述驱动源码注册的设备地址:/sys/class/leds/led/led1,led1就是注册时候的名字。可以使用echo进行写入操作,控制LED的亮灭。
在这里插入图片描述

  • 7
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值