【Linux高级驱动】linux设备驱动模型之平台设备驱动机制【转】

【1:引言: linux字符设备驱动的基本编程流程】

转自:http://www.cnblogs.com/lcw/p/3802579.html
1.实现模块加载函数
  a.申请主设备号
    register_chrdev(major,name,file_operations);
  b.创建字符设备cdev,注册字符设备
    cdev_alloc cdev_init cdev_add 
  c.创建设备文件
    class_create device_create
  d.注册中断
    ret =request_irq(中断号,...,...,...,...);
  e.映射
    虚拟地址=ioremap(物理地址,大小)
  f.初始化(初始化等待队列头,初始化tasklet,初始化工作队列)
  ...
2.实现模块卸载函数
3.构建file_operations结构体变量
4.实现操作硬件的方法
  xxx_open xxx_write xxx_read



    为了提高驱动的可移植性,减少驱动开发周期,最好将跟硬件/平台相关的东西分离出来,以便增强驱动的可移植性

 

    中断号,物理地址----->归为设备资源

    最好将设备资源与设备驱动分离开来

                       平台设备驱动机制
platform_device                             platform_driver
设备资源(设备)           <------>            设备驱动

 

【2:设备总线驱动模型:内核用来管理设备与驱动的一种方式】

 

    设备总线驱动模型:以对象的思想来实现的
    每一个设备对应唯一的一个驱动
    每个驱动则可能服务多个设备
    系统中有很多总线:1)实际的物理总线(如:i2c总线,usb总线,SDIO总线,SPI总线...)
                     2)虚拟总线(只有一条:平台总线)

【对象思想】

/*1.在系统用来表示一个设备*/
struct device {
 struct device_driver *driver;  //设备驱动
 struct bus_type *bus;     //所属总线
 struct device  *parent;   //父设备
 dev_t   devt;     //设备号
 void  *platform_data;    //私有数据
 ....
}

/*2.在系统中用来表示设备驱动*/
struct device_driver {
 const char  *name;   //驱动名字
 struct bus_type  *bus;  //所属总线
 struct module  *owner;  //拥有者
 int (*probe) (struct device *dev); //probe函数
}

/*3.在系统中用来表示总线*/
struct bus_type {
 const char  *name;   //总线名字
 /*mach函数,匹配函数,每条总线里面都会有自己的
  *mach,但不同总线的mach的匹配方法可能会不同
  */
 int (*match)(struct device *dev, struct device_driver *drv);  
 
 /*当设备与驱动匹配成功的时候,便会调用probe函数
  *不过,一般总线中不会实现probe函数,在匹配成功
  *的时候,会直接调用设备驱动中的probe函数
  */
 int (*probe)(struct device *dev);
 int (*remove)(struct device *dev);
}

 

【设备总线驱动模型里面的操作函数】

/*1.总线注册*/
int bus_register(struct bus_type *bus)
void bus_unregister(struct bus_type *bus)
/*2.设备注册*/
int device_register(struct device *dev)
void device_unregister(struct device *dev)
/*3.设备驱动注册*/
int driver_register(struct device_driver *drv)
void driver_unregister(struct device_driver *drv)

 

【3:平台设备驱动机制】

借助于设备总线驱动模型,虚拟出一条总线,用来实现设备资源与设备驱动的匹配
===============================================
平台设备驱动机制采用了:分离的思想,对象的思想

                       分离的思想:设备资源与设备驱动分离开

【对象思想】

/*1.平台设备结构体*/
struct platform_device {
 const char * name;     //名字
 int  id;
 struct device dev;    //设备结构体
 u32  num_resources;    //资源数量
 struct resource * resource;      //设备资源
 const struct platform_device_id *id_entry;
 /* arch specific additions */
 struct pdev_archdata archdata;
};

