0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

Linux平台设备框架驱动

嵌入式技术 来源:嵌入式技术 作者:嵌入式技术 2022-09-25 08:59 次阅读

Linux平台设备框架驱动

  平台设备框架(platform)是将一个驱动分为设备层和驱动层两个部分,通过总线模型将设备和驱动进行绑定。在系统中每注册一个设备,都会与之匹配一个驱动,同样的,每注册一个驱动也会与之匹配一个设备。
通常 Linux 设备和驱动通常都需要挂接在一种总线上,对于本身依附于 PCI、 USB、 I2 C、 SPI 等的设备而言,这自然不是问题,但是在嵌入式系统里面, SOC 系统中集成的独立的外设控制器、挂接在 SOC 内存空间的外设等却不依附于此类总线。
基于总线框架的模型结构,Linux下就衍生了平台设备框架模型(platform),平台设备总线是一种虚拟总线,称为platform总线。对应的设备层称为platform_device;驱动层称为platform_driver。设备层和驱动层通过平台设备总线进行匹配管理。

1.平台设备框架特性

平台模型采用了分层结构,把一个设备驱动程序分成了两个部分:
平台设备( platform_device)和平台驱动( platform_driver)。
平台设备将设备本身的资源注册进内核,可以由内核统一管理。
硬件资源和驱动接口分离,编译代码的维护与移植。

poYBAGMto8uAVBODAAFDIhZx3Kk481.png#pic_center

2.平台设备总线相关接口函数

2.1 设备层接口函数

  每个设备的系统通过设备结构体struct platform_device保存。结构体原型在 include/linux/platform_devcie.h 中定义。

struct platform_device {
	const char	* name; //设备名字,驱动层和设备层匹配标志
	int		id;//通常填-1
	struct device	dev;//设备结构体信息
	u32		num_resources;//资源个数
	struct resource	* resource;//资源内容
	const struct platform_device_id	*id_entry;
	/* MFD cell pointer */
	struct mfd_cell *mfd_cell;
	/* arch specific additions */
	struct pdev_archdata	archdata;
};
  • struct device dev结构信息

struct device dev 结构体是用来实现设备模型的。这个结构体中成员比较多,结构体原型在 include/linux/devcie.h 中定义。我们常关心的是其中的两个成员:
平台数据指针: void *platform_data;
资源释放函数: void (*release)(struct device *dev);
平台数据指针platform_data是一个void *类型指针,可以向驱动层传递任意数据,release资源释放函数接口在设备层一定要自己实现,否则在设备层释放资源时会报错。
以下列举其中几个成员结构:

struct device {
	const char *init_name; /*逻辑设备的名字*/
	struct device_type *type; /* 设备类型 */
	struct bus_type *bus; /* 设备所属的总线类型 */
	struct device_driver *driver;/* 指向开辟 struct device 结构 driver 指针*/
	void		*platform_data;	/* 平台设备指针 */
	dev_t devt;  /* 存放设备号 dev_t,creates the sysfs"dev" */
	struct class *class;  /* 设备所属类*/
	void	(*release)(struct device *dev);/*设备资源释放函数*/
};
  • struct resource * resource结构信息

      struct resource * resource 结构体是用来保存设备资源内容信息。该结构体定义位置: include/linux/ioport.h
struct resource {
	resource_size_t start; //资源起始地址
	resource_size_t end; //资源结构地址
	const char *name;//资源名字
	unsigned long flags;//资源类型
	struct resource *parent, *sibling, *child;
};
  • 设备层注册函数
int platform_device_register(struct platform_device *pdev)
函数功能: 注册平台设备;
形参: pdev --设备结构体;
返回值: 成功返回0,失败返回其它值;
  • 设备层注销函数
void platform_device_unregister(struct platform_device *pdev)
函数功能: 注册平台设备;
形参: pdev --设备结构体;
  • 向内核添加多个设备
int platform_add_devices(struct platform_device **devs, int num)
函数功能: 向内核注册多个设备;
形参: pdev --设备结构体;
   num – 注册的设备个数
返回值: 成功返回0,失败返回其它值;

2.2 驱动层接口函数

驱动层通过struct platform_driver 结构体保存相关信息,结构体定义位置: include/linux/devcie.h
在该结构体中必须要实现接口函数:

资源匹配函数:int (*probe)(struct platform_device *)
资源释放函数:int (*remove)(struct platform_device *);
驱动资源结构体:struct device_driver driver;
一个驱动层可匹配多个设备层,若想同时匹配多个设备层,则通过id_table 指针完成匹配。

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;//匹配多多设备时需要填写
};
  • struct device_driver driver 结构信息

  struct device_driver driver 结构体中有个成员name必须要填写,当没有实现id_table指针时,设备层和驱动层就是通过该成员完成资源匹配。

struct device_driver {
	const char		*name; //资源匹配参数
	struct bus_type		*bus;

	struct module		*owner;
	const char		*mod_name;	/* used for built-in modules */

	bool suppress_bind_attrs;	/* disables bind/unbind via sysfs */

	const struct of_device_id	*of_match_table;

