(九)嵌入式 Linux驱动程序设计之平台总线模型
接上篇:(八)嵌入式 Linux驱动程序设计之申请字符类设备号,注册字符类设备,自动创建设备节点
**
1.平台总线模型概述
2.注册platform设备
3.注册platform驱动
4.平台总线probe函数编写
**
1.平台总线模型概述
1.什么是平台总线模型?
平台总线模型也叫 platform总线模型。是 Linux内核虚拟出来的一条总线,不是真实的导线,平台总线模型就是把原来的驱动C文件给分成了俩个C文件,一个是 device. c,一个是driver. c;把稳定不变的放在 driver.c里面,需要变得就放在了 device.c里面。
2.为什么会有平台总线模型?
(1)可以提高代码的重用性
(2)减少重复性代码设备总线驱动device. c driver.c
3.怎么编写以平台总线模型设计的驱动?
一个是 device. c,一个是 driver.c,然后分别注册 device.c和 driver.c。
平台总线是以名字来匹配的,实际上就是字符串比较.
2.注册platform设备
1.平台总线注册
一个 device device. c里面写的是硬件资源,这里的硬件资源是指寄存器的地址,中断号,时钟等硬件;
在 Linux内核里面,我们是用一个结构体来描述硬件资源的。include/linux/platform_device.h
> struct platform_device {
platform总线设备
const char *name; //平台总线进行匹配的时候用到的name,/sys/bus
int id; //设备id,一般写-1
//ID 是用来区分如果设备名字相同的时候(通过在后面添加一个数字来代表不同的设备,因为有时候有这种需求)
bool id_auto;
struct device dev; //内嵌的 device结构体
u32 num_resources; //资源结构体数量
struct resource *resource; // device里面的硬件资源 指向一个资源结构体数组
const struct platform_device_id *id_entry; // 用来进行与设备驱动匹配用的id_table表
/* arch specific additions */
struct pdev_archdata archdata; // 自留地 添加自己的东西
};
在ioport.h中可以找到resource的结构体定义,主要用来描述硬件资源
struct resource {
// 资源结构体
resource_size_t start; // 资源的起始值,如果是地址,那么是物理地址,不是虚拟地址
resource_size_t end; // 资源的结束值,如果是地址,那么是物理地址,不是虚拟地址
const char *name; // 资源名
unsigned long flags; // 资源的标示,用来识别不同的资源
struct resource *parent, *sibling, *child; // 资源指针,可以构成链表
};
在这里还有很多的宏定义来表示地址,常用的有以下几个
IO的内存
#define IORESOURCE_IO 0x00000100 /* PCI/ISA I/O ports */
表述一段物理内存
#define IORESOURCE_MEM 0x00000200
表示中断
#define IORESOURCE_IRQ 0x00000400
dma的地址
#define IORESOURCE_DMA 0x00000800
总线号
#define IORESOURCE_BUS 0x00001000
device.c
//平台总线模型
#include <linux/init.h>
#include <linux/module.h>
#include <linux/platform_device.h>
struct resource led_res[] = {
[0] = {
.start = 0x2090000,
.end = 0x2090003,
.flags = IORESOURCE_MEM,
.name = "GPIO1_DR"
}
//`[1] ={
}... 注意:如果设备树中没有描述电气属性等还需要在这里加,改地址及名字即可`
};
void led_release(struct device *dev)
{
printk("led_release ok!!!\n");
}
struct platform_device led_device = {
// platform总线设备
.name = "led_device_test", // 平台设备的名字
.id = -1, // ID 是用来区分如果设备名字相同的时候(通过在后面添加一个数字来代表不同的设备,因为有时候有这种需求)
.num_resources = ARRAY_SIZE(led_res), // 资源结构体数量
.resource = led_res, // 指向一个资源结构体数组
.dev=
{
.release = led_release
}
};
static int device_init(void)
{
printk("led_device ok!!!\n"); // 在内核中无法使用c语言库,所以不用printf
return platform_device_register(&led_device); // platform_device_register有返回值,所以要判断
}
static void device_exit(void)
{
printk("led_device byb!!!\n");
platform_device_unregister(&led_device);
}
module_init(device_init);
module_exit(device_exit