Linux平台设备框架驱动

  平台设备框架(platform)是将一个驱动分为设备层和驱动层两个部分,通过总线模型将设备和驱动进行绑定。在系统中每注册一个设备,都会与之匹配一个驱动,同样的,每注册一个驱动也会与之匹配一个设备。
   通常 Linux 设备和驱动通常都需要挂接在一种总线上,对于本身依附于 PCI、 USB、 I2 C、 SPI 等的设备而言,这自然不是问题,但是在嵌入式系统里面, SOC 系统中集成的独立的外设控制器、挂接在 SOC 内存空间的外设等却不依附于此类总线。
   基于总线框架的模型结构,Linux下就衍生了平台设备框架模型(platform),平台设备总线是一种虚拟总线,称为platform总线。对应的设备层称为platform_device;驱动层称为platform_driver。设备层和驱动层通过平台设备总线进行匹配管理。

1.平台设备框架特性

  1. 平台模型采用了分层结构,把一个设备驱动程序分成了两个部分:
      平台设备( platform_device)和平台驱动( platform_driver)。
  2. 平台设备将设备本身的资源注册进内核,可以由内核统一管理。
  3. 将硬件资源和驱动接口分离,编译代码的维护与移植。

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 设备层注册示例

  设备层注册步骤:

  1. 填充struct device结构体,填写设备资源信息struct resource * resource;
  2. 调用设备层注册函数platform_device_register();
  3. 注销时调用注销函数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 驱动层注册示例

  驱动层注册步骤:

  1. 填充 struct platform_driver结构体,实现资源匹配函数和资源释放函数;
  2. 调用设备层注册函数platform_driver_register();
  3. 注销时调用注销函数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平台设备框架驱动相关推荐

  1. 支持驱动最好的linux软件,Linux平台设备和驱动

    一 platform总线 一个现实的linux设备驱动通常需要挂接在一种总线上,对于本身依附于PCI,USB,IIC,SPI等的设备而言,这自然不是问题,但是在嵌入式系统里面,SOC系统中集成的独立的 ...

  2. Linux平台设备驱动

    在设备驱动程序中经常会见到和platform相关的字段,分布在驱动程序的多个角落,这也是2.6内核中比较重要的一种机制,把它原理弄懂,对以后分析驱动程序很有帮助:在linux2.6设备模型中,关心总线 ...

  3. linux平台设备驱动模型是什么意思,Linux设备驱动模型之我理解

    点击(此处)折叠或打开 /* my_bus.c   */ #include #include #include #include #include #include "my_bus.h&qu ...

  4. Linux 块设备 EMMC 驱动介绍

    目录: 高质量文章导航-持续更新中 前置:硬件接口 EMMC(Embedded Multi-Media Card)是一种用于存储和传输数据的嵌入式存储器(芯片),通常用于移动设备和嵌入式设备中.Lin ...

  5. linux字符设备led驱动源码,字符设备驱动控制LED灯

    开发板:龙芯1B PC:Ubuntu 13.10 本程序为字符设备驱动,提供控制led灯功能,如要实现控制需要自己写应用程序,打开驱动文件就可控制led灯,led灯通过gpio控制 #include ...

  6. Linux内核平台设备驱动模型platform_device和platform_driver框架

    关于Linux平台设备驱动模型,并不是创建新的设备分类,是在原有的字符设备基础上使用,将设备和驱动分开,生成两个.ko文件.         Linux内核维护一个全局设备链表,对应的总线会将驱动和设 ...

  7. platform框架--Linux MISC杂项框架--Linux INPUT子系统框架--串行集成电路总线I2C设备驱动框架--串行外设接口SPI 设备驱动框架---通用异步收发器UART驱动框架

    platform框架 input. pinctrl. gpio 子系统都是 Linux 内核针对某一类设备而创建的框架, input子系统是管理输入的子系统 pinctrl 子系统重点是设置 PIN( ...

  8. Linux内核总线系统 —— 通用总线和平台设备

    在 Linux内核输入子系统框架_Bin Watson的博客-CSDN博客 这篇文章中,我们详细分析了输入子系统.了解到了 dev 和 handler 分层的思想.而在 jz2440_输入子系统驱动程 ...

  9. 宋宝华:Linux设备与驱动的手动解绑与手动绑定

    众所周知,Linux靠设备与驱动之间的match,来完成设备与驱动的bind,从而触发驱动的probe()成员函数被执行.每个bus都有相应的match方法,完成match的总的入口函数是: stat ...

最新文章

  1. ASP.net MVC基础
  2. element中el-image怎样显示图片
  3. Spring集成Mybatis plus
  4. swift:Optional Type 、Swift和Objective-C混编的讲解
  5. WinAPI【消息及相关结构体】
  6. linux下mongodb 安装,linux下mongodb安装
  7. 取代上万行遗留代码,机器学习模型终“上位”
  8. php memcache 扩展 libmemcached 安装
  9. Mysql 的ERROR 1005 (HY000): Can't create table 'xxx' (errno: 150)
  10. 卷积神经网络中的参数计算(转载)
  11. 基于springboot的社区物业管理系统(完美运行,包含数据库源代码,可完美运行)
  12. QT二次开发Kvaser
  13. paypal android 教程,android端集成paypal
  14. 国内外常用的MD5在线解密网站
  15. java roundup函数_随手记之Linux 2.6.32内核SYN flooding警告信息
  16. java http data chunk_HTTP协议之chunk编码(分块传输编码)
  17. 数字公路探索新范式,维谛技术(Vertiv)助力智慧高速“再提速”
  18. dos系统的界面字体设置
  19. 透视变换(perspective transformation)
  20. 深入理解Camera基础知识点

热门文章

  1. 【Python55--爬虫:代理】
  2. SpringCloud 微服务工作笔记:validationQuery: SELECT 1 FROM DUAL
  3. 信息系统项目管理师-九大知识领域必备知识点整理
  4. go:linkname must refer to declared function or variable
  5. Java高级---集合
  6. 力扣 347. 前 K 个高频元素
  7. 奖金575万!81岁拓扑数学家摘得数学界诺奖「阿贝尔奖」
  8. 【220】【3】滑动窗口(双指针)的应用,另有序的容器应用
  9. PHP获取微信用户手机号
  10. 《离散数学及应用》第七版奇数题课后习题