详细教Linux驱动10平台总线 澳洋科技股票

股票资讯  2021-03-06 09:45:26

原标题:详细教Linux驱动10平台总线

平台总线是学习linux驱动程序必须掌握的知识点。

一.概念

嵌入式系统中有许多物理总线:I2c、SPI、USB、uart、PCIE、APB、AHB

Linux从2.6开始加入了驱动管理和注册的新机制。平台总线是虚拟总线,不是物理总线。

与PCI和USB相比,主要用于描述SOC上的片上资源。平台描述的资源有一个共同点:直接在CPU的总线上访问。

平台设备被分配一个名称(用于驱动程序绑定)和一系列资源,如地址和中断请求号(IRQ)。

设备由platform_device表示,驱动程序由platform_driver注册。

与传统的总线/设备/驱动机制相比,平台由内核管理,使用驱动中的资源,提高了代码的安全性和可移植性。

第二,平台1。平台总线最重要的两种结构

平台维护的所有驱动程序必须由以下结构定义:

platform _ driver struct platform _ driver {

int(* probe)(struct platform _ device *);//

int(* remove)(struct platform _ device *);

void(* shut down)(struct platform _ device *);

int(* suspend)(struct platform _ device *,pm _ message _ ts state);

int(* resume)(struct platform _ device *);

structdevice _ driverdriver

constructplatform _ device _ id * id _ table;

boolprevent _ delivered _ probe;

};

该结构用于将驱动程序注册到平台总线。

成员 意义 探针 当驱动和硬件信息匹配成功时,会调用探测函数,所有驱动资源的注册和初始化都放在探测函数中 除去 硬件信息已被删除,或者驱动程序已被卸载,必须全部释放。释放资源的操作放在这个函数中 struct设备驱动程序 内核维护的所有驱动都必须包含这个成员,通常是驱动->名称用于与设备匹配 const struct platform _ device _ id * id _ table 通常,一个驱动程序可以同时支持多个硬件,这些硬件的名称都放在结构数组中 我们写驱动的时候,经常需要填写上面的成员

平台设备

平台总线用于描述设备硬件信息的结构,包括所有资源(io、内存、中断、DMA等。)的硬件。

structplatform_device{

constchar * name

intid

boolid _ auto

structdevicedev

u32 num _ resources

structresource*资源;

constructplatform _ device _ id * id _ entry;

/* MFD单元格指针*/

structmfd _ cell * mfd _ cell

/* arch特定附加功能*/

structpdev _ archdataarchdata

};

成员 意义 const char *名称 用于匹配驱动程序的设备名称 struct devicedev 内核中维护的所有设备都必须包含该成员。 u32num_resources 资源数量 结构资源*资源 描述资源 struct devicedev->必须实施该版本。

描述了硬件信息的成员结构资源

0x139d0000

structresource{

resource _ size _ tstart//指示资源的起始值。

resource _ size _ tend//表示资源最后一个字节的地址。如果是中断,end和satrt是相同的

constchar * name//不写

unsignedlongflags//资源类型

structresource*父级,*同级,*子级;

};

标志的类型描述

# defineoresource _ mem 0x 00000200//内存

# defineoresource _ IRQ 0x 00000400//中断

所有由内核管理的驱动程序必须包含一个名为struct device_driver的成员。//男人描述的硬件必须包含结构设备结构成员。//女

structdevice_driver{

constchar * name

structbus _ type * bus

structmodule*所有者;

constchar * mod _ name/*用于内置模块*/

boolsuppress _ bind _ attrs/*通过sysfs禁用绑定/解除绑定*/

construct of _ device _ id * of _ match _ table;

constructacpi _ device _ id * acpi _ match _ table;

int(* probe)(struct device * dev);

int(* remove)(struct device * dev);

void(* shut down)(struct device * dev);

int(*suspend) (struct device *dev,pm _ message _ ts state);

int(* resume)(struct device * dev);

construct attribute _ group * * group;

conststructdev _ pm _ ops * pm

struct driver _ private * p;

};

其中:

constchar * name

用于与硬件匹配。

