#导入Word文档图片# Linux平台设备驱动模型

Posted DS小龙哥

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了#导入Word文档图片# Linux平台设备驱动模型相关的知识,希望对你有一定的参考价值。

16.1 平台设备和驱动初识

16.1.1 总线驱动模型简介

在Linux 2.6的设备驱动模型中,关心总线设备驱动这3个实体,总线将设备和驱动绑定。在系统每注册一个设备的时候,会寻找与之匹配的驱动;相反的,在系统每注册一个驱动的时候,会寻找与之匹配的设备,而匹配由总线完成。

一个现实的Linux设备和驱动通常都需要挂接在一种总线上,对于本身依附于PCI、USB、I2 C、SPI等的设备而言,这自然不是问题,但是在嵌入式系统里面,SOC系统中集成的独立的外设控制器、挂接在SOC内存空间的外设等却不依附于此类总线。

基于这一背景,Linux发明了一种虚拟的总线,称为platform总线,相应的设备称为platform_device,而驱动成为platform_driver

16.1.2 平台总线驱动模型特点

  1. 平台模型采用了分层结构,把一个设备驱动程序分成了两个部分:

平台设备(platform_device)平台驱动(platform_driver)

(2)平台设备将设备本身的资源注册进内核,可以由内核统一管理。

(3)统一了设备驱动模型,使智能电源管理更容易实现(设计设计之初就是为了管理电源的)

(4)从代码的维护角度看,平台模型的可移植性,通用性更好。


16.2 平台设备驱动模型分

下面分别来介绍设备和驱动层的结构及内核提供编写的API函数。

16.2.1 平台设备层核心数据结构

在Linux 2.6内核中将每个设备的资源用结构struct platform_device来描述,该结构体定义在kernel\\include\\linux\\platform_device.h中,struct platform_device结构如下:

struct platform_device

const char * name; //设备名,要求和驱动层中的.name相同。

int id; //设备ID,一般为-1

struct devicedev;//内嵌标准device,一般可以用来传递平台数据

u32 num_resources; //设备占用资源个数

struct resource* resource;//设备占用资源的首地址。

struct platform_device_id*id_entry; //设备id入口,一般驱动不用

/* arch specific additions */

struct pdev_archdataarchdata;

;


该结构一个重要的元素是resource该元素存入了最为重要的设备资源信息,定义在kernel\\include\\linux\\ioport.h中,结构如下:

struct resource

resource_size_t start;//资源起始物理地址

resource_size_t end; //资源结束物理地址

const char *name; //资源名称,可以随便写,一般要有意义。

unsigned long flags;//资源类型,IO,内存,中断,DMA。

struct resource *parent, *sibling, *child;

;


struct resource 结构中flags成员是指资源的类型,目前可用资源类型定义在include\\linux\\ioport.h文件 中。如下:

#define IORESOURCE_IO0x00000100 空间一般在X86框架中存在,ARM一般没有

#define IORESOURCE_MEM0x00000200 内存空间,占用的是CPU 4G统一编址空间

#define IORESOURCE_IRQ0x00000400 中断资源,实际上就是中断号

#define IORESOURCE_DMA0x00000800 内存空间,占用的是CPU 4G统一编址空间,

但是这个空间是用来做dma模型使用的缓冲空间


另外一个很重要的成员是struct device,这个成员是用来实现设备模型的,其中的void 成员用途很大,一般称为平台数据指针,可以给平台驱动层传递任何信息需要的信息,因这个成员指针类型void类型的,在平台设备驱动模型中,随处可以看到这个成员的踪迹,在例子中会看到如何使用。

以下struct device的结构信息:

struct device

struct device*parent; /* 父设备指针 */

struct device_private*p;

struct kobject kobj;

const char*init_name; /*逻辑设备的名字*/

struct device_type*type; /* 设备类型 */

struct semaphoresem;/* semaphore to synchronize calls toits driver. */

struct bus_type*bus; /* 设备所属的总线类型 */

struct device_driver *driver;/* 指向开辟struct device结构driver指针*/

void*platform_data;/* 平台设备的私有数据指针,以传递任何结构*/

struct dev_pm_infopower;


#ifdef CONFIG_NUMA

intnuma_node;/* NUMA node this device is close to */