	int (*probe) (struct device *dev);
	int (*remove) (struct device *dev);
	void (*shutdown) (struct device *dev);
	int (*suspend) (struct device *dev, pm_message_t state);
	int (*resume) (struct device *dev);
	const struct attribute_group **groups;

	const struct dev_pm_ops *pm;

	struct driver_private *p;
};
  • const struct platform_device_id *id_table 结构信息

  该结构也是用于匹配设备资源,一个驱动层可以同时匹配多个设备层。

struct platform_device_id {
	char name[PLATFORM_NAME_SIZE]; //资源匹配参数
	kernel_ulong_t driver_data
			__attribute__((aligned(sizeof(kernel_ulong_t)))); //匹配设备层的 void *platform_data数据
};
  • 驱动层注册和注销函数
//驱动注册函数
int platform_driver_register(struct platform_driver *drv)
//驱动注销函数
void platform_driver_unregister(struct platform_driver *drv)

3.平台设备框架应用示例

3.1 设备层注册示例

设备层注册步骤:

填充struct device结构体,填写设备资源信息struct resource * resource;
调用设备层注册函数platform_device_register();
注销时调用注销函数platform_device_unregister;

#include 
#include 
#include 
#include 
#include 
#include 

#include 
#include 
#include 

static void platform_release(struct device *dev)
{
	printk("资源释放完成n");
}
static struct resource	resource[]=
{
	[0]={
			.start=EXYNOS4X12_GPM4(0),
			.end=EXYNOS4X12_GPM4(0),
			.name="led1",
			.flags=IORESOURCE_MEM
		},
	[1]={
			.start=EXYNOS4X12_GPM4(1),
			.end=EXYNOS4X12_GPM4(1),
			.name="led2",
			.flags=IORESOURCE_MEM
		},		
		
};

struct platform_device pdev=
{
	.name="led_dev",
	.id=-1,
	.dev=
	{
		.release=platform_release,//资源释放函数
	},
	.num_resources=sizeof(resource)/sizeof(resource[0]),
	.resource=resource,	
};

static int __init wbyq_platform_dev_init(void)
{
	platform_device_register(&pdev);
    return 0;
}
/*驱动释放*/
static void __exit wbyq_platform_dev_cleanup(void)
{
	/*注销设备层*/
	platform_device_unregister(&pdev);

}
module_init(wbyq_platform_dev_init);//驱动入口函数
module_exit(wbyq_platform_dev_cleanup);//驱动出口函数

MODULE_LICENSE("GPL");//驱动注册协议
MODULE_AUTHOR("it_ashui");
MODULE_DESCRIPTION("Exynos4 platform_dev Driver");

3.2 驱动层注册示例

驱动层注册步骤:

填充 struct platform_driver结构体,实现资源匹配函数和资源释放函数;
调用设备层注册函数platform_driver_register();
注销时调用注销函数platform_driver_unregister;

#include 
#include 
#include 
#include 
#include 
#include 

#include 
#include 
#include 

static int platform_probe(struct platform_device *dev)
{
	printk("资源匹配成功n");
	printk("资源个数:%dn",dev->num_resources);
	struct resource * resource=platform_get_resource(dev,IORESOURCE_MEM,0);
	if(resource)
	{
		printk("资源名:%ststart=%xtend=%xn",resource->name,resource->start,resource->end);
	}
	return 0;
	
}
static int platform_remove(struct platform_device *dev)
{
	printk("资源释放成功n");
	return 0;
}
static struct platform_device_id id_table[]=
{
	[0]=
	{
		.name="led_dev"
	},
	[1]=
	{
		.name="tiny4412_dev"
	},
	
};
static struct platform_driver drv=
{
	.probe=platform_probe,
	.remove=platform_remove,
	.driver=
	{
		.name="platform_drv",
	},
	.id_table=id_table,
};
static int __init wbyq_platform_drv_init(void)
{
	platform_driver_register(&drv);
	printk("驱动层平台设备注册成功n");
    return 0;
}
/*驱动释放*/
static void __exit wbyq_platform_drv_cleanup(void)
{
	/*注销设备层*/
	platform_driver_unregister(&drv);
	printk("驱动层平台设备注销成功n");

}
module_init(wbyq_platform_drv_init);//驱动入口函数
module_exit(wbyq_platform_drv_cleanup);//驱动出口函数

MODULE_LICENSE("GPL");//驱动注册协议
MODULE_AUTHOR("it_ashui");
MODULE_DESCRIPTION("Exynos4 platform_drv Driver");

3.3 Makefile文件

