你了解linux device tree源代码?.doc
《你了解linux device tree源代码?.doc》由会员分享,可在线阅读,更多相关《你了解linux device tree源代码?.doc(35页珍藏版)》请在三一办公上搜索。
1、你了解linux device tree源代码?/BasedonLinux v3.14 source codeLinux设备树机制(Device Tree)一、描述ARM Device Tree起源于OpenFirmware(OF),在过去的Linux中,arch/arm/plat-xxx和arch/arm/mach-xxx中充斥着大量的垃圾代码,相当多数的代码只是在描述板级细节,而这些板级细节对于内核来讲,不过是垃圾,如板上的platform设备、resource、i2c_board_info、spi_board_info以及各种硬件的platform_data。为了改变这种局面,Linux
2、社区的大牛们参考了PowerPC等体系架构中使用的Flattened Device Tree(FDT),也采用了Device Tree结构,许多硬件的细节可以直接透过它传递给Linux,而不再需要在kernel中进行大量的冗余编码。Device Tree是一种描述硬件的数据结构,由一系列被命名的结点(node)和属性(property)组成,而结点本身可包含子结点。所谓属性,其实就是成对出现的name和value。在Device Tree中,可描述的信息包括(原先这些信息大多被hard code到kernel中):CPU的数量和类别,内存基地址和大小,总线和桥,外设连接,中断控制器和中断使用情
3、况,GPIO控制器和GPIO使用情况,Clock控制器和Clock使用情况。通常由.dts文件以文本方式对系统设备树进行描述,经过Device Tree Compiler(dtc)将dts文件转换成二进制文件binary device tree blob(dtb),.dtb文件可由Linux内核解析,有了device tree就可以在不改动Linux内核的情况下,对不同的平台实现无差异的支持,只需更换相应的dts文件,即可满足。二、相关结构体1.U-Boot需要将设备树在内存中的存储地址传给内核。该树主要由三大部分组成:头(Header)、结构块(Structure block)、字符串块(S
4、trings block)。设备树在内存中的存储布局图。-base-|struct boot_param_header|-|(alignment gap)(*)|-|memory reserve map|-|(alignment gap)|-|device-tree structure|-|(alignment gap)|-|device-tree strings|-|-(base+totalsize)1.1 头(header)头主要描述设备树的一些基本信息,例如设备树大小,结构块偏移地址,字符串块偏移地址等。偏移地址是相对于设备树头的起始地址计算的。struct boot_param_hea
5、der_be32 magic;/设备树魔数,固定为0xd00dfeed_be32 totalsize;/整个设备树的大小_be32 off_dt_struct;/保存结构块在整个设备树中的偏移_be32 off_dt_strings;/保存的字符串块在设备树中的偏移_be32 off_mem_rsvmap;/保留内存区,该区保留了不能被内核动态分配的内存空间_be32 version;/设备树版本_be32 last_comp_version;/向下兼容版本号_be32 boot_cpuid_phys;/为在多核处理器中用于启动的主cpu的物理id_be32 dt_strings_size;/
6、字符串块大小_be32 dt_struct_size;/结构块大小;1.2 结构块(struct block)设备树结构块是一个线性化的结构体,是设备树的主体,以节点node的形式保存了目标单板上的设备信息。在结构块中以宏OF_DT_BEGIN_NODE标志一个节点的开始,以宏OF_DT_END_NODE标识一个节点的结束,整个结构块以宏OF_DT_END结束。一个节点主要由以下几部分组成。(1)节点开始标志:一般为OF_DT_BEGIN_NODE。(2)节点路径或者节点的单元名(ersion=0x10以节点单元名表示)(3)填充字段(对齐到四字节)(4)节点属性。每个属性以宏OF_DT_PR
7、OP开始,后面依次为属性值的字节长度(4字节)、属性名称在字符串块中的偏移量(4字节)、属性值和填充(对齐到四字节)。(5)如果存在子节点,则定义子节点。(6)节点结束标志OF_DT_END_NODE。1.3 字符串块通过节点的定义知道节点都有若干属性,而不同的节点的属性又有大量相同的属性名称,因此将这些属性名称提取出一张表,当节点需要应用某个属性名称时直接在属性名字段保存该属性名称在字符串块中的偏移量。1.4 设备树源码 DTS 表示设备树源码文件(.dts)以可读可编辑的文本形式描述系统硬件配置设备树,支持 C/C+方式的注释,该结构有一个唯一的根节点“/”,每个节点都有自己的名字并可以包
8、含多个子节点。设备树的数据格式遵循了 Open Firmware IEEE standard 1275。这个设备树中有很多节点,每个节点都指定了节点单元名称。每一个属性后面都给出相应的值。以双引号引出的内容为 ASCII 字符串,以尖括号给出的是 32 位的16进制值。这个树结构是启动 Linux 内核所需节点和属性简化后的集合,包括了根节点的基本模式信息、CPU 和物理内存布局,它还包括通过/chosen 节点传递给内核的命令行参数信息。1.5 machine_desc结构内核提供了一个重要的结构体struct machine_desc ,这个结构体在内核移植中起到相当重要的作用,内核通过m
9、achine_desc结构体来控制系统体系架构相关部分的初始化。machine_desc结构体通过MACHINE_START宏来初始化,在代码中, 通过在start_kernel-setup_arch中调用setup_machine_fdt来获取。struct machine_descunsignedintnr;/*architecture number*/constchar*name;/*architecture name*/unsigned long atag_offset;/*tagged list(relative)*/constchar*const*dt_compat;/*array
10、of device tree*compaTIblestrings*/unsignedintnr_irqs;/*number of IRQs*/#ifdef CONFIG_ZONE_DMAphys_addr_t dma_zone_size;/*size of DMA-able area*/#endifunsignedintvideo_start;/*start of video RAM*/unsignedintvideo_end;/*endof video RAM*/unsigned char reserve_lp0:1;/*never has lp0*/unsigned char reserv
11、e_lp1:1;/*never has lp1*/unsigned char reserve_lp2:1;/*never has lp2*/enum reboot_mode reboot_mode;/*default restart mode*/struct smp_operaTIons*smp;/*SMP operaTIons*/bool(*smp_init)(void);void(*fixup)(struct tag*,char*,struct meminfo*);void(*init_meminfo)(void);void(*reserve)(void);/*reserve mem bl
12、ocks*/void(*map_io)(void);/*IO mappingfuncTIon*/void(*init_early)(void);void(*init_irq)(void);void(*init_time)(void);void(*init_machine)(void);void(*init_late)(void);#ifdef CONFIG_MULTI_IRQ_HANDLERvoid(*handle_irq)(struct pt_regs*);#endifvoid(*restart)(enum reboot_mode,constchar*);1.6 设备节点结构体struct
13、device_nodeconstchar*name;/设备nameconstchar*type;/设备类型phandle phandle;constchar*full_name;/设备全称,包括父设备名structproperty*properties;/设备属性链表structproperty*deadprops;/removed propertiesstruct device_node*parent;/指向父节点struct device_node*child;/指向子节点struct device_node*sibling;/指向兄弟节点struct device_node*next;/
14、相同设备类型的下一个节点struct device_node*allnext;/nextinlist of all nodesstruct proc_dir_entry*pde;/该节点对应的procstruct kref kref;unsigned long _flags;void*data;#ifdefined(CONFIG_SPARC)constchar*path_component_name;unsignedintunique_id;struct of_irq_controller*irq_trans;#endif;1.7 属性结构体structpropertychar*name;/属
15、性名intlength;/属性值长度void*value;/属性值structproperty*next;/指向下一个属性unsigned long _flags;/标志unsignedintunique_id;三、设备树初始化及解析分析Linux内核的源码,可以看到其对扁平设备树的解析流程如下:(1)首先在内核入口处将从u-boot传递过来的镜像基地址。(2)通过调用early_init_dt_scan()函数来获取内核前期初始化所需的bootargs,cmd_line等系统引导参数。(3)根据bootargs,cmd_line等系统引导参数进入start_kernel()函数,进行内核的第
16、二阶段初始化。(4)调用unflatten_device_tree()函数来解析dtb文件,构建一个由device_node结构连接而成的单项链表,并使用全局变量of_allnodes指针来保存这个链表的头指针。(5)内核调用OF提供的API函数获取of_allnodes链表信息来初始化内核其他子系统、设备等。/kernel 初始化的代码(init/main.c)asmlinkage void _init start_kernel(void)./这个setup_arch就是各个架构自己的设置函数,哪个参与了编译就调用哪个,arm架构应当是arch/arm/kernel/setup.c中的 se
17、tup_arch。setup_arch(.void _init setup_arch(char*cmdline_p)conststruct machine_desc*mdesc;setup_processor();/setup_machine_fdt函数获取内核前期初始化所需的bootargs,cmd_line等系统引导参数mdesc=setup_machine_fdt(_atags_pointer);/_atags_pointer是bootloader传递参数的物理地址if(!mdesc)mdesc=setup_machine_tags(_atags_pointer,_machine_arc
18、h_type);machine_desc=mdesc;machine_name=mdesc-name;if(mdesc-reboot_mode!=REBOOT_HARD)reboot_mode=mdesc-reboot_mode;init_mm.start_code=(unsigned long)_text;init_mm.end_code=(unsigned long)_etext;init_mm.end_data=(unsigned long)_edata;init_mm.brk=(unsigned long)_end;strlcpy(cmd_line,boot_command_line,
19、COMMAND_LINE_SIZE);*cmdline_p=cmd_line;parse_early_param();sort(early_paging_init(mdesc,lookup_processor_type(read_cpuid_id();setup_dma_zone(mdesc);sanity_check_meminfo();arm_memblock_init(paging_init(mdesc);request_standard_resources(mdesc);if(mdesc-restart)arm_pm_restart=mdesc-restart;/解析设备树unflat
20、ten_device_tree();.(一)函数获取内核前期初始化所需的bootargs,cmd_line等系统引导参数1.setup_machine_fdt()函数获取内核前期初始化所需的bootargs,cmd_line等系统引导参数。conststruct machine_desc*_init setup_machine_fdt(unsignedintdt_phys)conststruct machine_desc*mdesc,*mdesc_best=NULL;#ifdef CONFIG_ARCH_MULTIPLATFORMDT_MACHINE_START(GENERIC_DT,Gene
21、ric DT based system)MACHINE_ENDmdesc_best=#endif/bootloader传递参数的物理地址不为空,并将物理地址转化为虚拟地址,/通过函数early_init_dt_scan从设备树中读出bootargs,cmd_line等系统引导参数。if(!dt_phys|!early_init_dt_scan(phys_to_virt(dt_phys)returnNULL;/根据设备树中根节点属性compatible的属性描述,找到系统中定义的最匹配的machine_desc结构,该结构控制系统体系架构相关部分的初始化mdesc=of_flat_dt_matc
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 你了解linux device tree源代码? 了解 linux tree 源代码
链接地址:https://www.31ppt.com/p-4927267.html