/*2.平台驱动结构体*/
struct platform_driver {
 int (*probe)(struct platform_device *);  //probe函数
 int (*remove)(struct platform_device *);
 void (*shutdown)(struct platform_device *);
 int (*suspend)(struct platform_device *, pm_message_t state);
 int (*resume)(struct platform_device *);
 struct device_driver driver;  //设备驱动
 const struct platform_device_id *id_table;
};

/*3.虚拟总线:平台总线结构体*/
struct bus_type platform_bus_type = {
 .name  = "platform",   //总线名字
 .dev_attrs = platform_dev_attrs,
 .match  = platform_match,  //匹配函数
 .uevent  = platform_uevent,
 .pm   = &platform_dev_pm_ops,
};

/*4.资源结构体*/
struct resource {
 resource_size_t start;   //起始
 resource_size_t end;   //结束
 const char *name;    //名字
 unsigned long flags;   //标号
 struct resource *parent, *sibling, *child;
};

//平台设备驱动机制中如何来实现设备与驱动的匹配
static int platform_match(struct device *dev, struct device_driver *drv)
{
 struct platform_device *pdev = to_platform_device(dev);
 struct platform_driver *pdrv = to_platform_driver(drv);
 /* match against the id table first :可能支持多个设备*/
 if (pdrv->id_table)
  return platform_match_id(pdrv->id_table, pdev) != NULL;
 /*平台设备里面的名字,与设备驱动里面的名字匹配*/
 return (strcmp(pdev->name, drv->name) == 0);
}

 

【总线注册】

/*内核启动时的第一个C语言入口函数*/
start_kernel     //init/main.c
     rest_init
     /*创建一个内核线程*/
     kernel_thread(kernel_init, NULL, CLONE_FS | CLONE_SIGHAND);  
     kernel_init
          do_basic_setup   //init/main.c
           driver_init
            platform_bus_init
         /*1.注册平台总线*/
         bus_register(&platform_bus_type);

 

【平台设备驱动模型的关键接口函数】

/*1.注册平台设备*/
int platform_device_register(struct platform_device *pdev)
void platform_device_unregister(struct platform_device *pdev)

/*2.注册平台驱动*/
int platform_driver_register(struct platform_driver *drv)
void platform_driver_unregister(struct platform_driver *drv)

/*3.获取平台资源*/
platform_get_resource(struct platform_device * dev, unsigned int type, unsigned int num)

 

【linux设备驱动之设备总线驱动模型】

 

【设备总线驱动模型】

@成鹏致远(wwwlllll@126.com)

时间: 2024-09-20 00:50:00

【Linux高级驱动】linux设备驱动模型之平台设备驱动机制【转】的相关文章

linux驱动-linux字符设备驱动求助:设备号无法释放

问题描述 linux字符设备驱动求助:设备号无法释放 我在驱动中,资源释放时调用了unregister_chrdev_region函数,为什么用rmmod卸载驱动模块之后,/proc/devices里边仍能够显示我的驱动设备啊? lsmod中已经没有我写的驱动模块了. 是因为设备号没能正确释放么? 解决方案 当应用程序打开设备节点时,内核调用相应驱动程序的open()函数.可以在shell中执行以下代码来触发cmos_open()的执行: bash> cat /dev/cmos/0 当应用程序关

linux内核 声卡驱动-platform匹配问题,没有对应的平台设备?

