目录: 一. bus-driver-device模型

    二. 运行结果,及错误解决

    三. 怎样利用以有的driver device驱动来写自已的beep-driver-device 驱动

        四. 总结

  怎样解决编译时出现内核提供的函数或变量没有定义,使用source insight搜索功能找到声明的头文件,然后包含该头件就行了:

  比如: error: implicit declaration of function 'copy_from_user'

  解决:使用source insight搜索功能,可以找到copy_from_user函数是在linux/uaccess.h 头文件中定义,所以包含此头文件就行了。

一. bus-driver-device模型:

  

二. 运行结果,及错误解决

步骤一:驱动运行结果:

从上图红色线可知,卸载led_dev失败原因是因为led_dev.c  platform_device中没有加release()函数;所以正确的方法如下:在led_dev.c 中:

static struct platform_device led_dev = {
    .name = "mini210_led",
    .id = 0,
    .dev = {
        .release = led_release,    //必须在.dev中加入
        //.platform_data = &smsc911x_config,
    },
    .num_resources = ARRAY_SIZE(led_resources),
    .resource = led_resources,
};

步骤二:改正步骤一的问题后,重新编译,下载到板上,又出现下面情况

错误:

通过开发板串口返回的错:[root@FriendlyARM driver]# rmmod led_dev
rmmod: remove 'led_dev': Device or resource busy

再查看编译出现的警告:

上图说led_dev_exit定义了,但没有使用,所以原来是modele_exit(led_dev_exit); //这里错了,会导致rmmod 失败:Device or resource busy;

正确写法:module_exit(led_dev_exit);

解决上面2个步骤后,这驱动程序问题就解决了。

三. 怎样利用以有的driver device驱动来写自已的beep-driver-device 驱动

  新建beep_dev.c  与 beep_drv.c文件

  1) 用source insight软件打开beep_dev.c:

  搜索platform_device 找到有platform_device 类型定义的变量,这里我找到的是3ds_debugboard.c参考此文件来编写自己的驱动,打开此文件并找到以下内容并复制到beep_dev.c文件中:

static struct resource smsc911x_resources[] = {
    {
        .flags = IORESOURCE_MEM,
    } , {
        .start = EXPIO_INT_ENET,
        .end = EXPIO_INT_ENET,
        .flags = IORESOURCE_IRQ,
    },
};static struct platform_device smsc_lan9217_device = {
    .name = "smsc911x",
    .id = 0,
    .dev = {
        .platform_data = &smsc911x_config,
    },
    .num_resources = ARRAY_SIZE(smsc911x_resources),
    .resource = smsc911x_resources,
};

beep_dev.c完整代码:

/*分配,设置,注册一个platform_device*/

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/sched.h>
#include <linux/poll.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/cdev.h>
#include <linux/miscdevice.h>
#include <linux/serial_core.h>

/*分配,设置,注册一个platform_device*/

static struct resource beep_resources[] = {
    [0] = {
        /*.start = 0xE0200280, //0xE02000A0;
        .end = 0xE0200280 + 8 - 1,
        .flags = IORESOURCE_MEM,*/
        .start = 0xE02000A0, //;
        .end = 0xE02000A0 + 8 - 1,
        .flags = IORESOURCE_MEM,
    },
    [1] = {
        .start = 0,
        .start = 0,
        .flags = IORESOURCE_IRQ,
    }
};

static void beep_release(struct device *dev)
{
    printk("beep_release\n");
}

static struct platform_device beep_dev = {
    .name = "mini210_beep",
    .id = 0,
    .dev = {
        .release = beep_release,
        //.platform_data = &smsc911x_config,
    },
    .num_resources = ARRAY_SIZE(beep_resources),
    .resource = beep_resources,
};

static int beep_dev_init(void)
{
    platform_device_register(&beep_dev);
    return 0;
}

static void beep_dev_exit(void)
{
    platform_device_unregister(&beep_dev);
}

module_init(beep_dev_init);
//modele_exit(beep_dev_exit);  //这里错了,会导致rmmod 失败:Device or resource busy
module_exit(beep_dev_exit);

MODULE_LICENSE("GPL");

2) 用source insight软件打开beep_drv.c:

搜索platform_driver 找到有platform_driver 类型定义的变量,这里我使用的是88pm8607.c参考此文件来编写自己的驱动,打开此文件并找到以下内容并复制到beep_drv.c文件中:

static int __devinit pm8607_regulator_probe(struct platform_device *pdev)
{
    struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent);
    struct pm8607_regulator_info *info = NULL;
    struct regulator_init_data *pdata = pdev->dev.platform_data;
    struct resource *res;
    int i;

