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;//通常填-1struct 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 sysfs"dev" */struct class *class; /* 设备所属类*/void (*release)(struct device *dev);/*设备资源释放函数*/
};
- struct resource * resource结构信息
struct resource * resource 结构体是用来保存设备资源内容信息。该结构体定义位置: include/linux/ioport.h
struct resource {resource_size_t start; //资源起始地址resource_size_t end; //资源结构地址const char *name;//资源名字unsigned long flags;//资源类型struct resource *parent, *sibling, *child;
};
在资源结构体中的资源类型flags,资源类型的相关宏定义位置: include/linux/ioport.h ,常用的资源类型如下:
#define IORESOURCE_TYPE_BITS 0x00001f00 /* Resource type */
#define IORESOURCE_IO 0x00000100 //IO 空间, 一般在 X86 框架中存在, ARM 一般没有
#define IORESOURCE_MEM 0x00000200 //内存空间,占用的是 CPU 4G 统一编址空间
#define IORESOURCE_IRQ 0x00000400 //中断号
#define IORESOURCE_DMA 0x00000800 //DMA
- 设备层注册函数
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 <linux/kernel.h>
#include <linux/module.h>
#include <asm/io.h>
#include <linux/miscdevice.h>
#include <linux/fs.h>
#include <linux/platform_device.h>#include <linux/gpio.h>
#include <mach/gpio.h>
#include <plat/gpio-cfg.h>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 <linux/kernel.h>
#include <linux/module.h>
#include <asm/io.h>
#include <linux/miscdevice.h>
#include <linux/fs.h>
#include <linux/platform_device.h>#include <linux/gpio.h>
#include <mach/gpio.h>
#include <plat/gpio-cfg.h>static int platform_probe(struct platform_device *dev)
{printk("资源匹配成功\n");printk("资源个数:%d\n",dev->num_resources);struct resource * resource=platform_get_resource(dev,IORESOURCE_MEM,0);if(resource){printk("资源名:%s\tstart=%x\tend=%x\n",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.5
all: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 cleanrm app -f
obj-m +=platform_drv.o platform_dev.o platform_dev2.o
4运行效效果
Linux平台设备框架驱动相关推荐
- 支持驱动最好的linux软件,Linux平台设备和驱动
一 platform总线 一个现实的linux设备驱动通常需要挂接在一种总线上,对于本身依附于PCI,USB,IIC,SPI等的设备而言,这自然不是问题,但是在嵌入式系统里面,SOC系统中集成的独立的 ...
- Linux平台设备驱动
在设备驱动程序中经常会见到和platform相关的字段,分布在驱动程序的多个角落,这也是2.6内核中比较重要的一种机制,把它原理弄懂,对以后分析驱动程序很有帮助:在linux2.6设备模型中,关心总线 ...
- linux平台设备驱动模型是什么意思,Linux设备驱动模型之我理解
点击(此处)折叠或打开 /* my_bus.c */ #include #include #include #include #include #include "my_bus.h&qu ...
- Linux 块设备 EMMC 驱动介绍
目录: 高质量文章导航-持续更新中 前置:硬件接口 EMMC(Embedded Multi-Media Card)是一种用于存储和传输数据的嵌入式存储器(芯片),通常用于移动设备和嵌入式设备中.Lin ...
- linux字符设备led驱动源码,字符设备驱动控制LED灯
开发板:龙芯1B PC:Ubuntu 13.10 本程序为字符设备驱动,提供控制led灯功能,如要实现控制需要自己写应用程序,打开驱动文件就可控制led灯,led灯通过gpio控制 #include ...
- Linux内核平台设备驱动模型platform_device和platform_driver框架
关于Linux平台设备驱动模型,并不是创建新的设备分类,是在原有的字符设备基础上使用,将设备和驱动分开,生成两个.ko文件. Linux内核维护一个全局设备链表,对应的总线会将驱动和设 ...
- platform框架--Linux MISC杂项框架--Linux INPUT子系统框架--串行集成电路总线I2C设备驱动框架--串行外设接口SPI 设备驱动框架---通用异步收发器UART驱动框架
platform框架 input. pinctrl. gpio 子系统都是 Linux 内核针对某一类设备而创建的框架, input子系统是管理输入的子系统 pinctrl 子系统重点是设置 PIN( ...
- Linux内核总线系统 —— 通用总线和平台设备
在 Linux内核输入子系统框架_Bin Watson的博客-CSDN博客 这篇文章中,我们详细分析了输入子系统.了解到了 dev 和 handler 分层的思想.而在 jz2440_输入子系统驱动程 ...
- 宋宝华:Linux设备与驱动的手动解绑与手动绑定
众所周知,Linux靠设备与驱动之间的match,来完成设备与驱动的bind,从而触发驱动的probe()成员函数被执行.每个bus都有相应的match方法,完成match的总的入口函数是: stat ...
最新文章
- ASP.net MVC基础
- element中el-image怎样显示图片
- Spring集成Mybatis plus
- swift:Optional Type 、Swift和Objective-C混编的讲解
- WinAPI【消息及相关结构体】
- linux下mongodb 安装,linux下mongodb安装
- 取代上万行遗留代码,机器学习模型终“上位”
- php memcache 扩展 libmemcached 安装
- Mysql 的ERROR 1005 (HY000): Can't create table 'xxx' (errno: 150)
- 卷积神经网络中的参数计算(转载)
- 基于springboot的社区物业管理系统(完美运行,包含数据库源代码,可完美运行)
- QT二次开发Kvaser
- paypal android 教程,android端集成paypal
- 国内外常用的MD5在线解密网站
- java roundup函数_随手记之Linux 2.6.32内核SYN flooding警告信息
- java http data chunk_HTTP协议之chunk编码(分块传输编码)
- 数字公路探索新范式,维谛技术(Vertiv)助力智慧高速“再提速”
- dos系统的界面字体设置
- 透视变换(perspective transformation)
- 深入理解Camera基础知识点