你知道Linux获取设备树源文件(DTS)里的资源?

来源:
导读 大家好,我是本期栏目编辑小友,现在为大家讲解你知道Linux获取设备树源文件(DTS)里的资源?问题。 当linux使用platform_driver_register(

大家好,我是本期栏目编辑小友,现在为大家讲解你知道Linux获取设备树源文件(DTS)里的资源?问题。

当linux使用platform_driver_register()注册platform_driver时,需要知道platform_driver的probe()中设备的中断号和内存地址。这些资源的描述信息存储在资源数据结构中,相同的资源存储在由父节点、兄弟节点和子节点连接的树形数据结构中。比如中断资源、IO端口资源、IO内存资源、DMA资源等都有不同的资源树。使用Linux结构资源描述解析结构资源{ resource _ size _ tstart//资源范围resource_size_t结束的开始;//资源范围结束常量字符*名称;//资源所有者名称无符号长标志;//资源属性ID结构资源*父,*同级,*子;//资源树的父节点、兄弟节点和字节点指针};资源大小由系统确定为uint32_t或uint64_t.在平台机制中,platform_get_resource()用于获取指定的资源类型。例如,获取所需的中断号,irq=platform_get_irq(pdev,0);int platform _ get _ IRQ(struct platform _ device * dev,无符号int num){ struct resource * r=platform _ get _ resource(dev,IORESOURCE_IRQ,num);返回r?r-start :-ENXIO;} EXport _ SYMBOL _ GPL(platform _ get _ IRQ);Platform_get_irq()返回一个start,这是一个可用的中断号。然后可以使用request_irq()注册中断服务功能。比如想获取IO内存资源:struct resource * RES _ mem=platform _ get _ resource(pdev,IO resource _ mem,0);可以得到一个IO内存资源节点指针,包括地址的起始地址和结束地址等。IO内存的长度可以通过resource_size()获得,但是这个资源只是一个descriptIOn。如果你真的想使用这个io内存,你需要先应用,然后映射它。例如,可以使用devm_request_mem_region()来申请这个IO内存,然后可以使用ioremap()将其映射到用户空间。devm _ request _ mem _ region(pdev-dev,res_mem-start,resource_size(res_mem),RES _ mem-name))addr _ start=iore map(RES _ mem-start,resource _ size(RES _ mem));ioremap()的返回值是资源的虚拟地址。IO内存资源在设备树源文件中给出(以结尾。dts)。那个。dts文件用于描述目标板的硬件信息。启动uboot后,使用uboot提供的特定API获取,如fdt_getprop()和fdt_path_offset(),这些API包含在uboot的头文件中。Uboot解析。然后给相应的寄存器赋值。linux启动后,这些给定的资源可以通过使用platform_get_resource()获得,并在驱动程序中使用。例如,中gpio资源的描述。dts文件:GPIO : GPIO-控制器@ 10700000800 { # GPIO-cells=;兼容='cavium,oct eon-3860-gpio ';reg=;gpio控制器;……根据其descriptIOn可知,gpio控制器的io内存起始地址为0x107900000800。长度为0x100,即从0x107900000800到0x1079000008ff。使用目标板中的cat/proc/ioem,可以看到:107000000800-1070000008 ff :/SOC @ 0/Gpio-controller @ 1070000000800 I2C的描述:twsi 0: I2C @ 11800000001000 { # address-cells=;# size-cells=;compaTIble='cavium,oct eon-3860-twsi ';reg=;中断=;时钟速率=;IO内存起始地址为0x118000001000,长度为0x200,从0x118000001000到0x1180000011ff。在目标板中使用cat/proc/ioem,可以看到:118000001000-1180000011 ff 3360/SOC @ 0/。

2em; text-align: center;">

在linux使用platform_driver_register() 注册 platform_driver 时, 需要在 platform_driver 的probe() 里面知道设备的中断号, 内存地址等资源。 这些资源的描述信息存放在 resource 数据结构中, 相同的资源存放在一个树形树形数据结构中, 通过父节点, 兄弟节点, 子节点相连。 比如中断资源, IO端口资源, IO内存资源, DMA资源有不同资源树。 Linux使用 struct resource 来描述一个resouce struct resource { resource_size_t start; //资源范围的开始 resource_size_t end; //资源范围的结束 const char *name; //资源拥有者名 unsigned long flags; //资源属性标识 struct resource *parent, *sibling, *child; //资源树的父节点, 兄弟节点, 字节点指针 }; resource_size_t 由系统决定 为uint32_t 或uint64_t 。 在platform机制里, 使用platform_get_resource()来获取指定的资源类型。 比如获取想获取中断号, irq = platform_get_irq(pdev, 0); int platform_get_irq(struct platform_device *dev, unsigned int num) { struct resource *r = platform_get_resource(dev, IORESOURCE_IRQ, num); return r ? r->start : -ENXIO; } EXPORT_SYMBOL_GPL(platform_get_irq); platform_get_irq() 会返回一个start, 即可用的中断号。 之后便可使用request_irq() 来注册中断服务函数。 再比如想要获取IO内存资源: struct resource *res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); 即可得到一个IO内存资源节点指针, 包括了地址的开始,结束地址等, 该IO内存的长度可用 resource_size() 来获取, 但这段资源只是一个描述, 想真正使用这段IO内存, 还要经过先申请, 再映射的过程。例如可使用devm_request_mem_region()申请出使用这段IO内存, 再使用ioremap() 将其映射出来, 供用户空间使用。 devm_request_mem_region(&pdev->dev, res_mem->start, resource_size(res_mem), res_mem->name)) addr_start = ioremap(res_mem->start, resource_size(res_mem)); ioremap() 的返回值即为该资源的虚拟地址。 IO内存的资源是在设备树源(Device Tree Source)文件(以.dts结尾)里给出的,.dts文件就是用来描述目标板硬件信息的, 在uboot启动后, 使用uboot提供的特定API将其获取出来, 如fdt_getprop(), fdt_path_offset(), 这些API包含在uboot 的头文件 里面。 uboot将.dts文件里的描述解析出来, 再对相应寄存器赋值, 在linux启动后, 使用 platform_get_resource() 即可获取到这些给定的资源, 在驱动里使用。 例如一个在.dts文件中关于gpio资源的描述: gpio: gpio-controller@1070000000800 { #gpio-cells = ; compaTIble = "cavium,octeon-3860-gpio"; reg = ; gpio-controller; … 根据其描述, 可知道gpio控制器的IO内存起始地址为:0x107900000800, 长度为0x100. 即从 0x107900000800 到 0x1079000008ff. 在目标板里使用 cat /proc/iomem 可以看到: 1070000000800-10700000008ff : /soc@0/gpio-controller@1070000000800 关于i2c 的描述: twsi0: i2c@1180000001000 { #address-cells = ; #size-cells = ; compaTIble = "cavium,octeon-3860-twsi"; reg = ; interrupts = ; clock-rate = ; IO内存起始地址为: 0x118000001000, 长度为0x200. 从 0x118000001000 到 0x1180000011ff. 在目标板里使用 cat /proc/iomem 可以看到: 1180000001000-11800000011ff : /soc@0/i2c@1180000001000

 

标签:

版权声明:转载此文是出于传递更多信息之目的。若有来源标注错误或侵犯了您的合法权益,请作者持权属证明与本网联系,我们将及时更正、删除,谢谢您的支持与理解。