Linux平台设备框架驱动

linux平台设备框架驱动      平台设备框架(platform)是将一个驱动分为设备层和驱动层两个部分,通过总线模型将设备和驱动进行绑定。在系统中每注册一个设备,都会与之匹配一个驱动,同样的,每注册一个驱动也会与之匹配一个设备。
      通常 linux 设备和驱动通常都需要挂接在一种总线上,对于本身依附于 pci、 usb、 i2 c、 spi 等的设备而言,这自然不是问题,但是在嵌入式系统里面, soc 系统中集成的独立的外设控制器、挂接在 soc 内存空间的外设等却不依附于此类总线。
      基于总线框架的模型结构,linux下就衍生了平台设备框架模型(platform),平台设备总线是一种虚拟总线,称为platform总线。对应的设备层称为platform_device;驱动层称为platform_driver。设备层和驱动层通过平台设备总线进行匹配管理。
1.平台设备框架特性     平台模型采用了分层结构,把一个设备驱动程序分成了两个部分:
    平台设备( platform_device)和平台驱动( platform_driver)。
    平台设备将设备本身的资源注册进内核,可以由内核统一管理。
    将硬件资源和驱动接口分离,编译代码的维护与移植。
2.平台设备总线相关接口函数 2.1 设备层接口函数   每个设备的系统通过设备结构体struct platform_device保存。结构体原型在 include/linux/platform_devcie.h 中定义。
struct platform_device { const char * name; //设备名字,驱动层和设备层匹配标志 int id;//通常填-1 struct device dev;//设备结构体信息 u32 num_resources;//资源个数 struct resource * resource;//资源内容 const struct platform_device_id *id_entry; /* mfd cell pointer */ struct mfd_cell *mfd_cell; /* arch specific additions */ struct pdev_archdata archdata;};  struct device dev结构信息  struct device dev 结构体是用来实现设备模型的。这个结构体中成员比较多,结构体原型在 include/linux/devcie.h 中定义。我们常关心的是其中的两个成员:
 平台数据指针: void *platform_data;
 资源释放函数: void (*release)(struct device *dev);
 平台数据指针platform_data是一个void *类型指针,可以向驱动层传递任意数据,release资源释放函数接口在设备层一定要自己实现,否则在设备层释放资源时会报错。
 以下列举其中几个成员结构:
struct device { const char *init_name; /*逻辑设备的名字*/ struct device_type *type; /* 设备类型 */ struct bus_type *bus; /* 设备所属的总线类型 */ struct device_driver *driver;/* 指向开辟 struct device 结构 driver 指针*/ void *platform_data; /* 平台设备指针 */ dev_t devt; /* 存放设备号 dev_t,creates the sysfsdev */ struct class *class; /* 设备所属类*/ void (*release)(struct device *dev);/*设备资源释放函数*/}; struct resource * resource结构信息
struct resource * resource 结构体是用来保存设备资源内容信息。该结构体定义位置: include/linux/ioport.hstruct resource { resource_size_t start; //资源起始地址 resource_size_t end; //资源结构地址 const char *name;//资源名字 unsigned long flags;//资源类型 struct resource *parent, *sibling, *child;}; 设备层注册函数int platform_device_register(struct platform_device *pdev)函数功能: 注册平台设备;形参: pdev --设备结构体;返回值: 成功返回0,失败返回其它值; 设备层注销函数void platform_device_unregister(struct platform_device *pdev)函数功能: 注册平台设备;形参: pdev --设备结构体; 向内核添加多个设备int platform_add_devices(struct platform_device **devs, int num)函数功能: 向内核注册多个设备;形参: pdev --设备结构体;   num – 注册的设备个数返回值: 成功返回0,失败返回其它值; 2.2 驱动层接口函数   驱动层通过struct platform_driver 结构体保存相关信息,结构体定义位置: include/linux/devcie.h
  在该结构体中必须要实现接口函数:
  资源匹配函数:int (*probe)(struct platform_device *)
  资源释放函数:int (*remove)(struct platform_device *);
  驱动资源结构体:struct device_driver driver;
   一个驱动层可匹配多个设备层,若想同时匹配多个设备层,则通过id_table 指针完成匹配。
struct platform_driver { int (*probe)(struct platform_device *);//资源匹配函数 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;//匹配多多设备时需要填写}; struct device_driver driver 结构信息   struct device_driver driver 结构体中有个成员name必须要填写,当没有实现id_table指针时,设备层和驱动层就是通过该成员完成资源匹配。
struct device_driver { const char *name; //资源匹配参数 struct bus_type *bus; struct module *owner; const char *mod_name; /* used for built-in modules */ bool suppress_bind_attrs; /* disables bind/unbind via sysfs */ const struct of_device_id *of_match_table; int (*probe) (struct device *dev); int (*remove) (struct device *dev); void (*shutdown) (struct device *dev); int (*suspend) (struct device *dev, pm_message_t state); int (*resume) (struct device *dev); const struct attribute_group **groups; const struct dev_pm_ops *pm; struct driver_private *p;}; const struct platform_device_id *id_table 结构信息   该结构也是用于匹配设备资源,一个驱动层可以同时匹配多个设备层。
struct platform_device_id { char name[platform_name_size]; //资源匹配参数 kernel_ulong_t driver_data __attribute__((aligned(sizeof(kernel_ulong_t)))); //匹配设备层的 void *platform_data数据}; 驱动层注册和注销函数//驱动注册函数int platform_driver_register(struct platform_driver *drv)//驱动注销函数void platform_driver_unregister(struct platform_driver *drv) 3.平台设备框架应用示例 3.1 设备层注册示例     设备层注册步骤:
   填充struct device结构体,填写设备资源信息struct resource * resource;
   调用设备层注册函数platform_device_register();
   注销时调用注销函数platform_device_unregister;
#include #include #include #include #include #include #include #include #include static void platform_release(struct device *dev){ printk(资源释放完成n);}static struct resource resource[]={ [0]={ .start=exynos4x12_gpm4(0), .end=exynos4x12_gpm4(0), .name=led1, .flags=ioresource_mem }, [1]={ .start=exynos4x12_gpm4(1), .end=exynos4x12_gpm4(1), .name=led2, .flags=ioresource_mem }, };struct platform_device pdev={ .name=led_dev, .id=-1, .dev= { .release=platform_release,//资源释放函数 }, .num_resources=sizeof(resource)/sizeof(resource[0]), .resource=resource, };static int __init wbyq_platform_dev_init(void){ platform_device_register(&pdev); return 0;}/*驱动释放*/static void __exit wbyq_platform_dev_cleanup(void){ /*注销设备层*/ platform_device_unregister(&pdev);}module_init(wbyq_platform_dev_init);//驱动入口函数module_exit(wbyq_platform_dev_cleanup);//驱动出口函数module_license(gpl);//驱动注册协议module_author(it_ashui);module_description(exynos4 platform_dev driver); 3.2 驱动层注册示例 驱动层注册步骤:
填充 struct platform_driver结构体,实现资源匹配函数和资源释放函数;
调用设备层注册函数platform_driver_register();
注销时调用注销函数platform_driver_unregister;
#include #include #include #include #include #include #include #include #include static int platform_probe(struct platform_device *dev){ printk(资源匹配成功n); printk(资源个数:%dn,dev->num_resources); struct resource * resource=platform_get_resource(dev,ioresource_mem,0); if(resource) { printk(资源名:%ststart=%xtend=%xn,resource->name,resource->start,resource->end); } return 0; }static int platform_remove(struct platform_device *dev){ printk(资源释放成功n); return 0;}static struct platform_device_id id_table[]={ [0]= { .name=led_dev }, [1]= { .name=tiny4412_dev }, };static struct platform_driver drv={ .probe=platform_probe, .remove=platform_remove, .driver= { .name=platform_drv, }, .id_table=id_table,};static int __init wbyq_platform_drv_init(void){ platform_driver_register(&drv); printk(驱动层平台设备注册成功n); return 0;}/*驱动释放*/static void __exit wbyq_platform_drv_cleanup(void){ /*注销设备层*/ platform_driver_unregister(&drv); printk(驱动层平台设备注销成功n);}module_init(wbyq_platform_drv_init);//驱动入口函数module_exit(wbyq_platform_drv_cleanup);//驱动出口函数module_license(gpl);//驱动注册协议module_author(it_ashui);module_description(exynos4 platform_drv driver); 3.3 makefile文件ker_add=/home/wbyq/src_pack/linux-3.5all: make -c $(ker_add) m=`pwd` modules #arm-linux-gcc main.c -o app cp ./*.ko /home/wbyq/src_pack/rootfs/code make -c $(ker_add) m=`pwd` modules clean rm app -fobj-m +=platform_drv.o platform_dev.o platform_dev2.o 4 运行效效果


iphone8什么时候上市多少钱?iphone 8发布会时间确定,外观大改,无线充电器单独售卖,iPhone8价格贵到没朋友
基于A/D和DSP的高速数据采集系统方案介绍
打造智慧停车领域的领跑者:星创易联SR700工业路由器
蜂鸣器驱动电路图大全(五款蜂鸣器驱动电路原理图)
托管数据中心的灾难类型和解决措施
Linux平台设备框架驱动
受电动汽车市场影响,本田在中国裁员900人
“AI赋能 智引安防”——第七届中国·深圳智慧城市建设高峰论坛成功召开
电子变压器在新能源逆变器中有哪些应用呢?
Vishay发布超小尺寸具有业内最高亮度的LED
Android官方推出发推文称计划将于今年三季度向中国厂商收费
触摸延时开关电源电路设计详解 —电路图天天读(120)
LMZ31530RLGT替换解决方案的说明
vivo X60 系列手机的影像系统详细介绍:蔡司光学镜头,第二代微云台
简单介绍几种物联网相关技术在智慧林业中的应用
苹果手机指纹识别不了的原因及解决方法
Surface Duo充电端口周围的塑料出现了裂缝
详细解读CAN总线原理和数据帧问题
恩智浦推出业界首款全新超快速I2C总线控制器
收发一体芯片TRF7970A的特点性能及的NFC模块设计介绍