内核描述硬件,必须包含结构设备结构成员:

structdevice{

structdevice*父级;

struct device _ private * p;

structkobjectkobj

constchar * init _ name/*设备的初始名称*/

conststructdevice _ type * type

structmutexmutex/*要同步调用的互斥体

*它的驱动程序。

*/

structbus _ type * bus/*总线设备类型开启*/

structdevice_driver*驱动程序;/*哪个驱动程序分配了这个

设备*/

void * platform _ data/*平台特定数据、设备

core不碰它*/

structdev _ pm _ infopower

structdev _ pm _ domain * pm _ domain

# ifdefCONFIG_PINCTRL

structdev _ pin _ info * pins

# endif

# ifdefCONFIG_NUMA

intnuma _ node/*此设备靠近的NUMA节点*/

# endif

u64 * dma _ mask/* dma掩码(如果是可dma设备)*/

u64 coherent _ dma _ mask/*像dma_mask,但是对于

alloc_coherent映射为

并非所有硬件都支持

一致的64位地址

像deors这样的分配。*/

struct device _ DMA _ parameters * DMA _ parms;

structlist _ headdma _ pools/* dma池(如果dma可用)*/

struct DMA _ coherent _ mem * DMA _ mem;/*内部用于连贯记忆

覆盖*/

# ifdefCONFIG_DMA_CMA

structcma * cma _ area/* DMA的连续存储区

分配*/

# endif

/* arch特定附加功能*/

structdev _ archdataarchdata

structdevice _ node * of _ node/*关联的设备树节点*/

structacpi _ dev _ nodeacpi _ node/*关联的ACPI设备节点*/

dev _ tdevt/* dev_t,创建sysfs“dev”*/

u32 id/*设备实例*/

spinlock _ tdevres _ lock

structlist _ headdevres _ head

structklist _ nodeknode _ class

structclass * class

construct attribute _ group * * group;/*可选组*/

void(* release)(struct device * dev);

structiommu _ group * iommu _ group

booloffline _ disabled:1;

booloffline:1;

};

其中:

void(* release)(struct device * dev);

它不能为空。

2.如何注册

向注册平台驱动程序

1)注册驱动平台_设备_寄存器

/**

* platform_device_register -添加平台级设备

* @pdev:我们正在添加的平台设备

*/

int platform _ device _ register(struct platform _ device * pdev)

{

device _ initialize(& amp;pdev->dev);

arch _ setup _ pdev _ archdata(pdev);

return platform _ device _ add(pdev);

}

2)注册设备platform_driver_register

# defineplatform _ driver _ register(drv)

_ _平台_驱动程序_寄存器(drv,THIS _ MODULE)

三.例1。开发步骤

平台总线下驱动的开发步骤如下:

设备

要实现的结构是platform_device。

1)初始化资源结构变量

2)初始化平台_设备结构变量

3)向系统注册设备:platform_device_register。

以上三个步骤必须在加载设备驱动之前,也就是在执行platform_driver_register之前完成,因为驱动注册需要匹配内核中所有注册的设备名称。

在platform_driver_register中向内核添加设备是最终要调用的device_add函数。

Platform_device_add和device_add的主要区别是insert_resource(p,r),即把平台资源添加到内核中,由内核统一管理。

开车

在驱动注册中,要实现的结构是platform_driver。

在驱动的初始化函数中,调用platform_driver_register来注册platform_driver。

需要注意的是,platform_driver和platform_device中的name变量值必须相同[不考虑设备树,后面会写一篇关于设备树的新文章详细介绍]。

这样,在注册platform_driver_register时,会将当前注册的platform_driver中的name变量值与所有注册的platform_devices中的name变量值进行比较,只有找到同名的platform _ device,注册才能成功。

注册成功后,将调用platform_driver结构元素的探测函数指针。

例1

这个例子很简单,只用来测试platform_driver和platform_device能否匹配成功。

左边是platform_device结构注册的代码,右边是platform_driver结构注册的代码。

Platform_driver定义和注册:

1#包括<。Linux/init . h & gt;

2#包括<。linux/module.h>。

