概念:
- FDT:Flattened Device Tree (扁平设备树)是一种数据结构,用来描述设备的硬件配置信息,它源自开放固件使用的设备树格式。
 - DTS:Device tree source(设备树源)是一个文本文件,以人类可读的形式描述了计算机系统的硬件资源
 - DTB:Device tree blob 它是由DTS文本文件编译生成的二进制文件
 
设备树的引入是为了解决linux kernel越来越臃肿的问题
设备树特点:
在设备树dts文件指定硬件资源,dts被编译为dtb文件, 在启动单板时,U-boot会将dtb文件传给内核,使得驱动程序与硬件分离,我们只需要修改dts文件,便能实现需求。这就是设备树易于扩展,硬件有变动时不需要重新编译内核或驱动程序,只需要提供不一样的dtb文件。
而对于传统字符驱动的编写有两种方式:
- 一是在驱动程序中,直接写死硬件资源,如:GPIO、寄存器地址、中断号等,使得硬件改动时,必须修改驱动程序。
 - 二是采用总线驱动platform模型,将硬件资源与驱动软件分离,在platform_device中描述硬件资源,arch/arm/mach-xxx对应的文件,便是以platform_device描述各自CPU对应的硬件资源;在platform_driver中分配/设置/注册 file_operations结构体, 并从platform_device获得硬件资源。这种编写方式使得驱动易于扩展,硬件改动时只需修改platform_device或者platform_driver,这就导致linux内核产生大量的冗余代码。
 
要将FDT信息传递给kernel有两种方式:FDT兼容TAG模式和FDT取代TAG模式
(一)FDT兼容TAG
(1)内核配置
使能CONFIG_ARM_APPENDED_DTB功能,该功能是将DTB文件拼接到uImage的后面
  
   - 
    
     
    
    
     
       500 
      #
     
    
 
   - 
    
     
    
    
     
       501 
      # Boot options
     
    
 
   - 
    
     
    
    
     
       502 
      #
     
    
 
   - 
    
     
    
    
     
       503 CONFIG_USE_OF=y
     
    
 
   - 
    
     
    
    
     
       504 CONFIG_ATAGS=y
     
    
 
   - 
    
     
    
    
     
       505 
      # CONFIG_DEPRECATED_PARAM_STRUCT is not set
     
    
 
   - 
    
     
    
    
     
       506 
      # CONFIG_BUILD_ARM_APPENDED_DTB_IMAGE is not set                                                                              
     
    
 
   - 
    
     
    
    
     
       507 CONFIG_ZBOOT_ROM_TEXT=0
     
    
 
   - 
    
     
    
    
     
       508 CONFIG_ZBOOT_ROM_BSS=0
     
    
 
   - 
    
     
    
    
     
       509 CONFIG_ARM_APPENDED_DTB=y
     
    
 
   - 
    
     
    
    
     
       510 CONFIG_ARM_ATAG_DTB_COMPAT=y
     
    
 
   - 
    
     
    
    
     
       511 CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_FROM_BOOTLOADER=y
     
    
 
   - 
    
     
    
    
     
       512 
      # CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEND is not set
     
    
 
   - 
    
     
    
    
     
       513 CONFIG_CMDLINE=
      ""
     
    
 
   - 
    
     
    
    
     
       514 
      # CONFIG_KEXEC is not set
     
    
 
   - 
    
     
    
    
     
       515 
      # CONFIG_CRASH_DUMP is not set
     
    
 
   - 
    
     
    
    
     
       516 CONFIG_AUTO_ZRELADDR=y
     
    
 
  
 
(2)构建zImage-dtb
  
   - 
    
     
    
    
     
      #arch/arm/boot/Makefile
     
    
 
   - 
    
     
    
    
     
       68 $(obj)/zImage-dtb:  $(obj)/zImage $(DTB_OBJS) FORCE
     
    
 
   - 
    
     
    
    
     
       69     $(call if_changed,cat)
     
    
 
   - 
    
     
    
    
     
       70     @
      echo 
      '  Kernel: $@ is ready'
     
    
 
  
 
实际执行的命令是:
  
   - 
    
     
    
    
     
       cmd_arch/arm/boot/zImage-dtb := (cat arch/arm/boot/zImage arch/arm/boot/dts/hi3520dv400-demb.dtb > arch/arm/boot/zImage-dtb) ||
     
    
 
   - 
    
     
    
    
     
           (rm -f arch/arm/boot/zImage-dtb; 
      false)  
     
    
 
  
 