res = platform_get_resource(pdev, IORESOURCE_IO, 0);
    if (res == NULL) {
        dev_err(&pdev->dev, "No I/O resource!\n");
        return -EINVAL;
    }
    for (i = 0; i < ARRAY_SIZE(pm8607_regulator_info); i++) {
        info = &pm8607_regulator_info[i];
        if (info->desc.id == res->start)
            break;
    }
    if ((i < 0) || (i > PM8607_ID_RG_MAX)) {
        dev_err(&pdev->dev, "Failed to find regulator %llu\n",
            (unsigned long long)res->start);
        return -EINVAL;
    }
    info->i2c = (chip->id == CHIP_PM8607) ? chip->client : chip->companion;
    info->chip = chip;

/* check DVC ramp slope double */
    if ((i == PM8607_ID_BUCK3) && info->chip->buck3_double)
        info->slope_double = 1;

/* replace driver_data with info */
    info->regulator = regulator_register(&info->desc, &pdev->dev,
                         pdata, info);
    if (IS_ERR(info->regulator)) {
        dev_err(&pdev->dev, "failed to register regulator %s\n",
            info->desc.name);
        return PTR_ERR(info->regulator);
    }

platform_set_drvdata(pdev, info);
    return 0;
}

static int __devexit pm8607_regulator_remove(struct platform_device *pdev)
{
    struct pm8607_regulator_info *info = platform_get_drvdata(pdev);

platform_set_drvdata(pdev, NULL);
    regulator_unregister(info->regulator);
    return 0;
}

static struct platform_driver pm8607_regulator_driver = {
    .driver        = {
        .name    = "88pm860x-regulator",
        .owner    = THIS_MODULE,
    },
    .probe        = pm8607_regulator_probe,
    .remove        = __devexit_p(pm8607_regulator_remove),
};

beep_drv.c完整代码:

  #include <linux/module.h>

#include <linux/init.h>
#include <linux/fs.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/sched.h>
#include <linux/pm.h>
#include <linux/slab.h>
#include <linux/sysctl.h>
#include <linux/proc_fs.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
#include <linux/input.h>
#include <linux/uaccess.h>

#include <asm/io.h>

static int major;

static struct class *cls;  //可加可不加,作用: 系统自动帮我们创建设备节点
static volatile unsigned long *GPIOCON;
static volatile unsigned long *GPIODAT;
static int pin;

static int beep_open(struct inode *inode, struct file *file)
{
    /* 配制为输出*/
    *GPIOCON &= ~(0xf<<(pin*4));
    *GPIOCON |= (0x1<<(pin*4));
    return 0;
}

static ssize_t beep_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
{
    int val;
    copy_from_user(&val, buf, count);
    printk("beep_write: val:%d, pin:%d\n", val, pin);
    //val = 0;
    if (val == 1) {
        //off beep
        *GPIODAT &= ~(1<<pin);
    }else {
        //on beep
        *GPIODAT |= (1<<pin);
    }
    return 0;
}

static struct file_operations beep_fops = {
    .owner = THIS_MODULE,
    .open  = beep_open,
    .write = beep_write,
};

static int beep_probe(struct platform_device *pdev)
{
    struct resource *res;
    /* 根据platform_device的资源进行ioremap*/

  /* 这里res将获取beep_dev中beep_resources*/
    res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
    GPIOCON = ioremap(res->start, res->end - res->start + 1);
    GPIODAT = GPIOCON + 1;

res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
    pin = res->start;    //获取.start 的内容
    
    /* 注册字符设备驱动程序*/
    printk("beep_probel, found beep\n");
    major = register_chrdev(0, "mini210_beep", &beep_fops);
    cls = class_create(THIS_MODULE, "mini210_beep");  //
    device_create(cls, NULL, MKDEV(major, 0), NULL, "mini210_beep");

        /* 在开发板上建立/dev/mini210_beep 系统节点*/
    //register_chrdev_region(,unsigned count,const char * name);
    //*GPIODAT = 1;
    return 0;
}

static int beep_remove(struct platform_device *pdev)
{
    /*卸载字符设备驱动程序*/
    /* iounmap */
    printk("beep_remove, remove beep\n");

device_destroy(cls, MKDEV(major, 0));

class_destroy(cls);
    unregister_chrdev(major, "mini210_beep");
    iounmap(GPIOCON);
    
    return 0;
}

static struct platform_driver beep_drv = {
    .probe        = beep_probe,
    .remove        = __devexit_p(beep_remove),
    .driver        = {
        .name    = "mini210_beep",   //用来与beep_dev文件中:.name来匹配;因为bus是使          // 用.name搜索并匹配,才能对应。
        .owner    = THIS_MODULE,
/*#ifdef CONFIG_PM
        .pm    = &gpio_keys_pm_ops,
#endif*/
    }
};

static int beep_drv_init(void)
{
    platform_driver_register(&beep_drv);
    return 0;
}

static void beep_drv_exit(void)
{
    platform_driver_unregister(&beep_drv);    
}

module_init(beep_drv_init);
module_exit(beep_drv_exit);

MODULE_LICENSE("GPL");

