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

本文介绍了使用内核提供的驱动框架进行S5PV210平台LED驱动开发的过程,包括框架源码中的设备绑定和字符设备注册,以及自定义驱动源码中如何利用GPIO控制LED亮灭,通过平台总线进行驱动注册和卸载。
摘要由CSDN通过智能技术生成

前言

驱动开发框架由内核开发人员提供,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
    评论
要点亮LED,需要使用GPIO控制器驱动。以下是在Linux使用GPIO驱动框架点亮LED的步骤: 1. 确定GPIO引脚编号 首先需要确定要使用哪个GPIO引脚,并获取该引脚的GPIO编号。可以通过查看设备树或者GPIO控制器的文档来确定GPIO编号。 2. 编写GPIO驱动程序 在Linux使用GPIO驱动框架,可以通过编写内核模块来控制GPIO。以下是一个简单的GPIO驱动程序示例: ```c #include <linux/module.h> #include <linux/kernel.h> #include <linux/gpio.h> #include <linux/init.h> #define LED_GPIO 2 // GPIO引脚编号 static int __init led_init(void) { int ret; // 申请GPIO ret = gpio_request(LED_GPIO, "LED"); if (ret < 0) { printk(KERN_ERR "Failed to request GPIO\n"); return ret; } // 将GPIO设置为输出 ret = gpio_direction_output(LED_GPIO, 1); if (ret < 0) { printk(KERN_ERR "Failed to set GPIO direction\n"); gpio_free(LED_GPIO); return ret; } printk(KERN_INFO "LED driver initialized\n"); return 0; } static void __exit led_exit(void) { // 将GPIO设置为高电平 gpio_set_value(LED_GPIO, 1); // 释放GPIO gpio_free(LED_GPIO); printk(KERN_INFO "LED driver exited\n"); } module_init(led_init); module_exit(led_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Your Name"); MODULE_DESCRIPTION("A simple GPIO driver for LED"); ``` 3. 编译内核模块并加载 将以上代码保存为led.c文件,并使用以下命令编译内核模块: ```sh $ make -C /lib/modules/$(uname -r)/build M=$(pwd) modules ``` 然后使用以下命令加载内核模块: ```sh $ sudo insmod led.ko ``` 此时,LED应该会点亮。 4. 卸载内核模块 使用以下命令卸载内核模块: ```sh $ sudo rmmod led ``` 此时,LED应该会熄灭。 注意:在实际使用中,需要根据具体的硬件平台和GPIO控制器的型号进行相应的修改。另外,在使用GPIO控制器驱动时,需要特别注意GPIO的电气特性,以免损坏硬件。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值