您的位置:首页 > 产品设计 > UI/UE

2-内核的编译_uImag_zimage_设备树

2017-02-03 15:15 281 查看
内核的编译:

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文件可以永久挂载
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