0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線(xiàn)課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

Linux平臺(tái)設(shè)備框架驅(qū)動(dòng)

嵌入式技術(shù) ? 來(lái)源:嵌入式技術(shù) ? 作者:嵌入式技術(shù) ? 2022-09-25 08:59 ? 次閱讀

Linux平臺(tái)設(shè)備框架驅(qū)動(dòng)

? 平臺(tái)設(shè)備框架(platform)是將一個(gè)驅(qū)動(dòng)分為設(shè)備層和驅(qū)動(dòng)層兩個(gè)部分,通過(guò)總線(xiàn)模型將設(shè)備和驅(qū)動(dòng)進(jìn)行綁定。在系統(tǒng)中每注冊(cè)一個(gè)設(shè)備,都會(huì)與之匹配一個(gè)驅(qū)動(dòng),同樣的,每注冊(cè)一個(gè)驅(qū)動(dòng)也會(huì)與之匹配一個(gè)設(shè)備。
通常 Linux 設(shè)備和驅(qū)動(dòng)通常都需要掛接在一種總線(xiàn)上,對(duì)于本身依附于 PCI、 USB、 I2 C、 SPI 等的設(shè)備而言,這自然不是問(wèn)題,但是在嵌入式系統(tǒng)里面, SOC 系統(tǒng)中集成的獨(dú)立的外設(shè)控制器、掛接在 SOC 內(nèi)存空間的外設(shè)等卻不依附于此類(lèi)總線(xiàn)。
基于總線(xiàn)框架的模型結(jié)構(gòu),Linux下就衍生了平臺(tái)設(shè)備框架模型(platform),平臺(tái)設(shè)備總線(xiàn)是一種虛擬總線(xiàn),稱(chēng)為platform總線(xiàn)。對(duì)應(yīng)的設(shè)備層稱(chēng)為platform_device;驅(qū)動(dòng)層稱(chēng)為platform_driver。設(shè)備層和驅(qū)動(dòng)層通過(guò)平臺(tái)設(shè)備總線(xiàn)進(jìn)行匹配管理。

1.平臺(tái)設(shè)備框架特性

平臺(tái)模型采用了分層結(jié)構(gòu),把一個(gè)設(shè)備驅(qū)動(dòng)程序分成了兩個(gè)部分:
平臺(tái)設(shè)備( platform_device)和平臺(tái)驅(qū)動(dòng)( platform_driver)。
平臺(tái)設(shè)備將設(shè)備本身的資源注冊(cè)進(jìn)內(nèi)核,可以由內(nèi)核統(tǒng)一管理。
硬件資源和驅(qū)動(dòng)接口分離,編譯代碼的維護(hù)與移植。

poYBAGMto8uAVBODAAFDIhZx3Kk481.png#pic_center

2.平臺(tái)設(shè)備總線(xiàn)相關(guān)接口函數(shù)

2.1 設(shè)備層接口函數(shù)

??每個(gè)設(shè)備的系統(tǒng)通過(guò)設(shè)備結(jié)構(gòu)體struct platform_device保存。結(jié)構(gòu)體原型在 include/linux/platform_devcie.h 中定義。

