ARM32 ARM64 的设备树匹配及兼容ATAGS

arm32 arm64 u-boot 加载 linux的命令 bootm

  • arm64 linux 被加载的情况
  • bootm的命令
  bootm <uImage_addr>                            // 无设备树,bootm 0x30007FC0
  bootm <uImage_addr> <initrd_addr> <dtb_addr>   // 有设备树 
---
  nand read.jffs2 0x30007FC0 kernel;     // 读内核uImage到内存0x30007FC0
  nand read.jffs2 32000000 device_tree;  // 读dtb到内存32000000
  bootm 0x30007FC0 - 0x32000000          // 启动, 没有initrd时对应参数写为"-"

arm32 arm64 的 kernel_entry

---
//arm64 的 kernel_entry
arch/arm/lib/bootm.c // arm64架构对应的u-boot代码也是走arm目录
	armv8_switch_to_el2 (images->ft_addr, NULL, NULL, NULL); //从uboot跳到执行kernel,第一个参数就是fdt的地址
---
//arm32 的 kernel_entry
arch/arm/lib/bootm.c
	kernel_entry(0, machid, r2); // r2 中为 atags 或者 fdt 的地址


arm32和arm64 在 kernel_entry时 的区别
	1. arm32的参数分别是 0 , board number , atags addr(fdt addr)
		// board number 和多个MD中的nr匹配,唯一确定一个 MD 结构体
		// atags addr 可用于传递参数
			// cmdline atag 
			// mem atag
	2. arm32的参数分别是 0 , board number , fdt addr
		// 首先检测fdt中的数据是不是设备树.如果是,board number 被弃之不用
		// "唯一的dtb addr 对应的 dtb中的 compatible 属性的值" 与 "多个 DT_MACHINE_START 中的 dt_compat" 匹配,"唯一确定一个MD结构体"
		// dtb 中的节点用于传递参数
			// chosen节点可以用来传递参数 cmdline , 对应arm32的 cmdline atag 
			// memory 节点可以用来传递 mem , 对应arm32 的 mem atag
	3. arm64的参数分别是 dbt addr , 0 , 0 , 0
		// "唯一的dtb addr 对应的 dtb中的 compatible 属性的值" 与 "多个 DT_MACHINE_START 中的 dt_compat" 匹配,"唯一确定一个MD结构体"
		// dtb 中的节点用于传递参数
			// chosen节点可以用来传递参数 cmdline , 对应arm32的 cmdline atag 
			// memory 节点可以用来传递 mem , 对应arm32 的 mem atag
	4. arm64 不支持 atags

设备树对引导linux的影响

  • arm32 对 atags 和 dbt 的兼容
	
arm32 对 atags 和 dbt 的兼容
	setup_arch
		mdesc = setup_machine_fdt(atags_vaddr);
		if (!mdesc) mdesc = setup_machine_tags(atags_vaddr, __machine_arch_type);
		if (!mdesc) while(1);

  • DT_MACHINE_START 和 MACHINE_START 的区别
// 没有一个 machine number 能与 DT_MACHINE_START  匹配
// 能匹配 machine number 的 只有 MACHINE_START 

// 没有一个 MACHINE_START 能与 dtb 匹配
// 能匹配 dtb 的只有 DT_MACHINE_START 

DT_MACHINE_START 和 MACHINE_START 基本相同,
只是.nr 的设置不同,在 DT_MACHINE_START 里面直接将.nr 设置为~0(0xffffffff)
说明引入设备树以后不会再根据 machine id 来检查 Linux 内核(是否支持某个设备了,即匹配某个设备的MD,即MACHINE_START )
而是根据设备树中的内容匹配 MD(即DT_MACHINE_START)

实例

linux/u-boot  对 smdk6410 板子 支持 了 atags 和 设备树
				
	1. atags
		MD		:	arch/arm/mach-s3c/mach-smdk6410.c 中的 MACHINE_START(SMDK6410, "SMDK6410")
		atags 	:	u-boot去设置 atags , 这里要去看 u-boot 的代码
		atags的传递	: 要看 u-boot的代码
	2. 设备树
		MD 		: 	arch/arm/mach-s3c/mach-s3c64xx-dt.c 中的 DT_MACHINE_START(S3C6400_DT, "Samsung S3C64xx (Flattened Device Tree)")
		fdt		: 	arch/arm/boot/dts/s3c6410-smdk6410.dts
		fdt的传递 	: 要看 u-boot 的代码

