博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【Linux高级驱动】linux设备驱动模型之平台设备驱动机制
阅读量:6756 次
发布时间:2019-06-26

本文共 3983 字,大约阅读时间需要 13 分钟。

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

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)

 

转载地址:http://kegho.baihongyu.com/

你可能感兴趣的文章
产品经理:想爱没那么简单
查看>>
Java:按值传递还是按引用传递详细解说
查看>>
(转)HTML字符实体(Character Entities),转义字符串(Escape Sequence)
查看>>
去掉 Android工程中让人很不爽的“黄色警告”
查看>>
aliyun阿里云Maven仓库地址
查看>>
jdk1.8 HashMap源码分析(resize函数)
查看>>
再看static数据成员
查看>>
Pthon Matplotlib 画图
查看>>
十种排序算法实例说明总结
查看>>
Python 语言之 map/reduce
查看>>
Vue.js - Day4
查看>>
mysql之用户
查看>>
053(三十五)
查看>>
AddonSU Packages now available for LineageOS 15.1
查看>>
UVa 10970 - Big Chocolate
查看>>
C# API 如何保证使用托管对象的平台调用成功
查看>>
产品新版本发布前要做那些事呢
查看>>
hdu-1114 Piggy-Bank---完全背包
查看>>
批处理基础
查看>>
Android Disable Package/Component 跳过app安装
查看>>