在 Linux 的设备驱动模型中,关心总线、设备和驱动这 3 个实体,总线将设备和驱动绑定。在系统每注册一个设备的时候,会寻找与之匹配的驱动;相反的,在系统每注册一个驱动的时候,会寻找与之匹配的设备,而匹配由总线完成。
平台设备匹配的依据是:
1)根据平台设备结构和平台驱动结构中的name成员进行匹配。-- 一个设备对应一个驱动
2)根据平台设备结构中的name和平台驱动中的id_table 成员中的列表进行匹配 --一个驱动对应多个设备
匹配过程:
以name匹配过程:
1)先安装驱动,再安装设备
安装驱动,把驱动结构存放在内核驱动链表上,当安装一个设备时,内核触发一个动作,把设备结构中的name取出来和驱动链表上的每一个结构中的name进行字符串比较,如果相同,则调用驱动中的探测函数
2)先安装设备,再安装驱动
安装设备,把设备结构存放在内核设备链表上,当安装一个驱动时,内核触发一个动作,把驱动结构中的name取出来和设备链表上的每一个结构中的name进行字符串比较,如果相同,则调用驱动中的探测函数 。
当探测函数调用时,传递一个实际参数,这个参数就是和它匹配的平台设备结构的地址。这样就实现两个层关联。
platform 设备层编程:
需要实现的结构体是: struct platform_device 。
1)初始化 struct resource 结构变量
2)初始化 struct platform_device 结构变量
3)向系统注册设备:使用 platform_device_register()函数。
kernel\include\linux\platform_device.h 中, struct platform_device 结构如下:
struct platform_device {
const char * name; //设备名,要求和驱动中的.name 相同。
int id; //设备 ID,一般为-1
struct device dev; //内嵌标准 device,一般可以用来传递平台数据
u32 num_resources; //设备占用资源个数
struct resource * resource; //设备占用资源的首地址。
struct platform_device_id *id_entry;//设备 id 入口,一般驱动不用
/* arch specific additions */
struct pdev_archdata archdata;
};
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_IO 0x00000100 // IO 空间。一般 在 X86 框架中存在, ARM 一般没有
#define IORESOURCE_MEM 0x00000200 // 内存空间,占用的是 CPU 4G 统一编址空间
#define IORESOURCE_IRQ 0x00000400 // 中断资源,实际上就是中断号
#define IORESOURCE_DMA 0x00000800 // 内存空间,占用的是 CPU 4G 统一编址空间,但是这个空
间是用来做 dma 模型使用的缓冲空间。
另外一个很重要的成员是 struct device,这个成员是用来实现设备模型的,其中的 void
*platform_data 成员用途很大, 一般称为平台数据指针, 可以给平台驱动层传递任何信息需要的信息,因这
个成员指针类型是 void 类型的,在平台设备驱动模型中,随处可以看到这个成员的踪迹,在例子中会看到
如何使用。 以下 struct