3#包括<。Linux/platform _ device . h & gt;

4#包括<。Linux/I port . h & gt。

6 staticintello _ probe(struct platform _ device * pdev)

7 {

8 printk(" match ok n ");

9return0

10}

11 staticinthello _ remove(struct platform _ device * pdev)

12 {

13 printk(" hello _ remove n ");

14return0

15}

16 staticstructplatform _ driverhello _ driver =

17 {

18.probe = hello_probe,

19.driver.name = "duang ",

20.remove = hello_remove,

21};

22staticinthello_init( void)

23 {

24 printk(" hello _ init n ");

25 return platform _ driver _ register(& amp;hello _ driver);

26}

27staticvoidhello_exit( void)

28 {

29 printk(" hello _ exit n ");

30 platform _ driver _ unregister(& amp;hello _ driver);

31return

32}

33 module _ LICENSE(" GPL ");

34 module _ init(hello _ init);

35 module _ exit(hello _ exit);

平台_设备定义和注册:

1#包括<。Linux/init . h & gt;

2#包括<。linux/module.h>。

3#包括<。Linux/platform _ device . h & gt;

4#包括<。Linux/I port . h & gt。

6staticvoidhello_release(结构设备*dev)

7 {

8返回;

9}

10 statisticstructplatform _ device hello _ device =

11 {

12.name = "duang ",

13.id = -1,

14.dev.release = hello_release,

15};

16

17

18staticinthello_init( void)

19 {

20 printk(" hello _ init n ");

21 return platform _ device _ register(& amp;hello _ device);

22

23}

24 staticvodihello _ exit(void)

25 {

26 printk(" hello _ exit n ");

27 platform _ device _ unregister(& amp;hello _ device);

28return

29}

30MODULE _ LICENSE(" GPL ");

31 module _ init(hello _ init);

32 module _ exit(hello _ exit);

本程序仅用于测试平台框架是否能成功匹配,struct platform _ device hello _ device不设置任何硬件信息。

Makfile

1 fneq($(KERNELREESON),)

2 bj-m:= device . o driver . o

3else

4KDIR:=/lib/modules/$(shell uname-r)/build

5PWD :=$(shell pwd)

6所有:

7make -C $(KDIR) M=$(PWD)模块

8清洁:

9rm -f *。ko *。o *.mod.o *。symvers *。cmd *.mod.c *。顺序

10endif

makefile可以同时将两个c文件编译成ko文件。

编译:

编辑和翻译

编译生成的文件:

在此插入图片描述

输入程序片

清除日志信息

sudo dmesg -c

匹配成功示例2

硬件信息添加到结构platform_device中,可以在内核中读出。在本例中,以下信息被添加到hello_device结构中:

基址寄存器地址0x139d0000,该地址的空间为0x4

中断号199【注意】在实际内核中,会根据HW id从外设的中断号中计算出一个新的中断号(通常在soc厂商设备soc时会为每个中断源定义一个唯一的id),这个中断号会被cpu识别。

device.c

structure resources

结果显示探针功能正确读取硬件信息。

4.platform_device是如何管理的?1.没有设备树

在没有设备树的情况下,以三星Cortex-A8 s5pc100为例,硬件信息放置在以下位置

archarmmach-s5pc 100 mach-smdkc 100 . c

archarmplat-samsung

注册平台_设备

平台_设备定义

这个数组存储内核启动时需要初始化的硬件信息。

2.如果有设备树,

内核会有完整的设备初始化代码,在内核启动的时候会解析初始化设备树信息,将硬件信息初始化到对应的链表中。总线匹配成功后,硬件信息将传递给探针功能。

四、与总线1相关的其他知识点。内核总线相关结构变量

内核维护的所有总线都需要注册一个结构如下的变量。