S5PV210之beep-bus模型 linux3.0.8驱动的更多相关文章

  1. (转)S5pv210 HDMI 接口在 Linux 3.0.8 驱动框架解析 (By liukun321 咕唧咕唧)

    作者:liukun321 咕唧咕唧 日期:2014.1.18 转载请标明作者.出处:http://blog.csdn.net/liukun321/article/details/18452663 本文 ...

  2. S5pv210 HDMI 接口在 Linux 3.0.8 驱动框架解析

    作者:liukun321 咕唧咕唧 日期:2014.1.18 转载请标明作者.出处:http://blog.csdn.net/liukun321/article/details/18452663 本文 ...

  3. S5PV210之GPIO模拟I2c时序之pcf8591与at24xx linux3.0.8驱动

    目录:一. 说明 二. 驱动程序说明及问题 三. 案例一       四. 案例二 一. 说明 mini210开发板上带了at24c08, 看了linux内核自带的at24.c的驱动程序,编译下载到看 ...

  4. S5PV210之添加缺少的-内核提供的'.h'文件 linux3.0.8驱动

    怎样解决编译时出现内核提供的函数或变量没有定义,使用source insight搜索功能找到声明的头文件,然后包含该头件就行了: 比如: error: implicit declaration of ...

  5. linux-3.0下input_dev模型按键驱动

    该代码在FL2440开发板上测试通过,为方便教学,将驱动中的platform_device和platform_driver故意分为两个驱动模块. [guowenxue@centos6 input_kb ...

  6. Linux内核源码分析--内核启动之(6)Image内核启动(do_basic_setup函数)(Linux-3.0 ARMv7)【转】

    原文地址:Linux内核源码分析--内核启动之(6)Image内核启动(do_basic_setup函数)(Linux-3.0 ARMv7) 作者:tekkamanninja 转自:http://bl ...

  7. linux-3.0内核移植到fl2440开发板(以MINI2440为模板)

    我们的fl2440开发板使用的是s3c2440的芯片,与MINI2440十分相似,因此需要改动的地方不多,移植也比较容易. 1.[weishusheng@localhost kernel]$ sudo ...

  8. Fixflow引擎解析(二)(模型) - BPMN2.0读写

    Fixflow引擎解析(四)(模型) - 通过EMF扩展BPMN2.0元素 Fixflow引擎解析(三)(模型) - 创建EMF模型来读写XML文件 Fixflow引擎解析(二)(模型) - BPMN ...

  9. Linux内核源码分析--内核启动之(3)Image内核启动(C语言部分)(Linux-3.0 ARMv7)

    http://blog.chinaunix.net/uid-20543672-id-3157283.html Linux内核源码分析--内核启动之(3)Image内核启动(C语言部分)(Linux-3 ...

随机推荐

  1. 如何从NFS文件系统启动

    笔记,备忘! 步骤: 1.设置好NFS服务器 2.修改uboot启动参数bootarg setenv bootargs console=ttySAC0 root=/dev/nfs nfsroot=19 ...

  2. Rocketmq-尝试理解

    普通的信息发送和消费 首先要启动nameserver和broker,nameserver是一个几乎无状态节点.broker分为master和slave,master和slave的对应关系通过指定相同的 ...

  3. Deep Learning in Bioinformatics

    最近在学tensorflow,深度学习的开源工具,很好奇在生信领域深度学习都能做些什么东西. 镇楼的综述:Deep Learning in Bioinformatics 几篇文章读读看: Deep l ...

  4. Oracle session inactive状态临时表数据未清空问题

    问题描述:Oracle数据库,java代码使用某数据库实例,获取connection并在使用结束关闭,而session未销毁,而是状态变为inactive从而导致临时表数据未清空. Oracle临时表 ...

  5. iOS开发数据库SQLite的使用

    iOS系统自带Core Data来进行持久化处理,而且Core Data可以使用图形化界面来创建对象,但是Core Data不是关系型数据库,对于Core Data来说比较擅长管理在设备上创建的数据持 ...

  6. 第四周 技术随笔psp

    本周psp 类型 内容 开始时间 结束 打断时间 净时间 写随笔 Scrum会议 23:46 00:27 0 41分

  7. Binary Tree Level Order Traversal II [LeetCode]

    Given a binary tree, return the bottom-up level order traversal of its nodes' values. (ie, from left ...

  8. Java 集合系列 06 Stack详细介绍(源码解析)和使用示例

    java 集合系列目录: Java 集合系列 01 总体框架 Java 集合系列 02 Collection架构 Java 集合系列 03 ArrayList详细介绍(源码解析)和使用示例 Java ...

  9. 5月18日 HTML 个人简历

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  10. css+div如何解决文字溢出

    看到标题你一定很轻易就会想到截断文字加“...”的做法.哈哈,就是这样.其实写这篇日志也只是把这样方法做个记录,因为似乎还有很多人不记得碰到这样的情况该如何处理. 首先,先解释一下,一般用div+cs ...