问题描述 platform匹配问题,没有对应的平台设备? 大家好: 我用的内核版本是linux-3.4.96,在sound/soc/samsung/s3c24xx_simtec_hermes.c这个文件里有一下代码: static struct platform_driver simtec_audio_hermes_platdrv = { .driver = { .owner = THIS_MODULE, .name = "s3c24xx-simtec-hermes-snd", .pm

如何实现Linux下的U盘(USB Mass Storage)驱动

摘要 本文主要介绍了USB Mass Storage的相关的各种协议之间的关系,以及如何在Linux的USB驱动框架下实现U盘驱动 本文提供多种格式供: 在线阅读 HTML HTMLs PDF CHM TXT RTF 下载(7zip压缩包) HTML HTMLs PDF CHM TXT RTF HTML版本的在线地址为: http://www.crifan.com/files/doc/docbook/usb_disk_driver/release/html/usb_disk_driver.htm

arm驱动linux异步通知与异步IO【转】

  转自:http://blog.csdn.net/chinazhangzhong123/article/details/51638793 <[ arm驱动] linux异步通知与 异步IO>涉及内核驱动函数二个,内核结构体一个,分析了内核驱动函数二个:可参考的相关应用程序模板或内核驱动模板二个,可参考的相关应用程序模板或内核驱动三个 描述:设备文件IO访问:阻塞与非阻塞io访问,poll函数提供较好的解决设备访问的机制,但是如果有了异步通知整套机制就更加完整了 一.阻塞 I/O,非阻塞IO,

rtl8188-瑞昱RTL8188ETV无线网卡驱动Linux系统的谁有,谢谢

问题描述 瑞昱RTL8188ETV无线网卡驱动Linux系统的谁有,谢谢 在Linux里如何把8188ETV驱动加进去,下载的CD Linux不能加载RTL8188ETV无线网卡 解决方案 你留一个邮箱 晚上给你发 解决方案二: 瑞昱RTL8188cus 无线网卡驱动移植

Linux 下的五种 IO 模型详细介绍_Linux

概念说明 用户空间与内核空间 现在操作系统都是采用虚拟存储器,那么对32位操作系统而言,它的寻址空间(虚拟存储空间)为4G(2的32次方).操作系统的核心是内核,独立于普通的应用程序,可以访问受保护的内存空间,也有访问底层硬件设备的所有权限.为了保证用户进程不能直接操作内核(kernel),保证内核的安全,操作系统将虚拟空间划分为两部分,一部分为内核空间,一部分为用户空间.针对linux操作系统而言,将最高的1G字节(从虚拟地址0xC0000000到0xFFFFFFFF),供内核使用,称为内核空

《Linux 高级程序设计(第三版)》——第2章 Linux下C语言开发工具 2.1 常用编辑工具

第2章 Linux下C语言开发工具 Linux 高级程序设计(第三版) Linux操作系统绝大多数的内核代码都是由C语言编写,因此,在Linux下的应用程序,特别是需要与内核进行交互的程序一般都是由C语言编写的,C++程序并不多见,例如驱动开发几乎都是由C语言编写的.因此,本书所有内容都立足于Linux下的C程序开发.本章主要介绍Linux下进行C语言程序开发所必备的工具. 本章第1节主要介绍Linux环境下常用的开发工具,包括常用的编辑器.这些编辑器类似于Windows平台下的记事本和Word

《Linux 高级程序设计(第三版)》——导读

**前言**Linux应用开发是目前最为广泛的软件开发内容之一,同时也是从事Linux内核及驱动开发的基础.<Linux高级程序设计>一书经过两次出版,收到了大量的读者来信,对本书提出了各种意见和建议,同时,随着技术的更新,新技术.新应用不断涌现,综合各方面的考虑,笔者做了大量的修订工作,推出了第三版.(1)内容丰富.本书是作者多年计算机教学及工程经验总结,整合了Linux应用编程的绝大多数知识点,几乎涵盖了Linux操作系统下C应用编程的所有内容,包括工具使用及环境设置.文件及文件管理.进程

《Linux 高级程序设计(第三版)》——1.3 部分常用工具简介

1.3 部分常用工具简介 Linux 高级程序设计(第三版)1.3.1 tar打包器 如果要发布包含大量程序和文档的程序,则需对其进行打包压缩.在Shell命令行下,可以使用的文件压缩工具有:gzip.bzip2和zip.相应的压缩和解压工具如表1-5所示. tar类型的文件是几个文件和(或)目录在一个文件中的集合,tar命令用来创建备份和归档.tar使用的选项有以下几项. -c:创建一个新归档. -x:从归档中抽取文件.即解压缩. -j:压缩/解压bz2格式tar文件. -z:压缩/解压gz格