structbus_type{

constchar * name

constchar * dev _ name

structdevice * dev _ root

struct device _ attribute * dev _ attrs;/*改用dev _ groups

construct attribute _ group * * bus _ groups;

construct attribute _ group * * dev _ groups;

construct attribute _ group * * drv _ groups;

int(*match)(struct device *dev,struct device _ driver * drv);

int(*uevent)(struct device *dev,struct kobj _ uevent _ env * env);

int(* probe)(struct device * dev);

int(* remove)(struct device * dev);

void(* shut down)(struct device * dev);

int(* online)(struct device * dev);

int(* offline)(struct device * dev);

int(*suspend)(struct device *dev,pm _ message _ ts state);

int(* resume)(struct device * dev);

conststructdev _ pm _ ops * pm

structiommu _ ops * iommu _ ops

struct subsys _ private * p;

structlock _ class _ keylock _ key

};

平台总线变量struct bus _ type的定义平台总线_ type定义如下:

struct bus _ type platform _ bus _ type = {

。name = "平台"、

。dev_groups = platform_dev_groups,

。match = platform_match,

。uevent = platform_uevent,

。pm = & ampplatform_dev_pm_ops,

};

最重要的成员是**。匹配**。

当一个设备的硬件信息注册在platform_bus_type总线上时,它会遍历平台总线维护的所有驱动程序,并按名称进行匹配。如果二者相同,说明硬件信息与驱动匹配,驱动的platform _ driver会被调用->: Probe函数,初始化驱动的所有资源,让驱动生效。

当一个设备驱动在platform_bus_type总线上注册时,它会遍历平台总线维护的所有硬件信息,并按名称进行匹配。如果相同,说明硬件信息与驱动匹配,驱动的platform _ driver会被调用->: Probe函数,初始化驱动的所有资源,让驱动生效。

注册位置

driversbasePlatform.c

平台_总线_类型五注册.注册码流程详解

该架构的优势在于它可以帮助我们定位问题

1.什么时候调用match函数?2.何时调用探测函数

以下是上述两个问题代码的调用过程:

代码调用过程返回搜狐查看更多

负责编辑:


以上就是详细教Linux驱动10平台总线澳洋科技股票的全部内容了,喜欢我们网站的可以继续关注市盈率公式其他的资讯!

相关推荐

翱翔新高,明天的目标!
今天指数创造了大阳线。三大指数盘中均创新高,量能也恢复到一万亿以上。画资金的主要攻击方向仍然是控股集团,如面板二人组TCL科技、...
南戈壁-S(01878)前三季度业绩由盈利转为亏损,达1786.2万美元
原标题:南戈壁-S(01878)前三个季度扭亏为盈至1786.2万美元智通金融APP新闻,南戈壁-S(01878)发布截至202...
中银智能制造001476基金历史净值周转率如何
中银智能制造001476基金历史净值,漳州资金配置公司哪些公司比较正规可靠?把自己放在市场的主位,想想他怎么想的,急的话可以砍价...
当我醒来时,枪声响起,一场更大的风暴正在美国来临!
这一次,大量人员被捕,两名警察倒在血泊中。更多的眼泪和风暴即将来临。综合媒体报道,最新事件,脉络大致如下。1.重点城市是肯塔基州...
国家社科“九五”五波理论abc三波特征
国家社科九五CICC证券账户有没有下载的应用软件?对于股票投资者来说,他们都希望自己能选择一只领先的股票,尤其是在加入资本配置和...
金源期货京顺长城内需二号混合(260109)基金净值
如何进行原油期货套利交易我们听说过原油期货的套利交易,也知道套利是指投资者选择同时买卖两个不同的期货合约,交易者可以从两个合约的...
迪瑞医疗(300396)的股市,在互联网证券开户。
近年来,a股市场的一些概念股不断被炒作。经历了化工、钢结构等概念股的炒作后,盐业概念股也逆市上涨。盐库存是什么?每个人都需要知道...
后浦基金如何逆转kdj指标的应用
厚朴基金泉州期货账户哪个期货公司服务好?我们在网上开一个融资平台网站,里面很多项目可能是不一样的,因为他们在不同平台上推出的项目...
结果查询黄骅证券哪个证券公司服务好?
结果:甘肃哪家配股公司资金雄厚?如果你想在北京投资,你必须有一个正确的态度。在北京股市,盈利多的人不一定技术高,但大多数人态度好...

友情链接