內(nèi)核的編譯:
- make uImage
- 1浆劲、在頂層目錄下搜索uImage發(fā)現(xiàn)找不到,有可能uImage存在于其他的Makefile文件中
- 2蚯嫌、include arch/arm/Makefile
- 3晒旅、進(jìn)入到arch/arm/Makefile中,尋找uImage目標(biāo)
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拟烫、進(jìn)入到arch/arm/boot目錄下尋找uImage目標(biāo)
78 $(obj)/uImage: $(obj)/zImage FORCE 79 @$(check_for_multiple_loadaddr) 80 $(call if_changed,uimage) 81 @$(kecho) ' Image $@ is ready'
- 如果需要生成uImage,必須依賴zImage
- 5、搜索目標(biāo)zImage
54 $(obj)/zImage: $(obj)/compressed/vmlinux FORCE 55 $(call if_changed,objcopy)
- 6、在arch/arm/boot/compressed/Makefile中尋找vmlinux目標(biāo)
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
- 進(jìn)入到arch/arm/boot/Makefile,尋找Image目標(biāo)
47 $(obj)/Image: vmlinux(頂層目錄下的) 48 $(call if_changed,objcopy)
- 以Image為源文件,調(diào)用了gzip命令生成了piggy.gzip
- ld鏈接器以5個(gè).o文件為源文件生成了arch/arm/boot/compressed/vmlinux
- 7尝江、返回到arch/arm/boot/Makefile,以arch/arm/boot/compressed/vmlinux調(diào)用objcopy命令生成了zImage
- 8苍日、以zImage為源文件調(diào)用uimage命令生成uImage文件
- 總結(jié):uImage的生成,頂層目錄下生成vmlinux文件,通過(guò)vmlinux文件生成Image耕腾,Image調(diào)用gzip進(jìn)行壓縮最終生成了piggy.gzip,
- 調(diào)用ld鏈接器羹呵,以piggy.gzip.o和其它.o文件來(lái)進(jìn)行鏈接生成了zImage盈简,zImage調(diào)用uimage命令生成uImage文件
啟動(dòng)過(guò)程:
- 啟動(dòng)過(guò)程:涉及到匯編和c,代碼都不需要記。我們需要做到的是用什么功能弃衍,了解某個(gè)部分的代碼猖败。
- arch/arm/kernel/head.S內(nèi)核的最初啟動(dòng)文件
1、設(shè)置特權(quán)模式并且屏蔽所有中斷
- 因?yàn)槲覀冃枰跏蓟恍┯布⑶艺{(diào)用協(xié)處理器指令破停,所以必須設(shè)置特權(quán)模式
中斷代碼還沒(méi)有設(shè)置完成
2理茎、判斷u-boot給內(nèi)核傳遞的參數(shù)是設(shè)備樹(shù)還是tag結(jié)構(gòu)體
- 我們3.14內(nèi)核在和u-boot2013版本配合使用時(shí)默認(rèn)使用了設(shè)備樹(shù)
3蚯撩、創(chuàng)建頁(yè)表
- 虛擬地址和物理地址的關(guān)系.如果要理解這個(gè)關(guān)系必須先了解什么是頁(yè)目錄,頁(yè)表美浦,還有頁(yè)。
- 虛擬地址32位币厕,在32位中分成3個(gè)部分:10 + 10 + 12
- 頁(yè)目錄 頁(yè)表 頁(yè)
- 1024項(xiàng) 1024項(xiàng) 1024項(xiàng)
也就是說(shuō)我們可以把上面的頁(yè)目錄阴绢,頁(yè)表,頁(yè)都看成是數(shù)組,而虛擬地址分成的三個(gè)部分就是這三個(gè)數(shù)組的下標(biāo)
- 0x12345678
- 0001001000 1101000101 011001111000
4篓足、使能并且開(kāi)啟MMU
5陪腌、進(jìn)入到init/main.c中執(zhí)行start_kernel函數(shù)
- 執(zhí)行setup_arch();
- ==>setup_machine_fdt();接收了u-boot傳遞給內(nèi)核的設(shè)備樹(shù)地址然后去解析設(shè)備樹(shù)內(nèi)容
- console_init()控制臺(tái)初始化函數(shù)参滴,如果在它之前調(diào)用printk則輸入信息會(huì)被臨時(shí)存放到緩存區(qū)中
- vfs_caches_init()
- ==>mnt_init();
- ==>sysfs_init()初始化sysfs文件系統(tǒng),它的作用在驅(qū)動(dòng)中講
- rest_init()
- ==>kernel_thread(kernel_init,,);
- kernel_init_freeable();
- ==>sys_open();//在應(yīng)用層中的open調(diào)用了sys_open,sys_open()函數(shù)最終幫助我們找到了驅(qū)動(dòng)接口
- ==>prepare_namespace();
- ==>mount_root();
- ==> mount_nfs_root()通過(guò)nfs服務(wù)來(lái)掛載rootfs文件夾的
設(shè)備樹(shù):
- 設(shè)備樹(shù)是干嘛的暴心?設(shè)備樹(shù)是描述硬件信息的弹沽。
- 在操作系統(tǒng)內(nèi)核中驅(qū)動(dòng)、設(shè)備蚌堵、總線
- 總線上可以理解為既掛載了設(shè)備文件又掛載了驅(qū)動(dòng)程序瘸味。總線幫助我們?nèi)テヅ潋?qū)動(dòng)和設(shè)備毅贮。
- 所以在使用總線的前提下我們要寫(xiě)一個(gè)驅(qū)動(dòng)程序和一個(gè)設(shè)備程序炫加。這兩種程序都會(huì)被最終編譯到uImage文件中魄健。
- 設(shè)備樹(shù)命名:.dts(設(shè)備樹(shù)的源文件) .dtb(設(shè)備樹(shù)的二進(jìn)制文件) .dtsi(設(shè)備樹(shù)的頭文件)
vi arch/arm/boot/dts/exynos4412-fs4412.dts
設(shè)備樹(shù)的基本語(yǔ)法:
節(jié)點(diǎn)和屬性:
- 每個(gè)設(shè)備樹(shù)文件都是從根節(jié)點(diǎn)開(kāi)始的农尖。其它的所有節(jié)點(diǎn)都必須包含于根節(jié)點(diǎn)。
/{
model = "字符串";對(duì)平臺(tái)或芯片的描述語(yǔ)句,這個(gè)屬性不重要。
compatible = "fs4412,key";在驅(qū)動(dòng)中的某個(gè)結(jié)構(gòu)體成員內(nèi)容也必須是"fs4412,key"
reg = <寄存器首地址1 偏移量1 寄存器首地址2 偏移量2>;
節(jié)點(diǎn)@地址{ 為什么某些節(jié)點(diǎn)的后面會(huì)出現(xiàn)地址洗显?這個(gè)地址為了區(qū)分同種設(shè)備中的不同子設(shè)備
};
標(biāo)號(hào):節(jié)點(diǎn){為什么會(huì)有標(biāo)號(hào)?如果后面的設(shè)備需要調(diào)用當(dāng)前設(shè)備的所有信息的話玄组,只需要調(diào)用標(biāo)號(hào)就可以了
};
interrupt-parent = <&gpx0>; 中斷父節(jié)點(diǎn),其中g(shù)px0是某個(gè)頭文件中一個(gè)標(biāo)號(hào),引用標(biāo)號(hào)的方法要加&
interrupts = <中斷類型 中斷號(hào) 中斷觸發(fā)方式>
中斷類型:0代表SPI 1代表PPI
中斷號(hào):6代表了EINT[6]來(lái)索引中斷號(hào)
觸發(fā)方式:1上升沿觸發(fā) 2下降沿觸發(fā) 4高電平 8低電平
};
根文件系統(tǒng):
- etc/:
- inittab:每行都有4個(gè)域胞此,用:分隔
- 域1:域2:域3:域4
- 在嵌入式中前兩個(gè)幾乎不用.第三個(gè)域是一種動(dòng)作枝缔,第四個(gè)域是完成具體動(dòng)作使用到的命令或者腳本
- tmpfs、proc、sysfs都是文件系統(tǒng)類型顿涣,其中tmpfs可以被掛載多次孵淘,但是proc必須掛載到proc目錄下揉阎,sysfs必須掛載到/sys目錄下
- mount命令只能臨時(shí)掛載
- fstab文件可以永久掛載