美文网首页android驱动开发
android从驱动到应用之驱动层(一)

android从驱动到应用之驱动层(一)

作者: lutery | 来源:发表于2016-11-03 22:13 被阅读61次

    内核驱动层#

    流程##

    android内核驱动目录在如下文件夹

    android源码目录/kernel/drivers/

    我们要添加自己的内核驱动就是在这个目录下。

    一、 添加自己的文件目录
    比如ledhal

    二、 在创建的文件目录下,添加源文件,码上相应的代码

    #include <linux/fs.h>
    #include <linux/cdev.h>
    #include <linux/pci.h>
    #include <linux/kernel.h>
    #include <linux/init.h>
    #include <linux/module.h>
    #include <linux/delay.h>
    #include <linux/gpio.h>
    #include <asm/uaccess.h>
    #include <mach/map.h>
    #include <mach/regs-gpio.h>
    #include <mach/gpio-bank-m.h>
    
    #define DEVICE_NAME "rk3288_leds_hal"
    #define DEVICE_COUNT 1
    #define RK3288_LEDS_MAJOR 0
    #define RK3288_LEDS_MINOR 234
    
    #define RK3288_LEDS_HAI_WRITE_GPMPUD 1
    #define RK3288_LEDS_HAI_WRITE_GPMCON 2
    #define RK3288_LEDS_HAI_WRITE_GPMDAT 3
    #define RK3288_LEDS_HAI_READ_GPMPUD 4
    #define RK3288_LEDS_HAI_READ_GPMCON 5
    #define RK3288_LEDS_HAI_READ_GPMDAT 6
    
    static unsigned char mem[5]; // 第1个字节:GPM寄存器类型,后面4个字节保存GPM寄存器的值
    
    static int major = RK3288_LEDS_MAJOR;
    static int minor = RK3288_LEDS_MINOR;
    static dev_t dev_number;
    static struct class* leds_class = NULL;
    
    static int byte_to_int(unsigned char buf[], int start)
    {
        int n = 0;
        n = ((int) buf[start]) << 24 | ((int) buf[start + 1]) << 16
                | ((int) buf[start + 2]) << 8 | ((int) buf[start + 3]);
        return n;
    }
    
    static void int_to_bytes(int n, unsigned char buf[], int start)
    {
        buf[start] = n >> 24;
        buf[start + 1] = n >> 16;
        buf[start + 2] = n >> 8;
        buf[start + 3] = n;
    }
    
    static ssize_t rk3288_leds_hal_write(struct file* file, const char __user* buf)
    {
        printk("~~~~~~~~~~~~~~~~~~~~~~~~~~");
        printk("rk3288_leds_hal_write");
        printk("~~~~~~~~~~~~~~~~~~~~~~~~~~");
    
        return 5;
    }
    
    static ssize_t rk3288_leds_hal_read(struct file* file, char __user* buf, size_t count, loff_t* ppos)
    {
        printk("~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
        printk("rk3288_leds_hal_read");
        printk("~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
    
        return 5;
    }
    
    static struct file_operations dev_fops =
    { .owner = THIS_MODULE, .read = rk3288_leds_hal_read, .write = rk3288_leds_hal_write };
    
    static struct cdev leds_cdev;
    
    static int leds_create_device(void)
    {
        int ret = 0;
        int err = 0;
    
        cdev_init(&leds_cdev, &dev_fops);
        leds_cdev.owner = THIS_MODULE;
        if (major > 0)
        {
            dev_number = MKDEV(major, minor);
            err = register_chrdev_region(dev_number, DEVICE_COUNT, DEVICE_NAME);
            if (err < 0)
            {
                printk(KERN_WARNING "register_chrdev_region() failed\n");
                return err;
            }
        }
        else
        {
            err = alloc_chrdev_region(&leds_cdev.dev, 10, DEVICE_COUNT, DEVICE_NAME);
    
            if (err < 0)
            {
                printk(KERN_WARING "alloc_chrdev_region() failed\n");
                return err;
            }
    
            major = MAJOR(leds_cdev.dev);
            minor = MINOR(leds_cdev.dev);
    
            dev_number = leds_cdev.dev;
        }
    
        ret = cdev_add(&leds_cdev, dev_number, DEVICE_COUNT);
        leds_class = class_create(THIS_MODULE, DEVICE_NAME);
        device_create(leds_class, NULL, dev_number, NULL, DEVICE_NAME);
    
        return ret;
    }
    
    static int leds_init(void)
    {
        int ret;
        ret = leds_create_device();
        printk(DEVICE_NAME"\tinitalized\n");
        printk(KERN_EMERG"test1fdddfs1t\n");
        return ret;
    }
    
    static void leds_destroy_devoce(void)
    {
        device_destroy(leds_class, dev_number);
    
        if (leds_class)
        {
            class_destroy(leds_class);
        }
        unregister_chrdev_region(dev_number, DEVICE_COUNT);
    
        return;
    }
    
    static void leds_exit(void)
    {
        leds_destroy_device();
        printk(DEVICE_NAME"\texit!\n");
    }
    
    module_init(leds_init);
    module_exit(leds_ext);
    MODULE_LICENSE("GPL");
    MODULE_AUTHOR("Lutery");
    

    三、 创建Kconfig文件,用于内核配置

    config LEDHAL
            tristate "Led For Hal"
            help
                Hellp Fore LedHal
    

    四、 创建Makefile文件

    obj-$(CONFIG_LEDHAL) += rk3288_leds_hal.o
    

    五、 配置内核驱动Kconfig和Makefile文件
    如果需要讲自己添加的驱动添加到内核里面,需要做其他额外的设置。找到kernel/drivers文件夹下载Kconfig文件,在内部添加如下代码

    source "drivers/ledhal/Kconfig"
    

    找到kernel/drivers文件夹下的Makefile文件,在里面添加如下代码

    obj-y                     += ledhal/
    

    完成如上之后,回到kernel文件夹下,输入如下命令:

    make menuconfig
    

    将需要添加的驱动以编译进内核的方式进行保存。
    然后就可以在kernel文件夹下进行编译

    //这段会将配置恢复初始配置,一般编译的时候不要输入
    make firefly-rk3288_defconfig
    make -j8 firefly-rk3288.img
    

    六、 编译完成后就可以讲生成的kernel.img文件烧录到开发板上

    原理##

    问题##

    在烧录过程中,可能会出现烧录成功但是没有生成驱动的问题,这个时候并不一定是驱动初始化运行出现问题,而是需要重新全部烧录一遍,也许可能会生效

    相关文章

      网友评论

        本文标题:android从驱动到应用之驱动层(一)

        本文链接:https://www.haomeiwen.com/subject/iyxbuttx.html