2-内核的编译_uImag_zimage_设备树

来源:互联网 发布:pmp网络班价格 编辑:程序博客网 时间:2024/05/02 18:50
内核的编译:
  • make uImage
    • 1、在顶层目录下搜索uImage发现找不到,有可能uImage存在于其他的Makefile文件中
    • 2、include arch/arm/Makefile
    • 3、进入到arch/arm/Makefile中,寻找uImage目标

      299 BOOT_TARGETS = zImage Image xipImage bootpImage uImage
      304 $(BOOT_TARGETS): vmlinux(顶层目录下的)
      305 $(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $(boot)/$@
      boot := arch/arm/boot
    • 4、进入到arch/arm/boot目录下寻找uImage目标

      78 $(obj)/uImage: $(obj)/zImage FORCE
      79 @$(check_for_multiple_loadaddr)
      80 $(call if_changed,uimage)
      81 @$(kecho) ' Image $@ is ready'
    • 如果需要生成uImage,必须依赖zImage
    • 5、搜索目标zImage

      54 $(obj)/zImage: $(obj)/compressed/vmlinux FORCE
      55 $(call if_changed,objcopy)
    • 6、在arch/arm/boot/compressed/Makefile中寻找vmlinux目标

      185 $(obj)/vmlinux: $(obj)/vmlinux.lds $(obj)/$(HEAD) $(obj)/piggy.$(suffix_y).o \
      186 $(addprefix $(obj)/, $(OBJS)) $(lib1funcs) $(ashldi3) \
      187 $(bswapsdi2) FORCE
      188 @$(check_for_multiple_zreladdr)
      189 $(call if_changed,ld)
      190 @$(check_for_bad_syms)
      // 如果要生成piggy.$(suffix_y).o,需要依赖 $(obj)/piggy.$(suffix_y)
      // 如果要生成$(obj)/piggy.$(suffix_y),要依赖$(obj)/../Image
    • 进入到arch/arm/boot/Makefile,寻找Image目标

      47 $(obj)/Image: vmlinux(顶层目录下的)
      48 $(call if_changed,objcopy)
    • 以Image为源文件,调用了gzip命令生成了piggy.gzip
    • ld链接器以5个.o文件为源文件生成了arch/arm/boot/compressed/vmlinux
    • 7、返回到arch/arm/boot/Makefile,以arch/arm/boot/compressed/vmlinux调用objcopy命令生成了zImage
    • 8、以zImage为源文件调用uimage命令生成uImage文件
  • 总结:uImage的生成,顶层目录下生成vmlinux文件,通过vmlinux文件生成Image,Image调用gzip进行压缩最终生成了piggy.gzip,
  • 调用ld链接器,以piggy.gzip.o和其它.o文件来进行链接生成了zImage,zImage调用uimage命令生成uImage文件

启动过程:

  • 启动过程:涉及到汇编和c,代码都不需要记。我们需要做到的是用什么功能,了解某个部分的代码。
  • arch/arm/kernel/head.S内核的最初启动文件
1、设置特权模式并且屏蔽所有中断
  • 因为我们需要初始化一些硬件并且调用协处理器指令,所以必须设置特权模式
    中断代码还没有设置完成
2、判断u-boot给内核传递的参数是设备树还是tag结构体
  • 我们3.14内核在和u-boot2013版本配合使用时默认使用了设备树
3、创建页表
  • 虚拟地址和物理地址的关系.如果要理解这个关系必须先了解什么是页目录,页表,还有页。
  • 虚拟地址32位,在32位中分成3个部分:10 + 10 + 12
  • 页目录 页表 页
  • 1024项 1024项 1024项
也就是说我们可以把上面的页目录,页表,页都看成是数组,而虚拟地址分成的三个部分就是这三个数组的下标
  • 0x12345678
  • 0001001000 1101000101 011001111000
4、使能并且开启MMU
5、进入到init/main.c中执行start_kernel函数
  • 执行setup_arch();
    • ==>setup_machine_fdt();接收了u-boot传递给内核的设备树地址然后去解析设备树内容
    • console_init()控制台初始化函数,如果在它之前调用printk则输入信息会被临时存放到缓存区中
    • vfs_caches_init()
    • ==>mnt_init();
    • ==>sysfs_init()初始化sysfs文件系统,它的作用在驱动中讲
    • rest_init()
    • ==>kernel_thread(kernel_init,,);
    • kernel_init_freeable();
    • ==>sys_open();//在应用层中的open调用了sys_open,sys_open()函数最终帮助我们找到了驱动接口
    • ==>prepare_namespace();
    • ==>mount_root();
    • ==> mount_nfs_root()通过nfs服务来挂载rootfs文件夹的

设备树:

  • 设备树是干嘛的?设备树是描述硬件信息的。
  • 在操作系统内核中驱动、设备、总线
  • 总线上可以理解为既挂载了设备文件又挂载了驱动程序。总线帮助我们去匹配驱动和设备。
  • 所以在使用总线的前提下我们要写一个驱动程序和一个设备程序。这两种程序都会被最终编译到uImage文件中。
  • 设备树命名:.dts(设备树的源文件) .dtb(设备树的二进制文件) .dtsi(设备树的头文件)
  • vi arch/arm/boot/dts/exynos4412-fs4412.dts
设备树的基本语法:
节点和属性:
  • 每个设备树文件都是从根节点开始的。其它的所有节点都必须包含于根节点。
/{    model = "字符串";对平台或芯片的描述语句,这个属性不重要。    compatible = "fs4412,key";在驱动中的某个结构体成员内容也必须是"fs4412,key"    reg = <寄存器首地址1 偏移量1 寄存器首地址2 偏移量2>;    节点@地址{ 为什么某些节点的后面会出现地址?这个地址为了区分同种设备中的不同子设备    };    标号:节点{为什么会有标号?如果后面的设备需要调用当前设备的所有信息的话,只需要调用标号就可以了    };    interrupt-parent = <&gpx0>; 中断父节点,其中gpx0是某个头文件中一个标号,引用标号的方法要加&    interrupts = <中断类型 中断号 中断触发方式>    中断类型:0代表SPI 1代表PPI    中断号:6代表了EINT[6]来索引中断号    触发方式:1上升沿触发 2下降沿触发 4高电平 8低电平};
根文件系统:
  • etc/:
  • inittab:每行都有4个域,用:分隔
  • 域1:域2:域3:域4
  • 在嵌入式中前两个几乎不用.第三个域是一种动作,第四个域是完成具体动作使用到的命令或者脚本
  • tmpfs、proc、sysfs都是文件系统类型,其中tmpfs可以被挂载多次,但是proc必须挂载到proc目录下,sysfs必须挂载到/sys目录下
  • mount命令只能临时挂载
  • fstab文件可以永久挂载
0 0
原创粉丝点击