platform平台总线调用流程和使用详细介绍

        总线的概念:总线是计算机各种功能部件之间传送信息的公共通信干线,它是由 导线 组成的传输线束, 按照计算机所传输的信息种类,计算机的总线可以划分为 数据总线 、 地址总线 和 控制总线 ,分别用来传输数据、数据地址和 控制信号 。

        平台总线的概念:相对于USB、PCI、I2C、SPI等物理总线来说,platform总线是一种虚拟、抽象出来的总线,实际中并不存在这样的总线。那为什么需要platform总线呢?其实是Linux设备驱动模型为了保持设备驱动的统一性而虚拟出来的总线。因为对于usb设备、i2c设备、pci设备、spi设备等等,他们与cpu的通信都是直接挂在相应的总线下面与我们的cpu进行数据交互的,但是在我们的嵌入式系统当中,并不是所有的设备都能够归属于这些常见的总线,在嵌入式系统里面,SoC系统中集成的独立的外设控制器、挂接在SoC内存空间的外设却不依附与此类总线。所以Linux驱动模型为了保持完整性,将这些设备挂在一条虚拟的总线上(platform总线),而不至于使得有些设备挂在总线上,另一些设备没有挂在总线上。

设备:

(1)struct device是硬件设备在内核驱动框架中的抽象

(2)device_register用于向内核驱动框架注册一个设备

(3)通常device不会单独使用,而是被包含在一个具体设备结构体中,如struct usb_device

驱动:

(1)struct device_driver是驱动程序在内核驱动框架中的抽象

(2)关键元素1:name,驱动程序的名字,很重要,经常被用来作为驱动和设备的匹配依据

(3)关键元素2:probe,驱动程序的探测函数,用来检测一个设备是否可以被该驱动所管理

平台总线下管理的2员大将:

(1)platform工作体系都定义在drivers/base/platform.c中

(2)两个结构体:platform_device和platform_driver

(3)两个接口函数:platform_device_register和platform_driver_register

相关代码位置:

platform总线相关代码:driver\base\platform.c 文件中

相关结构体定义:include\linux\platform_device.h 文件中

结构体分析:

platform_device结构体分析:(include\linux\platform_device.h)

	struct platform_device {           //  platform总线设备
      const char    * name;          //  平台设备的名字
      int        id;                 //   ID 是用来区分如果设备名字相同的时候(通过在后面添加一个数字来代表不同的设备,因为有时候有这种需求)
      struct device    dev;          //   内置的device结构体,device通用的一些东西
      u32        num_resources;      //   资源结构体数量
      struct resource    * resource; //   指向一个资源结构体数组
  
      const struct platform_device_id    *id_entry; //  用来进行与设备驱动匹配用的id_table表
  
     /* arch specific additions */
     struct pdev_archdata    archdata;             //  自留地    添加自己的东西
 	};

platform_device结构体中的struct resource结构体分析:

 struct resource {      // 资源结构体
     resource_size_t start;      // 资源的起始值,如果是地址,那么是物理地址,不是虚拟地址
     resource_size_t end;        // 资源的结束值,如果是地址,那么是物理地址,不是虚拟地址
     const char *name;           // 资源名
     unsigned long flags;        // 资源的标示,用来识别不同的资源
     struct resource *parent, *sibling, *child;   // 资源指针,可以构成链表
 };

platform_driver结构体分析:(include\linux\platform_device.h)

 struct platform_driver {
     int (*probe)(struct platform_device *);     //  这个probe函数其实和  device_driver中的是一样的功能,但是一般是使用device_driver中的那个
     int (*remove)(struct platform_device *);    //  卸载平台设备驱动的时候会调用这个函数,但是device_driver下面也有,具体调用的是谁这个就得分析了
     void (*shutdown)(struct platform_device *);	//	关闭一个设备
     int (*suspend)(struct platform_device *, pm_message_t state);	//	挂起一个设备
     int (*resume)(struct platform_device *);			//唤醒一个设备
     struct device_driver driver;                //   内置的device_driver 结构体 ,driver通用的一些东西
     const struct platform_device_id *id_table;  //  该设备驱动支持的设备的列表  他是通过这个指针去指向  platform_device_id 类型的数组
 };

平台总线体系的工作流程

(1)第一步:系统启动时在bus系统中注册platform

(2)第二步:内核移植的人负责提供platform_device

(3)第三步:写驱动的人负责提供platform_driver

(4)第四步:platform的match函数发现driver和device匹配后,调用driver的probe函数来完成驱动的初始化和安装,然后设备就工作起来了

分析源码:

测试实例:

实例1:本例比较简单,只用于测试platform_driver 和platform_device是否可以匹配成功。

实例2:给结构体platform_device 增加硬件信息,并在内核中能够读取出来。

device.c

struct resource	res[]={
	[0] ={
		.start = 0x139d0000,
		.end  = 0x139d0000 + 0x3,
		.flags = IORESOURCE_MEM,
	},

	[1] ={
		.start = 199,
		.end  = 199,
		.flags = IORESOURCE_IRQ,
	},	
};
static struct platform_device hello_device = 
{
	.name = "duang",
	.id = -1,
	.dev.release = hello_release,	
	.num_resources = ARRAY_SIZE(res),
	.resource = res,
};

driver.c

static int hello_probe(struct platform_device *pdev)
{
	printk("match ok \n");

	printk("mem = %x \n",pdev->resource[0].start);
	printk("irq = %d \n",pdev->resource[1].start);

	//注册中断、申请内存
	return 0;
}

执行结果;

由结果可知,probe函数正确读取到了硬件信息。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

开心肖肖乐❀

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值