将arch/arm/boot/dts/hi3520dv400-demb.dtb拼接到arch/arm/boot/zImage的后面生成arch/arm/boot/zImage-dtb文件。
(3)参数转换
在内核自解压阶段,自解压程序会去判断是否有设备的存在(通过设备树魔术判断),然后在再读取设备树大小等信息。然后将设备树指针保存到r2寄存器中去。
  
   - 
    
     
    
    
     
      #linux/arch/arm/boot/compressed/head.S    
     
    
 
   - 
    
     
    
    
     
          /*设备树相关的操作*/
     
    
 
   - 
    
     
    
    
     
              mov    r5, 
      #0            @ init dtb size to 0
     
    
 
   - 
    
     
    
    
     
              
     
    
 
   - 
    
     
    
    
     
      #ifdef CONFIG_ARM_APPENDED_DTB
     
    
 
   - 
    
     
    
    
     
      /*
     
    
 
   - 
    
     
    
    
     
       *   r0  = delta
     
    
 
   - 
    
     
    
    
     
       *   r2  = BSS start
     
    
 
   - 
    
     
    
    
     
       *   r3  = BSS end
     
    
 
   - 
    
     
    
    
     
       *   r4  = final kernel address (possibly with LSB 
      set)
     
    
 
   - 
    
     
    
    
     
       *   r5  = appended dtb size (still unknown)
     
    
 
   - 
    
     
    
    
     
       *   r6  = _edata
     
    
 
   - 
    
     
    
    
     
       *   r7  = architecture ID
     
    
 
   - 
    
     
    
    
     
       *   r8  = atags/device tree pointer
     
    
 
   - 
    
     
    
    
     
       *   r9  = size of decompressed image
     
    
 
   - 
    
     
    
    
     
       *   r10 = end of this image, including  bss/stack/malloc space 
      if non XIP
     
    
 
   - 
    
     
    
    
     
       *   r11 = GOT start
     
    
 
   - 
    
     
    
    
     
       *   r12 = GOT end
     
    
 
   - 
    
     
    
    
     
       *   sp  = stack pointer
     
    
 
   - 
    
     
    
    
     
       *
     
    
 
   - 
    
     
    
    
     
       * 
      if there are device trees (dtb) appended to zImage, advance r10 so that the
     
    
 
   - 
    
     
    
    
     
       * dtb data will get relocated along with the kernel 
      if necessary.
     
    
 
   - 
    
     
    
    
     
       */
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
     
              ldr    lr, [r6, 
      #0]
     
    
 
   - 
    
     
    
    
     
      #ifndef __ARMEB__
     
    
 
   - 
    
     
    
    
     
              ldr    r1, =0xedfe0dd0        @ sig is 0xd00dfeed big endian
     
    
 
   - 
    
     
    
    
     
      #else
     
    
 
   - 
    
     
    
    
     
              ldr    r1, =0xd00dfeed     /**海思使用的是小端模式**/
     
    
 
   - 
    
     
    
    
     
      #endif
     
    
 
   - 
    
     
    
    
     
              cmp    lr, r1                /* 通过魔术字来判断是否内核镜像后有 DTB */
     
    
 
   - 
    
     
    
    
     
              bne    dtb_check_done        @ not found
     
    
 
   - 
    
     
    
    
     
              
     
    
 
   - 
    
     
    
    
     
      #ifdef CONFIG_ARM_ATAG_DTB_COMPAT
     
    
 
   - 
    
     
    
    
     
              /*
     
    
 
   - 
    
     
    
    
     
               *如果确实在zImage上附加了DTB,并且确实有ATAG列表,
     
    
 
   - 
    
     
    
    
     
               *我们希望将后者翻译成此处的前者。 
     
    
 
   - 
    
     
    
    
     
               *为了安全起见,让我们暂时将堆栈移到malloc区域。 
     
    
 
   - 
    
     
    
    
     
               *尚未发生GOT修正,但我们要调用的代码均未使用任何全局变量。
     
    
 
   - 
    
     
    
    
     
              */
     
    
 
   - 
    
     
    
    
     
              
     
    
 
   - 
    
     
    
    
     
              add    sp, sp, 
      #0x10000
     
    
 
   - 
    
     
    
    
     
              stmfd    sp!, {r0-r3, ip, lr}
     
    
 
   - 
    
     
    
    
     
              mov    r0, r8
     
    
 
   - 
    
     
    
    
     
              mov    r1, r6
     
    
 
   - 
    
     
    
    
     
              sub    r2, sp, r6
     
    
 
   - 
    
     
    
    
     
              bl    atags_to_fdt
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
     
              /*
     
    
 
   - 
    
     
    
    
     
               * If returned value is 1, there is no ATAG at the location
     
    
 
   - 
    
     
    
    
     
               * pointed by r8.  Try the typical 0x100 offset from start
     
    
 
   - 
    
     
    
    
     
               * of RAM and hope 
      for the best.
     
    
 
   - 
    
     
    
    
     
               */
     
    
 
   - 
    
     
    
    
     
              cmp    r0, 
      #1
     
    
 
   - 
    
     
    
    
     
              sub    r0, r4, 
      #TEXT_OFFSET
     
    
 
   - 
    
     
    
    
     
              bic    r0, r0, 
      #1
     
    
 
   - 
    
     
    
    
     
              add    r0, r0, 
      #0x100
     
    
 
   - 
    
     
    
    
     
              mov    r1, r6
     
    
 
   - 
    
     
    
    
     
              sub    r2, sp, r6
     
    
 
   - 
    
     
    
    
     
              bleq    atags_to_fdt
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
     
              ldmfd    sp!, {r0-r3, ip, lr}
     
    
 
   - 
    
     
    
    
     
              sub    sp, sp, 
      #0x10000
     
    
 
   - 
    
     
    
    
     
      #endif
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
     
              /* r6 指向的是设备树的地址 也是 _edata
     
    
 
   - 
    
     
    
    
     
               * 此时 r8 指向了设备树,
     
    
 
   - 
    
     
    
    
     
               * 在下面跳转至解压后的内存执行时
     
    
 
   - 
    
     
    
    
     
               * mov    r2, r8            @ restore atags pointer
     
    
 
   - 
    
     
    
    
     
               * 从而 r8 指向的设备树会直接传递进内核
     
    
 
   - 
    
     
    
    
     
              */
     
    
 
   - 
    
     
    
    
     
              mov    r8, r6            @ use the appended device tree
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
     
              /*
     
    
 
   - 
    
     
    
    
     
               * Make sure that the DTB doesn
      't end up in the final
     
    
 
   - 
    
     
    
    
     
               * kernel's .bss area. To 
      do so, we adjust the decompressed
     
    
 
   - 
    
     
    
    
     
               * kernel size to compensate 
      if that .bss size is larger
     
    
 
   - 
    
     
    
    
     
               * than the relocated code.
     
    
 
   - 
    
     
    
    
     
               */
     
    
 
   - 
    
     
    
    
     
               
     
    
 
   - 
    
     
    
    
     
               /*
     
    
 
   - 
    
     
    
    
     
                *调整解压后的kernel大小
     
    
 
   - 
    
     
    
    
     
                *如果 _kernel_bss_size - (dtb/_edata - wont_overwrite) 大于0
     
    
 
   - 
    
     
    
    
     
                *则  size of decompressed image 会增加上面的值
     
    
 
   - 
    
     
    
    
     
                *从而使得下面 relocate 过程里, 目的地址在解压后内核的最后,
     
    
 
   - 
    
     
    
    
     
                *再往后移 _kernel_bss_size - (dtb/_edata - wont_overwrite)
     
    
 
   - 
    
     
    
    
     
                *从而使得 relocate 的代码与 kernel 的 bss有重合,但是 dtb 没有。
     
    
 
   - 
    
     
    
    
     
                *
     
    
 
   - 
    
     
    
    
     
                *如果 _kernel_bss_size - (dtb/_edata - wont_overwrite) 小于0,
     
    
 
   - 
    
     
    
    
     
                *则 relocate 的代码段(dtb/_edata - wont_overwrite)全部覆盖 kernel bss段后,
     
    
 
   - 
    
     
    
    
     
                *还会占用后面的一部分,而 dtb 还在这后面,肯定不会与 kernel bss 有重合了。
     
    
 
   - 
    
     
    
    
     
                *
     
    
 
   - 
    
     
    
    
     
                *在该代码段执行完后,relocate的代码段内存空间可以在内核启动后覆盖 即被 bss使用,
     
    
 
   - 
    
     
    
    
     
                *但是 dtb 对应的空间则不要一直保留,不能被bss初始化为全0.     
     
    
 
   - 
    
     
    
    
     
               */
     
    
 
   - 
    
     
    
    
     
              ldr    r5, =_kernel_bss_size
     
    
 
   - 
    
     
    
    
     
              adr    r1, wont_overwrite
     
    
 
   - 
    
     
    
    
     
              sub    r1, r6, r1
     
    
 
   - 
    
     
    
    
     
              subs    r1, r5, r1
     
    
 
   - 
    
     
    
    
     
              addhi    r9, r9, r1
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
     
              /**dtb 开始4字节是魔术,接下来4字节是dtb文件大小**/
     
    
 
   - 
    
     
    
    
     
              ldr    r5, [r6, 
      #4]    
     
    
 
   - 
    
     
    
    
     
      #ifndef __ARMEB__   /**ARM 设备不会进入这里**/
     
    
 
   - 
    
     
    
    
     
              /* convert r5 (dtb size) to little endian */
     
    
 
   - 
    
     
    
    
     
              eor    r1, r5, r5, ror 
      #16
     
    
 
   - 
    
     
    
    
     
              bic    r1, r1, 
      #0x00ff0000
     
    
 
   - 
    
     
    
    
     
              mov    r5, r5, ror 
      #8
     
    
 
   - 
    
     
    
    
     
              eor    r5, r5, r1, lsr 
      #8
     
    
 
   - 
    
     
    
    
     
      #endif
     
    
 
   - 
    
     
    
    
     
              /*dtb 大小设置8字节对齐*/
     
    
 
   - 
    
     
    
    
     
              /* preserve 64-bit alignment */
     
    
 
   - 
    
     
    
    
     
              add    r5, r5, 
      #7
     
    
 
   - 
    
     
    
    
     
              bic    r5, r5, 
      #7
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
     
              /* r6  = _edata  
     
    
 
   - 
    
     
    
    
     
               * r5 表示设备树的大小
     
    
 
   - 
    
     
    
    
     
               * 使得 _edata 包含了 设备树的大小,
     
    
 
   - 
    
     
    
    
     
               * 在下面 Relocate时,同时也会将设备树 Relocate
     
    
 
   - 
    
     
    
    
     
              */
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
     
              /* relocate some pointers past the appended dtb */
     
    
 
   - 
    
     
    
    
     
              add    r6, r6, r5
     
    
 
   - 
    
     
    
    
     
              add    r10, r10, r5
     
    
 
   - 
    
     
    
    
     
              
     
    
 
   - 
    
     
    
    
     
              /* 栈地址也扩大 */
     
    
 
   - 
    
     
    
    
     
              add    sp, sp, r5
     
    
 
   - 
    
     
    
    
     
      dtb_check_done:
     
    
 
   - 
    
     
    
    
     
      #endif /*end of CONFIG_ARM_APPENDED_DTB*/
     
    
 
  
 
这里需要注意一个atags_to_fdt 函数,该函数的功能是,当uboot有传递参数给kernel,同时uImage找那个也包含了设备树时,这个函数会将uboot的atags参数转换为fdt格式。
  
   - 
    
     
    
    
     
      /*/arch/arm/kernel/atags_to_fdt.c*/
     
    
 
   - 
    
     
    
    
     
      /*
     
    
 
   - 
    
     
    
    
     
       * Convert and fold provided ATAGs into the provided FDT.
     
    
 
   - 
    
     
    
    
     
       *
     
    
 
   - 
    
     
    
    
     
       * REturn values:
     
    
 
   - 
    
     
    
    
     
       *    = 0 -> pretend success
     
    
 
   - 
    
     
    
    
     
       *    = 1 -> bad ATAG (may retry with another possible ATAG pointer)
     
    
 
   - 
    
     
    
    
     
       *    < 0 -> error from libfdt
     
    
 
   - 
    
     
    
    
     
       */
     
    
 
   - 
    
     
    
    
     
      int atags_to_fdt(void *atag_list, void *fdt, int total_space)
     
    
 
   - 
    
     
    
    
     
      {
     
    
 
   - 
    
     
    
    
     
          
      struct tag *atag = atag_list;
     
    
 
   - 
    
     
    
    
     
          
      /* In the case of 64 bits memory size, need to reserve 2 cells for
     
    
 
   - 
    
     
    
    
     
           * address and size for each bank */
     
    
 
   - 
    
     
    
    
     
          
      uint32_t mem_reg_property[
      2 * 
      2 * NR_BANKS];
     
    
 
   - 
    
     
    
    
     
          
      int memcount = 
      0;
     
    
 
   - 
    
     
    
    
     
          
      int ret, memsize;
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
     
          
      /* make sure we've got an aligned pointer */
     
    
 
   - 
    
     
    
    
     
          
      if ((u32)atag_list & 
      0x3)
     
    
 
   - 
    
     
    
    
     
              
      return 
      1;
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
     
          
      /* if we get a DTB here we're done already */
     
    
 
   - 
    
     
    
    
     
          
      if (*(u32 *)atag_list == fdt32_to_cpu(FDT_MAGIC))
     
    
 
   - 
    
     
    
    
     
                 
      return 
      0;
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
     
          
      /* validate the ATAG */
     
    
 
   - 
    
     
    
    
     
          
      if (atag->hdr.tag != ATAG_CORE ||
     
    
 
   - 
    
     
    
    
     
              (atag->hdr.size != tag_size(tag_core) &&
     
    
 
   - 
    
     
    
    
     
               atag->hdr.size != 
      2))
     
    
 
   - 
    
     
    
    
     
              
      return 
      1;
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
     
          
      /* let's give it all the room it could need */
     
    
 
   - 
    
     
    
    
     
          ret = fdt_open_into(fdt, fdt, total_space);
     
    
 
   - 
    
     
    
    
     
          
      if (ret < 
      0)
     
    
 
   - 
    
     
    
    
     
              
      return ret;
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
     
          for_each_tag(atag, atag_list) {
     
    
 
   - 
    
     
    
    
     
              
      if (atag->hdr.tag == ATAG_CMDLINE) {
     
    
 
   - 
    
     
    
    
     
                  
      /* Append the ATAGS command line to the device tree
     
    
 
   - 
    
     
    
    
     
                   * command line.
     
    
 
   - 
    
     
    
    
     
                   * NB: This means that if the same parameter is set in
     
    
 
   - 
    
     
    
    
     
                   * the device tree and in the tags, the one from the
     
    
 
   - 
    
     
    
    
     
                   * tags will be chosen.
     
    
 
   - 
    
     
    
    
     
                   */
     
    
 
   - 
    
     
    
    
     
                  
      if (do_extend_cmdline)
     
    
 
   - 
    
     
    
    
     
                      merge_fdt_bootargs(fdt,
     
    
 
   - 
    
     
    
    
     
                                 atag->u.cmdline.cmdline);
     
    
 
   - 
    
     
    
    
     
                  
      else
     
    
 
   - 
    
     
    
    
     
                      setprop_string(fdt, 
      "/chosen", 
      "bootargs",
     
    
 
   - 
    
     
    
    
     
                                 atag->u.cmdline.cmdline);
     
    
 
   - 
    
     
    
    
     
              } 
      else 
      if (atag->hdr.tag == ATAG_MEM) {
     
    
 
   - 
    
     
    
    
     
                  
      if (memcount >= 
      sizeof(mem_reg_property)/
      4)
     
    
 
   - 
    
     
    
    
     
                      
      continue;
     
    
 
   - 
    
     
    
    
     
                  
      if (!atag->u.mem.size)
     
    
 
   - 
    
     
    
    
     
                      
      continue;
     
    
 
   - 
    
     
    
    
     
                  memsize = get_cell_size(fdt);
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
     
                  
      if (memsize == 
      2) {
     
    
 
   - 
    
     
    
    
     
                      
      /* if memsize is 2, that means that
     
    
 
   - 
    
     
    
    
     
                       * each data needs 2 cells of 32 bits,
     
    
 
   - 
    
     
    
    
     
                       * so the data are 64 bits */
     
    
 
   - 
    
     
    
    
     
                      
      uint64_t *mem_reg_prop64 =
     
    
 
   - 
    
     
    
    
     
                          (
      uint64_t *)mem_reg_property;
     
    
 
   - 
    
     
    
    
     
                      mem_reg_prop64[memcount++] =
     
    
 
   - 
    
     
    
    
     
                          cpu_to_fdt64(atag->u.mem.start);
     
    
 
   - 
    
     
    
    
     
                      mem_reg_prop64[memcount++] =
     
    
 
   - 
    
     
    
    
     
                          cpu_to_fdt64(atag->u.mem.size);
     
    
 
   - 
    
     
    
    
     
                  } 
      else {
     
    
 
   - 
    
     
    
    
     
                      mem_reg_property[memcount++] =
     
    
 
   - 
    
     
    
    
     
                          cpu_to_fdt32(atag->u.mem.start);
     
    
 
   - 
    
     
    
    
     
                      mem_reg_property[memcount++] =
     
    
 
   - 
    
     
    
    
     
                          cpu_to_fdt32(atag->u.mem.size);
     
    
 
   - 
    
     
    
    
     
                  }
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
     
              } 
      else 
      if (atag->hdr.tag == ATAG_INITRD2) {
     
    
 
   - 
    
     
    
    
     
                  
      uint32_t initrd_start, initrd_size;
     
    
 
   - 
    
     
    
    
     
                  initrd_start = atag->u.initrd.start;
     
    
 
   - 
    
     
    
    
     
                  initrd_size = atag->u.initrd.size;
     
    
 
   - 
    
     
    
    
     
                  setprop_cell(fdt, 
      "/chosen", 
      "linux,initrd-start",
     
    
 
   - 
    
     
    
    
     
                          initrd_start);
     
    
 
   - 
    
     
    
    
     
                  setprop_cell(fdt, 
      "/chosen", 
      "linux,initrd-end",
     
    
 
   - 
    
     
    
    
     
                          initrd_start + initrd_size);
     
    
 
   - 
    
     
    
    
     
              }
     
    
 
   - 
    
     
    
    
     
          }
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
     
          
      if (memcount) {
     
    
 
   - 
    
     
    
    
     
              setprop(fdt, 
      "/memory", 
      "reg", mem_reg_property,
     
    
 
   - 
    
     
    
    
     
                  
      4 * memcount * memsize);
     
    
 
   - 
    
     
    
    
     
          }
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
     
          
      return fdt_pack(fdt);
     
    
 
   - 
    
     
    
    
     
      }
     
    
 
  
 
(4)内核获取DTB文件地址:
1、bootloader启动内核时,会设置r0,r1,r2三个寄存器:
r0一般设置为0;
r1一般设置为machine id (在使用设备树时该参数没有被使用);
r2一般设置ATAGS或DTB的开始地址
2、通过head.S head-common.S处理,获得dtb文件指针__atags_pointer
bl __lookup_processor_type //使用汇编指令读取CPU ID, 根据该ID找到对应的proc_info_list结构体(里面含有这类 CPU 的初始化函数、信息)
bl __vet_atags //判断是否存在可用的ATAGS或DTB
bl __create_page_tables //创建页表, 即创建虚拟地址和物理地址的映射关系
b __enable_mmu //使能MMU, 以后就要使用虚拟地址了
ldr r13, =__mmap_switched //上述函数里将会调用__mmap_switched
3、//r9 = processor ID
__mmap_switched:
//缓存 r1 r2
mov r7, r1
mov r8, r2__mmap_switched_data:
.long processor_id @ r0
.long __machine_arch_type @ r1
.long __atags_pointer @ r2adr r4, __mmap_switched_data //将存储变量的地址赋给r4
4、//将u-boot传递给内核的参数r0 r1 r2 分别赋给C变量 processor_id、__machine_arch_type、__atags_pointer
ldmia r4, {r0, r1, r2, r3}
str r9, [r0] @ Save processor ID
str r7, [r1] @ Save machine type
str r8, [r2] @ Save atags pointer
(5)内核解析dtb文件匹配单板
 内核运行起来之后在
start_kernel ==> setup_arch(&command_line); ==>setup_arch==>
setup_processor();
mdesc = setup_machine_fdt(__atags_pointer);
if (!mdesc)
mdesc = setup_machine_tags(__atags_pointer, __machine_arch_type);
之后就是设备树的一些应用
(二)FDT取代TAG
- 在海思设备上默认并不支持该功能,并且因为海思自己在uboot上做的修改比较大,需要同时修改uboot与kernel才能正常启动,如果以后有机会再进行分析。
 - 它的基本原理应该是将bootargs中的参数放置到设备树中,在通过寄存器r2将设备树的地址传递给kernel,kernel起来之后通过该地址来解析设备信息。
 
参考内容:
设备树(三)—— linux内核对设备树的支持
 https://blog.csdn.net/ggxyx123/article/details/85595173
linux系统之驱动与FDT
 https://blog.csdn.net/eleven_xiy/article/details/72835181
Linux内核DTB文件启动的几种方式
 https://www.cnblogs.com/iot-yun/p/11403498.html
转载:https://blog.csdn.net/li_wen01/article/details/103584891