KER_ADD=/home/wbyq/src_pack/linux-3.5
all:
	make -C $(KER_ADD) M=`pwd` modules
	#arm-linux-gcc main.c -o app 
	cp ./*.ko  /home/wbyq/src_pack/rootfs/code 
	make -C $(KER_ADD) M=`pwd` modules clean
	rm app -f
obj-m +=platform_drv.o platform_dev.o platform_dev2.o

4 运行效效果

pYYBAGMto8uAbpCWAAB_bTHp4zA763.png#pic_center

审核编辑:汤梓红

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 接口
    +关注

    关注

    33

    文章

    7640

    浏览量

    148512
  • Linux
    +关注

    关注

    87

    文章

    10990

    浏览量

    206738
  • 函数
    +关注

    关注

    3

    文章

    3882

    浏览量

    61310
收藏 人收藏

    评论

    相关推荐

    linux平台设备驱动

    linux平台设备驱动http://bbs.edu118.com/forum.php?mod=viewthread&tid=630&fromuid=231(出处: 信盈达IT技术社
    发表于 09-01 14:40

    字符设备驱动设备驱动模型、sysfs、平台设备驱动的关系 -----从需求的角度去理解Linux之三

    学习Linux设备驱动开发的过程中自然会遇到字符设备驱动平台
    发表于 12-17 16:16

    linux驱动框架是什么

    编写linux驱动先看一下驱动框架是什么样子的。驱动编写和应用层编写有什么区别呢?
    发表于 07-26 08:14

    字符设备驱动 —— 字符设备驱动框架

      3、字符设备驱动框架作为字符设备驱动要素:1,必须有一个设备号,用在众多到
    发表于 10-19 17:08

    OpenHarmony系统平台驱动驱动框架概述

    接口。这里的平台设备,泛指I2C/UART等总线、以及GPIO/RTC等SOC片内硬件资源。OpenHarmony系统平台驱动框架是Open
    发表于 03-28 10:58

    想要驾驭Linux驱动开发,必须深刻理解Linux总线设备驱动框架

    想要驾驭Linux驱动开发,必须深刻理解Linux总线设备驱动框架。之所以会形成这样的
    的头像 发表于 03-22 11:08 1w次阅读
    想要驾驭<b class='flag-5'>Linux</b><b class='flag-5'>驱动</b>开发,必须深刻理解<b class='flag-5'>Linux</b>总线<b class='flag-5'>设备</b><b class='flag-5'>驱动</b><b class='flag-5'>框架</b>

    你对Linux总线设备驱动框架是否了解

    Linux设备驱动模型,或者说,Linux设备驱动框架
    发表于 05-05 15:13 603次阅读

    米尔科技Linux设备驱动研究浅谈

    Linux设备驱动开发详解(第2版)》是一本介绍linux设备驱动开发理论、
    的头像 发表于 11-25 09:32 1782次阅读
    米尔科技<b class='flag-5'>Linux</b><b class='flag-5'>设备</b><b class='flag-5'>驱动</b>研究浅谈

    如何使用Linux内核实现USB驱动程序框架

    Linux内核提供了完整的USB驱动程序框架。USB总线采用树形结构,在一条总线上只能有唯一的主机设备Linux内核从主机和
    发表于 11-06 17:59 19次下载
    如何使用<b class='flag-5'>Linux</b>内核实现USB<b class='flag-5'>驱动</b>程序<b class='flag-5'>框架</b>

    OpenHarmony HDF平台驱动框架驱动适配介绍

    驱动平台设备(PlatformDevice),为系统及外设驱动提供访接口。这里的平台设备,泛指
    的头像 发表于 09-24 11:16 5909次阅读
    OpenHarmony HDF<b class='flag-5'>平台</b><b class='flag-5'>驱动</b><b class='flag-5'>框架</b>及<b class='flag-5'>驱动</b>适配介绍

    嵌入式Linux驱动开发从基础到框架

    。在一众嵌入式Linux驱动书中笔者最推崇宋宝华的《Linux设备驱动开发详解》,但他完全可以更进一步上升到
    发表于 11-01 16:58 13次下载
    嵌入式<b class='flag-5'>Linux</b><b class='flag-5'>驱动</b>开发从基础到<b class='flag-5'>框架</b>

    Linux内核中视频设备驱动框架V4L2X详解

    V4L2(Video for Linux 2):Linux内核中关于视频设备驱动框架,对上向应用层提供统一的接口,对下支持各类复杂硬件的灵
    的头像 发表于 05-30 16:18 5182次阅读

    看看Linux为相机提供的驱动框架

      V4L2 (Video Linux Two),是为支持Linux内核设计的驱动框架驱动框架
    的头像 发表于 08-07 16:03 2689次阅读
    看看<b class='flag-5'>Linux</b>为相机提供的<b class='flag-5'>驱动</b><b class='flag-5'>框架</b>

    Linux的PWM驱动框架及实现方法

    本文主要讲述了Linux的PWM驱动框架、实现方法、驱动添加方法和调试方法。
    的头像 发表于 05-14 15:24 1018次阅读
    <b class='flag-5'>Linux</b>的PWM<b class='flag-5'>驱动</b><b class='flag-5'>框架</b>及实现方法

    Linux Regmap 驱动框架

    层,regmap 向驱动编写人员提供的 API 接口,驱动编写人员使用这些API 接口来操作具体的芯片设备,也是驱动编写人员重点要掌握的。 2、regmap 结构体
    的头像 发表于 07-06 17:29 743次阅读
    <b class='flag-5'>Linux</b> Regmap <b class='flag-5'>驱动</b><b class='flag-5'>框架</b>