linux platform驱动模型详解
- 格式:pdf
- 大小:170.94 KB
- 文档页数:7
platform模型驱动和字符设备模型驱动字符设备驱动模型:1、申请设备号:动态申请(alloc_chrdev_region()),动态申请(register_chrdev_region())struct cdev btn_cdev;//申请设备号if(major){//静态申请设备号dev_id = MKDEV(major, 0);register_chrdev_region(dev_id, 1, "button");}else{//动态申请设备号alloc_chardev_region(&dev_id, 0, 1, "button");major = MAJOR(dev_id);}在Linux中以主设备号用来标识与设备文件相连的驱动程序。
次编号被驱动程序用来辨别操作的是哪个设备。
cdev 结构体的 dev_t 成员定义了设备号,为 32 位,其中高 12 位为主设备号,低20 位为次设备号。
设备号的获得与生成:获得:主设备号:MAJOR(dev_t dev);次设备号:MINOR(dev_t dev);生成:MKDEV(int major,int minor);2、初始化设备:void cdev_init(struct cdev *, struct file_operations *);cdev_init()函数用于初始化cdev 的成员,并建立cdev 和file_operations 之间的连接。
3、注册设备int cdev_add(struct cdev *, dev_t, unsigned);cdev_add()函数向系统添加一个 cdev,完成字符设备的注册。
4、创建设备节点手动创建设备节点:mknod 的标准形式为:mknod DEVNAME {b | c} MAJOR MINOR1,DEVNAME是要创建的设备文件名,如果想将设备文件放在一个特定的文件夹下,就需要先用mkdir在dev目录下新建一个目录;2, b和c 分别表示块设备和字符设备:b表示系统从块设备中读取数据的时候,直接从内存的buffer中读取数据,而不经过磁盘;c表示字符设备文件与设备传送数据的时候是以字符的形式传送,一次传送一个字符,比如打印机、终端都是以字符的形式传送数据;3,MAJOR和MINOR分别表示主设备号和次设备号:为了管理设备,系统为每个设备分配一个编号,一个设备号由主设备号和次设备号组成。
Linux驱动之platform总线详解⽬录1、platform 总线简介1.1、Linux 驱动的分离和分层思想1.1.1、Linux 驱动的分离1.2、platform 平台驱动模型2、platform 框架2.1、platform 总线2.2、platform 驱动2.2.1、platform 驱动定义2.2.2、platform 驱动注册2.3、platform 设备2.3.1、platform 设备定义2.4、platform 匹配过程3、总结1、platform 总线简介1.1、Linux 驱动的分离和分层思想1.1.1、Linux 驱动的分离先讲 Linux 驱动的分离,Linux 操作系统⽀持在各类 CPU 上运⾏,因为每⼀种 CPU 对设备的驱动不⼀样,这样就造成了Linux 内核中积累了⼤量代码,并且这些代码关于同⼀设备的描述⼤致相同,这就使得内核代码很冗余。
以 CPU 通过 I2C 控制 MPU6050 为例:从图可以看出每⼀种平台下都有⼀套主机驱动和⼀套设备驱动,因为每个平台的 I2C 控制器不同,所以这个主机驱动得每个平台配⼀个⾃⼰的,但⼤家所⽤的 MPU6050 是⼀样的,所以完全可以就共⽤⼀套设备驱动代码。
完善后框架如下:当然,这只是对于 I2C 下的 MPU6050 这个设备,实际情况下,I2C 下肯定会挂载很多设备,根据这个思路,我们可以得到框架为:⽽在实际开发中,I2C 主机驱动半导体⼚家会编写好,设备驱动也由设备⼚家编写好,我们只需要提供设备信息即可,如设备接到那个 I2C 接⼝上,I2C 速度为多少。
这样就相当于把设备信息从设备驱动中剥离出来,⽽设备驱动也会⽤标准⽅法去获取设备信息(如从设备树中获取设备信息)。
这样就相当于驱动只负责驱动,设备(信息)只负责设备,想办法将两者进⾏匹配即可,来做这个匹配⼯作的就是总线,这就构成了 Linux 中的总线-驱动-设备模型。
platform设备驱动全透析1.1 platform总线、设备与驱动在Linux 2.6的设备驱动模型中,关心总线、设备和驱动这3个实体,总线将设备和驱动绑定。
在系统每注册一个设备的时候,会寻找与之匹配的驱动;相反的,在系统每注册一个驱动的时候,会寻找与之匹配的设备,而匹配由总线完成。
一个现实的Linux设备和驱动通常都需要挂接在一种总线上,对于本身依附于PCI、USB、I2 C、SPI等的设备而言,这自然不是问题,但是在嵌入式系统里面,SoC系统中集成的独立的外设控制器、挂接在SoC内存空间的外设等确不依附于此类总线。
基于这一背景,Linux 发明了一种虚拟的总线,称为platform总线,相应的设备称为platform_device,而驱动成为platform_driver。
注意,所谓的platform_device并不是与字符设备、块设备和网络设备并列的概念,而是Linux 系统提供的一种附加手段,例如,在S3C6410处理器中,把内部集成的I2 C、RTC、SPI、LCD、看门狗等控制器都归纳为platform_device,而它们本身就是字符设备。
platform_device 结构体的定义如代码清单1所示。
代码清单1 platform_device结构体1 struct platform_device {2 const char * name;/* 设备名*/3 u32 id;4 struct device dev;5 u32 num_resources;/* 设备所使用各类资源数量*/6 struct resource * resource;/* 资源*/7 };platform_driver这个结构体中包含probe()、remove()、shutdown()、suspend()、resume()函数,通常也需要由驱动实现,如代码清单2。
代码清单2 platform_driver结构体1 struct platform_driver {2 int (*probe)(struct platform_device *);3 int (*remove)(struct platform_device *);4 void (*shutdown)(struct platform_device *);5 int (*suspend)(struct platform_device *, pm_message_t state);6 int (*suspend_late)(struct platform_device *, pm_message_t state);7 int (*resume_early)(struct platform_device *);8 int (*resume)(struct platform_device *);9 struct pm_ext_ops *pm;10 struct device_driver driver;11};系统中为platform总线定义了一个bus_type的实例platform_bus_type,其定义如代码清单15.3。
Linux在2.6版本引入了设备驱动模型,设备驱动模型负责统一实现和维护一些特性,诸如:热插拔、对象生命周期、用户空间和驱动空间的交互等基础设施1.设备驱动模型基本概念设备驱动模型主要包含:类(class)、总线(bus)、设备(device)、驱动(driver),它们的本质都是内核中的几种数据结构的“实例”∙类的本质是class结构体类型,各种不同的类其实就是class的各种实例∙总线的本质是bus_type结构体类型,各种不同的总线其实就是bus_type的各种实例∙设备的本质是device结构体类型,各种不同的设备其实就是device的各种实例∙驱动的本质是device_driver结构体类型,各种不同的驱动其实就是device_driver的各种实例2.sysfs基本概念sysfs其实就是/sys目录,其主要作用就是:展示设备驱动模型中各组件的层次关系,并将各组件的本体——内核中的数据结构以文件形式呈现,方便用户层查看及操作3./sys目录结构与设备驱动模型∙/sys目录结构很好的展示了驱动设备模型,如图:∙注意:同一个设备可能在/sys中存在多个设备文件,比如一颗led的设备文件可能在/sys/bus/platform/devices/led1,同时还有一个在/sys/class/leds/led1。
虽然他们都是同一颗led的设备文件,但是他们的来源、机制、原理都是不同的,不能混为一谈4.各组件的特性与联系∙kobject:设备驱动模型各实例的最基本单元,提供一些公用型服务如:提供该实例在sysfs中的操作方法(show和store);提供在sysfs中以文件形式存在的属性,其实就是应用接口;提供各个实例的层次架构,让sysfs中弄出目录结构。
设备驱动模型中每个实例内部都会包含一个kobject∙总线、设备、驱动,这三者有着密切的联系。
在内核中,设备和驱动是分开注册的,注册设备的时候,并不需要驱动已经存在,而驱动被注册的时候,也不需要对应的设备已经被注册。
Linux设备驱动模型之platform总线深入浅出在Linux2.6以后的设备驱动模型中,需关心总线,设备和驱动这三种实体,总线将设备和驱动绑定。
在系统每注册一个设备的时候,会寻找与之匹配的驱动;相反,在系统每注册一个驱动的时候,会寻找与之匹配的设备,而匹配由总线完成。
对于依附在USB、PCI、I2C、SPI等物理总线来这些都不是问题。
但是在嵌入式系统里面,在Soc系统中集成的独立外设控制器,挂接在Soc内存空间的外设等却不依附在此类总线。
基于这一背景,Linux发明了一种总线,称为platform。
相对于USB、PCI、I2C、SPI等物理总线来说,platform总线是一种虚拟、抽象出来的总线,实际中并不存在这样的总线。
platform总线相关代码:driver\base\platform.c 文件相关结构体定义:include\linux\platform_device.h 文件中platform总线管理下最重要的两个结构体是platform_device和platform_driver 分别表示设备和驱动在Linux中的定义如下一:platform_driver//include\linux\platform_device.h 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 (*suspend_late)(struct platform_device *, pm_message_t state); int (*resume_early)(struct platform_device *); int (*resume)(struct platform_device *);//恢复函数,在开机时被调用struct device_driver driver;//设备驱动结构};12345678。
详解Linux2.6内核中基于platform机制的驱动模型【摘要】本文以Linux 2.6.25 内核为例,分析了基于platform总线的驱动模型。
首先介绍了Platform总线的基本概念,接着介绍了platform device和platform driver的定义和加载过程,分析了其与基类device 和driver的派生关系及在此过程中面向对象的设计思想。
最后以ARM S3C2440中I2C控制器为例介绍了基于platform总线的驱动开发流程。
【关键字】platform_bus, platform_device, resource , platform_driver, file_operations目录1 何谓platform bus? 22 device和platform_device 33 device_register和platform_device_register 54 device_driver和platform driver 85 driver_register 和platform_driver_register 106 bus、device及driver三者之间的关系177 哪些适用于plarform驱动?188 基于platform总线的驱动开发流程188.1 初始化platform_bus 198.2 定义platform_device 228.3 注册platform_device 228.4 定义platform_driver 288.5 注册platform_driver 298.6 操作设备321 何谓platform bus?Linux系统中许多部分对设备是如何链接的并不感兴趣,但是他们需要知道哪些类型的设备是可以使用的。
设备模型提供了一种机制来对设备进行分类,在更高的功能层面上描述这些设备,并使得这些设备对用户空间可见。
因此从2.6内核开始引入了设备模型。
深⼊解析LinuxPlatform_device及驱动[导读] 前⽂分析了Linux设备驱动的驱动模型,本⽂来聊聊Platform_driver/Platform_device这个类。
做嵌⼊式Linux的驱动,这个也是绕不开的,所以来学习分析总结⼀下。
上⽂阅读:注:代码分析基于linux-5.4.31为什么有Platform_driver前⽂谈到的总线驱动模型(注这个图是照着bootlin的⽂档绘制的):同时,根据代码分析其基础数据结构框架关系如下(UML关系并不严谨,仅为理解⽅便):可见驱动程序的模型分层有⼀层总线基础层,那么对于嵌⼊式开发领域⽽⾔,有很多SOC芯⽚内置了各种外设,并⽐如LCD,UART、audio、摄像头⼝等等,并没有总线。
为了统⼀驱动架构抽象,所以引⼊了platform bus这个虚拟的总线模型。
做过嵌⼊式开发的⼈应该都有体会,这类设备在嵌⼊式系统中⾮常多,所以在研究具体某类设备的驱动开发之前,有必要研究platform 设备的驱动模型。
在强调⼀下这个是统⼀在总线驱动模型这个体系内的。
驱动模型的实现定义在./include/linux/platform_device.h中,来梳理⼀下这些数据结构间的关系:platform_device ⽤于抽象平台设备platform_driver ⽤于抽象匹配平台设备对应的驱动程序通过继承演化关系分析,platform_device/platform_driver 仍然统⼀于总线驱动模型,只是虚拟出来了⼀条platform bus这样⼀条虚拟总线。
platform_bus在哪⾥实现的呢?该模块的实现位于./driver/base/platform.c中struct device platform_bus = {.init_name = "platform",};platform.c导出了⼀系列内核全局操作接⼝集:EXPORT_SYMBOL_GPL(platform_bus);EXPORT_SYMBOL_GPL(__platform_driver_register);EXPORT_SYMBOL_GPL(__platform_driver_probe);EXPORT_SYMBOL_GPL(platform_get_resource_byname);EXPORT_SYMBOL_GPL(platform_get_irq_byname);....那么既然这条总线并不存在,往往并不能实现设备枚举、热插拔等功能。
linux platform 驱动模型分析一。
概述platform设备和驱动与linux设备模型密切相关。
platform在linux设备模型中,其实就是一种虚拟总线没有对应的硬件结构。
它的主要作用就是管理系统的外设资源,比如io内存,中断信号线。
现在大多数处理器芯片都是soc,如s3c2440,它包括处理器内核(arm920t)和系统的外设(lcd接口,nandflash接口等)。
linux在引入了platform机制之后,内核假设所有的这些外设都挂载在platform虚拟总线上,以便进行统一管理。
二。
platform 总线1. 在系统中platform对应的文件drivers/base/platform.c,它不是作为一个模块注册到内核的,关键的注册总线的函数由系统初始化部分,对应/init/main.c中的do_basic_setup函数间接调用。
这里可以看出platform非常重要,要在系统其他驱动加载之前注册。
下面分析platform总线注册函数[cpp] view plaincopyprint?int __init platform_bus_init(void){int error;early_platform_cleanup();error = device_register(&platform_bus);//总线也是设备,所以也要进行设备的注册if (error)return error;error = bus_register(&platform_bus_type);//注册platform_bus_type总线到内核if (error)device_unregister(&platform_bus);return error;}int __init platform_bus_init(void){ int error; early_platform_cleanup();error = device_register(&platform_bus);//总线也是设备,所以也要进行设备的注册if (error)return error;error = bus_register(&platform_bus_type);//注册platform_bus_type总线到内核if (error)device_unregister(&platform_bus);return error; } 这个函数向内核注册了一种总线。