Erlo

linux平台总线模型

2025-01-16 01:29:01 发布   24 浏览  
页面报错/反馈
收藏 点赞

什么是平台总线模型: 是linux系统虚拟出来的总线, 没有对应的硬件接口

平台总线模型将一个驱动分成了两个部分
device.c: 描述硬件资源代码, 描述寄存器的地址, 中断号
driver.c: 控制硬件的驱动代码, 操作寄存器, 处理中断
这两个部分通过相同的name进行匹配

为什么要使用平台总线, 平台总线的优点
不同的处理器的相同功能的寄存器不在一个位置, 但是使用驱动可以是同一套

  1. 减少编写的重复代码, 提高效率
  2. 提高代码的利用率

注册平台设备

device.c描述的硬件资源是
硬件的寄存器的地址, 中断号, 和其他硬件资源
使用下面的结构体描述

struct platform_device {
    // 名字, 和driver匹配, 可以在sys目录下看到
	const char	*name;
	// 区分不同的设备, sys目录下的设备文件的后缀(-1无后缀)
	int		id;
	bool		id_auto; // 自动设置id, 一般不用
    // 设备的通用属性部分, 必须实现里面的release函数
	struct device	dev;
	u64		platform_dma_mask;
	struct device_dma_parameters dma_parms;

    // 存储资源的个数
	u32		num_resources;
	// 存放硬件资源的结构体
	struct resource	*resource;

	const struct platform_device_id	*id_entry;
	const char *driver_override;

	/* MFD cell pointer */
	struct mfd_cell *mfd_cell;

	/* arch specific additions */
	struct pdev_archdata	archdata;
};

描述硬件资源的结构体

// linux-master/include/linux/ioport.h
struct resource {
	resource_size_t start;
	resource_size_t end;
	const char *name;
	unsigned long flags;
	unsigned long desc;
	struct resource *parent, *sibling, *child;
};
  • start/end: 资源的起始信息和终止信息, 比如寄存器的起始地址和终止地址
  • flags: 硬件资源信息的类型, 在include/linux/ioport.h路径下列举

硬件资源举例

static struct resource my_device_resources[] = {
    [0] = {
        .start = 0xFDD60000,
        .end = 0xFDD60004,
        .flags = IORESOURCE_MEM, // 内存类型或寄存器
    },
    [1] = {
        .start = 13,
        .end = 13,
        .flags= IORESOURCE_IRQ, // 中断类型
    },
};

platform设备加卸载函数: 把设备加载到总线上

int platform_device_register(struct platform_device *pdev)
void platform_device_unregister(struct platform_device *pdev)

注册平台驱动

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;
	const struct platform_device_id *id_table;
	bool prevent_deferred_probe;
	bool driver_managed_dma;
};
  • probe: 必须实现, 当设备和驱动匹配成功之后, 自动执行
  • remove: 移出一个设备的时候执行
  • shutdown: 电源管理, 关掉设备时执行
  • suspend: 电源管理, 挂起时执行
  • resume: 电源管理, 恢复时执行
  • driver: 设备共用的一些属性
  • id_table: 设备的ID表

platform驱动加卸载函数

const struct platform_device_id mydriver_id_table = {
    .name = "mydevice",
};

struct platform driver platform driver test ={
    .probe = mydriver_probe,
    .remove =mydriver_remove,
    .driver = {
        .name ="mydevice",
        .owner = THIS_MODULE,
    }
    // id_table的优先级大于drive中的name
    .id_table = &mydriver_id_table,
}

int platform_driver_register(struct platform_driver *drv, struct module *owner)
void platform_driver_unregister(struct platform_driver *drv);

设备和驱动的匹配方法

平台设备和驱动的匹配方法

  1. 先通过platform_driver中的id_table
  2. 如果id_table不存在,则只是简单的比较设备中的name字段和驱动中的name字段是否相同
static int platform_match(struct device *dev, struct device_driver *drv)
{
    ...
	/* Then try to match against the id table */
	if (pdrv->id_table)
		return platform_match_id(pdrv->id_table, pdev) != NULL;
	/* fall-back to driver name match */
	return (strcmp(pdev->name, drv->name) == 0);
}

获取设备资源

获取设备资源的函数
platform_get_resource: 返回设备指定类型的第num个资源

struct resource *platform_get_resource(struct platform_device *dev,
				       unsigned int type, unsigned int num)
{
	u32 i;

	for (i = 0; i num_resources; i++) {
		struct resource *r = &dev->resource[i];

		if (type == resource_type(r) && num-- == 0)
			return r;
	}
	return NULL;
}

用户程序通过平台总线访问设备寄存器的例子

登录查看全部

参与评论

评论留言

还没有评论留言,赶紧来抢楼吧~~

手机查看

返回顶部

给这篇文章打个标签吧~

棒极了 糟糕透顶 好文章 PHP JAVA JS 小程序 Python SEO MySql 确认