#endif

u64*dma_mask;/* dma mask (if dmaable device) */

/*Like dma_mask, but foralloc_coherent mappings as

not all hardware supports 64 bit addresses for consistent

allocations such descriptors. */

u64coherent_dma_mask;


struct device_dma_parameters *dma_parms;

/* dma pools (if dmable) */

struct list_headdma_pools;

/* internal for coherent mem override */

struct dma_coherent_mem*dma_mem; /* arch specific additions */

struct dev_archdataarchdata;

dev_tdevt;/* 存放设备号dev_t,creates the sysfs"dev" */

spinlock_tdevres_lock;

struct list_headdevres_head;

struct klist_nodeknode_class;

struct class*class; /* 设备所属*/

const struct attribute_group **groups;/* optional groups */

void(*release)(struct device *dev);

;



上结构中驱动开发者比较重要的成员已经使用粗体标注出来。


16.2.2 platform设备层API

学习平台驱动设备层代码如何编写前,先介绍一下和设备层代码相关的内核API函数。

  1. int platform_device_register(struct platform_device *pdev)

函数原型

int platform_device_register(struct platform_device *pdev)

函数功能

向内核注册一平台设备

函数参数

pdev: 要注册的struct platform_device结构指针

函数返回值

0:注册成功;

负数:注册失败

函数头文件

include\\linux\\platform_device.h

函数定义文件

drivers\\base\\platform.c

(用EXPORT_SYMBOL_GPL(platform_device_register);导出给其他模块使用)

  1. void platform_device_unregister(struct platform_device *pdev)

函数原型

void platform_device_unregister(struct platform_device *pdev)

函数功能

把指定的平台设备struct platform_device从内核中删除

函数参数

pdev: 要删除的struct platform_device结构指针

函数返回值

函数头文件

include\\linux\\platform_device.h

函数定义文件

drivers\\base\\platform.c

(用EXPORT_SYMBOL_GPL(platform_device_unregister);导出给其他模块使用)

在设备层编程中,这两个函数所做的工作是相反的,一个用于添加设备到内核,另一个用于从内核中把设备删除。

  1. int platform_add_devices(struct platform_device **devs, int num)

函数原型

int platform_add_devices(struct platform_device **devs, int num)

函数功能

devs数组中的num平台设备struct platform_device结构注册到内核中。

函数参数

pdev: struct platform_device结构指针数组

num:pdev数组元素中的个数。

函数返回值

0:注册成功;

负数:注册失败

函数头文件

include\\linux\\platform_device.h

函数定义文件

drivers\\base\\platform.c

(用EXPORT_SYMBOL_GPL(platform_add_devices);导出给其他模块使用)

这个函数内部调用的还是platform_device_register(struct platform_device *pdev)同在于platform_device_register(struct platform_device *pdev)只注册单个平台设备,platform_add_devices(struct platform_device **devs, int num)注册多个平台设备结构。


16.2.3 platform 设备层编程​

需要实现的结构体是:struct platform_device。

1)初始化 struct resource 结构变量。

2)初始化 struct platform_device 结构变量。

3)向系统注册设备,使用platform_device_register()函数。


16.2.4 平台驱动层核心数据结构​

在内核中平台驱动模型的驱动层使用struct 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 (*resume)(struct platform_device *); //唤醒函数

struct device_driver driver;//里边的name很重要,用来匹配

struct platform_device_id *id_table;

;


这个结构中probe,remove是必须的要实现的函数成员,其他函数成员根据需要自行决定是否要实现。

struct device_driver driver成员中的name成员很重要,它的内容必须要和设备层核心结构struct platform_device的name成员相同,才能实现驱动层和设备层的绑定

struct device_driver结构如下:

struct device_driver

const char*name; 驱动层的名字,用来和设备层匹配的*/

struct bus_type*bus;

struct module#导入Word文档图片# Linux下I2C驱动架构全面分析

#导入Word文档图片# Linux下音频编程

#导入Word文档图片# 阻塞与非阻塞IO操作

csdn的blog可以直接导入内含图片的word文档吗?

#导入Word文档图片# VM虚拟机网络设置

#导入Word文档图片# Linux下信号处理

(c)2006-2024 SYSTEM All Rights Reserved IT常识