struct platform_device {
	const char	* name; //設(shè)備名字,驅(qū)動(dòng)層和設(shè)備層匹配標(biāo)志
	int		id;//通常填-1
	struct device	dev;//設(shè)備結(jié)構(gòu)體信息
	u32		num_resources;//資源個(gè)數(shù)
	struct resource	* resource;//資源內(nèi)容
	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結(jié)構(gòu)信息

struct device dev 結(jié)構(gòu)體是用來(lái)實(shí)現(xiàn)設(shè)備模型的。這個(gè)結(jié)構(gòu)體中成員比較多,結(jié)構(gòu)體原型在 include/linux/devcie.h 中定義。我們常關(guān)心的是其中的兩個(gè)成員:
平臺(tái)數(shù)據(jù)指針: void *platform_data;
資源釋放函數(shù): void (*release)(struct device *dev);
平臺(tái)數(shù)據(jù)指針platform_data是一個(gè)void *類(lèi)型指針,可以向驅(qū)動(dòng)層傳遞任意數(shù)據(jù),release資源釋放函數(shù)接口在設(shè)備層一定要自己實(shí)現(xiàn),否則在設(shè)備層釋放資源時(shí)會(huì)報(bào)錯(cuò)。
以下列舉其中幾個(gè)成員結(jié)構(gòu):

struct device {
	const char *init_name; /*邏輯設(shè)備的名字*/
	struct device_type *type; /* 設(shè)備類(lèi)型 */
	struct bus_type *bus; /* 設(shè)備所屬的總線(xiàn)類(lèi)型 */
	struct device_driver *driver;/* 指向開(kāi)辟 struct device 結(jié)構(gòu) driver 指針*/
	void		*platform_data;	/* 平臺(tái)設(shè)備指針 */
	dev_t devt;  /* 存放設(shè)備號(hào) dev_t,creates the sysfs"dev" */
	struct class *class;  /* 設(shè)備所屬類(lèi)*/
	void	(*release)(struct device *dev);/*設(shè)備資源釋放函數(shù)*/
};
  • struct resource * resource結(jié)構(gòu)信息

    ??struct resource * resource 結(jié)構(gòu)體是用來(lái)保存設(shè)備資源內(nèi)容信息。該結(jié)構(gòu)體定義位置: include/linux/ioport.h
struct resource {
	resource_size_t start; //資源起始地址
	resource_size_t end; //資源結(jié)構(gòu)地址
	const char *name;//資源名字
	unsigned long flags;//資源類(lèi)型
	struct resource *parent, *sibling, *child;
};
  • 設(shè)備層注冊(cè)函數(shù)
int platform_device_register(struct platform_device *pdev)
函數(shù)功能: 注冊(cè)平臺(tái)設(shè)備;
形參: pdev --設(shè)備結(jié)構(gòu)體;
返回值: 成功返回0,失敗返回其它值;
  • 設(shè)備層注銷(xiāo)函數(shù)
void platform_device_unregister(struct platform_device *pdev)
函數(shù)功能: 注冊(cè)平臺(tái)設(shè)備;
形參: pdev --設(shè)備結(jié)構(gòu)體;
  • 向內(nèi)核添加多個(gè)設(shè)備
int platform_add_devices(struct platform_device **devs, int num)
函數(shù)功能: 向內(nèi)核注冊(cè)多個(gè)設(shè)備;
形參: pdev --設(shè)備結(jié)構(gòu)體;
???num – 注冊(cè)的設(shè)備個(gè)數(shù)
返回值: 成功返回0,失敗返回其它值;

2.2 驅(qū)動(dòng)層接口函數(shù)

驅(qū)動(dòng)層通過(guò)struct platform_driver 結(jié)構(gòu)體保存相關(guān)信息,結(jié)構(gòu)體定義位置: include/linux/devcie.h
在該結(jié)構(gòu)體中必須要實(shí)現(xiàn)接口函數(shù):

資源匹配函數(shù):int (*probe)(struct platform_device *)
資源釋放函數(shù):int (*remove)(struct platform_device *);
驅(qū)動(dòng)資源結(jié)構(gòu)體:struct device_driver driver;
一個(gè)驅(qū)動(dòng)層可匹配多個(gè)設(shè)備層,若想同時(shí)匹配多個(gè)設(shè)備層,則通過(guò)id_table 指針完成匹配。

struct platform_driver {
	int (*probe)(struct platform_device *);//資源匹配函數(shù)
	int (*remove)(struct platform_device *);//資源釋放函數(shù)
	void (*shutdown)(struct platform_device *);
	int (*suspend)(struct platform_device *, pm_message_t state);
	int (*resume)(struct platform_device *);
	struct device_driver driver;//驅(qū)動(dòng)資源結(jié)構(gòu)體
	const struct platform_device_id *id_table;//匹配多多設(shè)備時(shí)需要填寫(xiě)
};
  • struct device_driver driver 結(jié)構(gòu)信息

??struct device_driver driver 結(jié)構(gòu)體中有個(gè)成員name必須要填寫(xiě),當(dāng)沒(méi)有實(shí)現(xiàn)id_table指針時(shí),設(shè)備層和驅(qū)動(dòng)層就是通過(guò)該成員完成資源匹配。

struct device_driver {
	const char		*name; //資源匹配參數(shù)
	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 結(jié)構(gòu)信息

??該結(jié)構(gòu)也是用于匹配設(shè)備資源,一個(gè)驅(qū)動(dòng)層可以同時(shí)匹配多個(gè)設(shè)備層。

struct platform_device_id {
	char name[PLATFORM_NAME_SIZE]; //資源匹配參數(shù)
	kernel_ulong_t driver_data
			__attribute__((aligned(sizeof(kernel_ulong_t)))); //匹配設(shè)備層的 void *platform_data數(shù)據(jù)
};
  • 驅(qū)動(dòng)層注冊(cè)和注銷(xiāo)函數(shù)
//驅(qū)動(dòng)注冊(cè)函數(shù)
int platform_driver_register(struct platform_driver *drv)
//驅(qū)動(dòng)注銷(xiāo)函數(shù)
void platform_driver_unregister(struct platform_driver *drv)

3.平臺(tái)設(shè)備框架應(yīng)用示例

3.1 設(shè)備層注冊(cè)示例

設(shè)備層注冊(cè)步驟:

填充struct device結(jié)構(gòu)體,填寫(xiě)設(shè)備資源信息struct resource * resource;
調(diào)用設(shè)備層注冊(cè)函數(shù)platform_device_register();
注銷(xiāo)時(shí)調(diào)用注銷(xiāo)函數(shù)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,//資源釋放函數(shù)
	},
	.num_resources=sizeof(resource)/sizeof(resource[0]),
	.resource=resource,	
};

