[Uboot 基础] -- 第四课:u-boot 对设备树的支持

在线课堂:https://www.100ask.net/index(课程观看)
论 坛:http://bbs.100ask.net/(学术答疑)
开 发 板:https://100ask.taobao.com/ (淘宝)
https://weidongshan.tmall.com/(天猫)
交流群一:QQ群:869222007(鸿蒙开发/Linux/嵌入式/驱动/资料下载)
交流群二:QQ群:536785813(单片机-嵌入式)
公 众 号:百问科技


前言:

本文转自韦东山老师的相关文章,原文链接:第四课:u-boot对设备树的支持

一、传递 dtb 给内核

先把设备树文件读到内存,在启动内核时把设备树的地址写到 R2 寄存器中。

1.1、u-boot 中内核启动命令:

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时对应参数写为"-"

1.2、bootm 命令怎么把 dtb_addr 写入 R2 寄存器传给内核?

在百度搜索 ARM 程序调用规则(ATPCS)

写一个 C 函数 c_function(p0, p1, p2) //p0 => r0,p1 => r1,p2 => r2 (3个参数分别保存到相应的寄存器)。

定义函数指针 the_kernel,指向内核的启动地址,然后执行:the_kernel(0, machine_id, 0x32000000);

armlinux.c 中:

     /* 100ask for device tree, no initrd image used */
	if (argc == 4) {
		//第三个参数0x32000000就是设备树地址
		of_flat_tree = (char *) simple_strtoul(argv[3], NULL, 16);

		if  (be32_to_cpu(*(ulong *)of_flat_tree) == OF_DT_HEADER) {
			printf ("\nStarting kernel with device tree at 0x%x...\n\n", of_flat_tree);

			cleanup_before_linux ();
			//把dtb的地址传到r2寄存器里			
			theKernel (0, bd->bi_arch_number, of_flat_tree);
					
		} else {
			printf("Bad magic of device tree at 0x%x!\n\n", of_flat_tree);
		}
		
	}

1.3、dtb_addr 可以随便选吗?

  1. 不要破坏 u-boot 本身;
  2. 不要挡内核的路:内核本身的空间不能占用,内核要用到的内存区域也不能占用;

内核启动时一般会在它所处位置的下边防止页表,这块空间(一般是 0x400 即 16K 字节)不能被占用。

                     ------------------------------
  0x33f80000       ->|    u-boot                  | 分析lds链接文件
                     ------------------------------
                     |    u-boot所使用的内存(栈等)|
                     ------------------------------
                     |                            |
                     |                            |
                     |        空闲区域            |
                     |                            |
                     |                            |
                     |                            |
                     |                            |
                     ------------------------------
  0x30008000       ->|      zImage                |
                     ------------------------------  uImage = 64字节的头部+zImage
  0x30007FC0       ->|      uImage头部            |
                     ------------------------------
  0x30004000       ->|      内核创建的页表        |  head.S
                     ------------------------------
                     |                            |
                     |                            |
              -----> ------------------------------
              |
              |
              --- (内存基址 0x30000000)

我如何知道内核放在 0x30008000?

在内核目录下执行 mkimage -l arch/arm/boot/uImage

命令示例:

a、可以启动:

nand read.jffs2 30000000 device_tree
nand read.jffs2 0x30007FC0 kernel
bootm 0x30007FC0 - 30000000

b、不可以启动:内核启动时会使用 0x30004000 的内存来存放页表,dtb 会被破坏

nand read.jffs2 30004000 device_tree
nand read.jffs2 0x30007FC0 kernel
bootm 0x30007FC0 - 30004000

猜你喜欢

转载自blog.csdn.net/u014674293/article/details/115214787