设备树编译

set -e;
mkdir -p include/config/;
trap "rm -f include/config/.kernel.release.tmp" EXIT;

{ echo "5.11.0$(sh ./scripts/setlocalversion .)"; } > include/config/.kernel.release.tmp;

if [ ! -r include/config/kernel.release ] || ! cmp -s include/config/kernel.release include/config/.kernel.release.tmp; then
	: '  UPD     include/config/kernel.release';
	mv -f include/config/.kernel.release.tmp include/config/kernel.release;
fi

make -f ./scripts/Makefile.build obj=scripts/basic
rm -f .tmp_quiet_recordmcount
make -f ./scripts/Makefile.build obj=scripts/dtc
make -f ./scripts/Makefile.build obj=arch/arm/boot/dts

gcc -E -Wp,-MMD,arch/arm/boot/dts/.s3c6410-smdk6410.dtb.d.pre.tmp -nostdinc -I./scripts/dtc/include-prefixes -undef -D__DTS__ -x assembler-with-cpp -o arch/arm/boot/dts/.s3c6410-smdk6410.dtb.dts.tmp arch/arm/boot/dts/s3c6410-smdk6410.dts ;
	// arch/arm/boot/dts/s3c6410-smdk6410.dts : 设备树源文件 
	// arch/arm/boot/dts/.s3c6410-smdk6410.dtb.dts.tmp 为展开后的文件
./scripts/dtc/dtc -O dtb -o arch/arm/boot/dts/s3c6410-smdk6410.dtb -b 0 -iarch/arm/boot/dts/ -i./scripts/dtc/include-prefixes -Wno-interrupt_provider -Wno-unit_address_vs_reg -Wno-unit_address_format -Wno-avoid_unnecessary_addr_size -Wno-alias_paths -Wno-graph_child_address -Wno-simple_bus_reg -Wno-unique_unit_address -Wno-pci_device_reg  -d arch/arm/boot/dts/.s3c6410-smdk6410.dtb.d.dtc.tmp arch/arm/boot/dts/.s3c6410-smdk6410.dtb.dts.tmp ;
	// arch/arm/boot/dts/.s3c6410-smdk6410.dtb.d.dtc.tmp : 依赖顺序文件
	// arch/arm/boot/dts/s3c6410-smdk6410.dtb : 设备树 编译后的 输出文件
cat arch/arm/boot/dts/.s3c6410-smdk6410.dtb.d.pre.tmp arch/arm/boot/dts/.s3c6410-smdk6410.dtb.d.dtc.tmp > arch/arm/boot/dts/.s3c6410-smdk6410.dtb.d

如何展开一个设备树文件

编译设备树的时候自会展开,gcc 用预处理过程做的

源文件
arch/arm/boot/dts/s3c6410-smdk6410.dts
展开的文件名如下
arch/arm/boot/dts/.s3c6410-smdk6410.dtb.dts.tmp

设备树中的节点

https://github.com/lisider/linux_4.0/blob/4d917d76df265d351201b4908c71ff9c0e77ec3c/arch/arm/boot/dts/vexpress-v2p-ca9.dts
挂在根节点下面的compatible非空节点 不是 amba节点,就是platform 节点 ,该节点为 platform 节点
	没有 compatible属性 的节点不会被解析成 device_node  , 无效节点
	compatible =  "arm,primecell"; 的节点 会被解析为 会被 解析为 amba总线的节点
	其他的compatible非空 节点 为 platform 节点

节点 compatible 属性 为 "simple-bus" 等字符串 的 节点 下面挂载的 都是 platform 节点 // 这个效果等价于 根节点

其他节点
	被匹配为i2c 控制器的节点(一般为platform节点)下面的节点为i2c节点(被匹配为i2c设备)
	被匹配为spi 控制器的节点(一般为platform节点)下面的节点为spi节点(被匹配为spi设备)
	

你可能感兴趣的:(ok6410开发板,arm开发,linux,运维)