static int __init wbyq_platform_dev_init(void)
{
	platform_device_register(&pdev);
    return 0;
}
/*驅(qū)動(dòng)釋放*/
static void __exit wbyq_platform_dev_cleanup(void)
{
	/*注銷(xiāo)設(shè)備層*/
	platform_device_unregister(&pdev);

}
module_init(wbyq_platform_dev_init);//驅(qū)動(dòng)入口函數(shù)
module_exit(wbyq_platform_dev_cleanup);//驅(qū)動(dòng)出口函數(shù)

MODULE_LICENSE("GPL");//驅(qū)動(dòng)注冊(cè)協(xié)議
MODULE_AUTHOR("it_ashui");
MODULE_DESCRIPTION("Exynos4 platform_dev Driver");

3.2 驅(qū)動(dòng)層注冊(cè)示例

驅(qū)動(dòng)層注冊(cè)步驟:

填充 struct platform_driver結(jié)構(gòu)體,實(shí)現(xiàn)資源匹配函數(shù)和資源釋放函數(shù);
調(diào)用設(shè)備層注冊(cè)函數(shù)platform_driver_register();
注銷(xiāo)時(shí)調(diào)用注銷(xiāo)函數(shù)platform_driver_unregister;

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

#include 
#include 
#include 

static int platform_probe(struct platform_device *dev)
{
	printk("資源匹配成功n");
	printk("資源個(gè)數(shù):%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("驅(qū)動(dòng)層平臺(tái)設(shè)備注冊(cè)成功n");
    return 0;
}
/*驅(qū)動(dòng)釋放*/
static void __exit wbyq_platform_drv_cleanup(void)
{
	/*注銷(xiāo)設(shè)備層*/
	platform_driver_unregister(&drv);
	printk("驅(qū)動(dòng)層平臺(tái)設(shè)備注銷(xiāo)成功n");

}
module_init(wbyq_platform_drv_init);//驅(qū)動(dòng)入口函數(shù)
module_exit(wbyq_platform_drv_cleanup);//驅(qū)動(dòng)出口函數(shù)

MODULE_LICENSE("GPL");//驅(qū)動(dòng)注冊(cè)協(xié)議
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 運(yùn)行效效果

pYYBAGMto8uAbpCWAAB_bTHp4zA763.png#pic_center

審核編輯:湯梓紅

聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 接口
    +關(guān)注

    關(guān)注

    33

    文章

    8357

    瀏覽量

    150517
  • Linux
    +關(guān)注

    關(guān)注

    87

    文章

    11161

    瀏覽量

    208468
  • 函數(shù)
    +關(guān)注

    關(guān)注

    3

    文章

    4257

    瀏覽量

    62226
收藏 人收藏

    評(píng)論

    相關(guān)推薦

    Linux字符設(shè)備驅(qū)動(dòng)開(kāi)發(fā)框架介紹

    字符設(shè)備Linux驅(qū)動(dòng)中最基本的一類(lèi)設(shè)備驅(qū)動(dòng),字符設(shè)備就是一個(gè)一個(gè)字節(jié),按照字節(jié)流進(jìn)行讀寫(xiě)操作
    發(fā)表于 04-15 11:52 ?1277次閱讀
    <b class='flag-5'>Linux</b>字符<b class='flag-5'>設(shè)備</b><b class='flag-5'>驅(qū)動(dòng)</b>開(kāi)發(fā)<b class='flag-5'>框架</b>介紹

    linux平臺(tái)設(shè)備驅(qū)動(dòng)

    linux平臺(tái)設(shè)備驅(qū)動(dòng)http://bbs.edu118.com/forum.php?mod=viewthread&tid=630&fromuid=231(出處: 信盈達(dá)IT技術(shù)社
    發(fā)表于 09-01 14:40

    字符設(shè)備驅(qū)動(dòng)、設(shè)備驅(qū)動(dòng)模型、sysfs、平臺(tái)設(shè)備驅(qū)動(dòng)的關(guān)系 -----從需求的角度去理解Linux之三

    學(xué)習(xí)Linux設(shè)備驅(qū)動(dòng)開(kāi)發(fā)的過(guò)程中自然會(huì)遇到字符設(shè)備驅(qū)動(dòng)、平臺(tái)
    發(fā)表于 12-17 16:16

    OpenHarmony系統(tǒng)平臺(tái)驅(qū)動(dòng)驅(qū)動(dòng)框架概述

    接口。這里的平臺(tái)設(shè)備,泛指I2C/UART等總線(xiàn)、以及GPIO/RTC等SOC片內(nèi)硬件資源。OpenHarmony系統(tǒng)平臺(tái)驅(qū)動(dòng)框架是Open
    發(fā)表于 03-28 10:58

    嵌入式Linux的USB驅(qū)動(dòng)設(shè)計(jì)

    本文主要介紹了 Linux 平臺(tái)的USB設(shè)備驅(qū)動(dòng)開(kāi)發(fā)的一般步驟方法和技巧,通過(guò)詳細(xì)介紹USB的相關(guān)概念和Linux中USB
    發(fā)表于 06-08 17:15 ?49次下載
    嵌入式<b class='flag-5'>Linux</b>的USB<b class='flag-5'>驅(qū)動(dòng)</b>設(shè)計(jì)

    想要駕馭Linux驅(qū)動(dòng)開(kāi)發(fā),必須深刻理解Linux總線(xiàn)設(shè)備驅(qū)動(dòng)框架

    想要駕馭Linux驅(qū)動(dòng)開(kāi)發(fā),必須深刻理解Linux總線(xiàn)設(shè)備驅(qū)動(dòng)框架。之所以會(huì)形成這樣的
    的頭像 發(fā)表于 03-22 11:08 ?1.1w次閱讀
    想要駕馭<b class='flag-5'>Linux</b><b class='flag-5'>驅(qū)動(dòng)</b>開(kāi)發(fā),必須深刻理解<b class='flag-5'>Linux</b>總線(xiàn)<b class='flag-5'>設(shè)備</b><b class='flag-5'>驅(qū)動(dòng)</b><b class='flag-5'>框架</b>

    Linux DMA Engine框架的介紹

    此會(huì)話(huà)描述如何從設(shè)備驅(qū)動(dòng)程序在Linux中使用DMA。 這包括內(nèi)存分配,緩存控制和DMA設(shè)備控制。 詳細(xì)介紹了Linux DMA Eng
    的頭像 發(fā)表于 11-23 06:29 ?6185次閱讀

    你對(duì)Linux總線(xiàn)設(shè)備驅(qū)動(dòng)框架是否了解

    Linux設(shè)備驅(qū)動(dòng)模型,或者說(shuō),Linux設(shè)備驅(qū)動(dòng)框架
    發(fā)表于 05-05 15:13 ?707次閱讀

    米爾科技Linux設(shè)備驅(qū)動(dòng)研究淺談

    Linux設(shè)備驅(qū)動(dòng)開(kāi)發(fā)詳解(第2版)》是一本介紹linux設(shè)備驅(qū)動(dòng)開(kāi)發(fā)理論、
    的頭像 發(fā)表于 11-25 09:32 ?1958次閱讀
    米爾科技<b class='flag-5'>Linux</b><b class='flag-5'>設(shè)備</b><b class='flag-5'>驅(qū)動(dòng)</b>研究淺談

    如何使用Linux內(nèi)核實(shí)現(xiàn)USB驅(qū)動(dòng)程序框架

    Linux內(nèi)核提供了完整的USB驅(qū)動(dòng)程序框架。USB總線(xiàn)采用樹(shù)形結(jié)構(gòu),在一條總線(xiàn)上只能有唯一的主機(jī)設(shè)備Linux內(nèi)核從主機(jī)和
    發(fā)表于 11-06 17:59 ?19次下載
    如何使用<b class='flag-5'>Linux</b>內(nèi)核實(shí)現(xiàn)USB<b class='flag-5'>驅(qū)動(dòng)</b>程序<b class='flag-5'>框架</b>

    OpenHarmony HDF平臺(tái)驅(qū)動(dòng)框架驅(qū)動(dòng)適配介紹

    驅(qū)動(dòng)平臺(tái)設(shè)備(PlatformDevice),為系統(tǒng)及外設(shè)驅(qū)動(dòng)提供訪(fǎng)接口。這里的平臺(tái)設(shè)備,泛指
    的頭像 發(fā)表于 09-24 11:16 ?6603次閱讀
    OpenHarmony HDF<b class='flag-5'>平臺(tái)</b><b class='flag-5'>驅(qū)動(dòng)</b><b class='flag-5'>框架</b>及<b class='flag-5'>驅(qū)動(dòng)</b>適配介紹

    Linux內(nèi)核中視頻設(shè)備驅(qū)動(dòng)框架V4L2X詳解

    V4L2(Video for Linux 2):Linux內(nèi)核中關(guān)于視頻設(shè)備驅(qū)動(dòng)框架,對(duì)上向應(yīng)用層提供統(tǒng)一的接口,對(duì)下支持各類(lèi)復(fù)雜硬件的靈
    的頭像 發(fā)表于 05-30 16:18 ?5914次閱讀

    看看Linux為相機(jī)提供的驅(qū)動(dòng)框架

    ? V4L2 (Video Linux Two),是為支持Linux內(nèi)核設(shè)計(jì)的驅(qū)動(dòng)框架驅(qū)動(dòng)框架。
    的頭像 發(fā)表于 08-07 16:03 ?3159次閱讀
    看看<b class='flag-5'>Linux</b>為相機(jī)提供的<b class='flag-5'>驅(qū)動(dòng)</b><b class='flag-5'>框架</b>

    Linux的PWM驅(qū)動(dòng)框架及實(shí)現(xiàn)方法

    本文主要講述了Linux的PWM驅(qū)動(dòng)框架、實(shí)現(xiàn)方法、驅(qū)動(dòng)添加方法和調(diào)試方法。
    的頭像 發(fā)表于 05-14 15:24 ?1324次閱讀
    <b class='flag-5'>Linux</b>的PWM<b class='flag-5'>驅(qū)動(dòng)</b><b class='flag-5'>框架</b>及實(shí)現(xiàn)方法

    Linux Regmap 驅(qū)動(dòng)框架

    ,regmap 向驅(qū)動(dòng)編寫(xiě)人員提供的 API 接口,驅(qū)動(dòng)編寫(xiě)人員使用這些API 接口來(lái)操作具體的芯片設(shè)備,也是驅(qū)動(dòng)編寫(xiě)人員重點(diǎn)要掌握的。 2、regmap 結(jié)構(gòu)體
    的頭像 發(fā)表于 07-06 17:29 ?1012次閱讀
    <b class='flag-5'>Linux</b> Regmap <b class='flag-5'>驅(qū)動(dòng)</b><b class='flag-5'>框架</b>