2-內(nèi)核的編譯_uImag_zimage_設(shè)備樹

內(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個.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文件,通過vmlinux文件生成Image,Image調(diào)用gzip進(jìn)行壓縮最終生成了piggy.gzip,
  • 調(diào)用ld鏈接器,以piggy.gzip.o和其它.o文件來進(jìn)行鏈接生成了zImage,zImage調(diào)用uimage命令生成uImage文件

啟動過程:

  • 啟動過程:涉及到匯編和c,代碼都不需要記。我們需要做到的是用什么功能,了解某個部分的代碼。
  • arch/arm/kernel/head.S內(nèi)核的最初啟動文件
1、設(shè)置特權(quán)模式并且屏蔽所有中斷
  • 因?yàn)槲覀冃枰跏蓟恍┯布⑶艺{(diào)用協(xié)處理器指令,所以必須設(shè)置特權(quán)模式
    中斷代碼還沒有設(shè)置完成
2、判斷u-boot給內(nèi)核傳遞的參數(shù)是設(shè)備樹還是tag結(jié)構(gòu)體
  • 我們3.14內(nèi)核在和u-boot2013版本配合使用時默認(rèn)使用了設(shè)備樹
3、創(chuàng)建頁表
  • 虛擬地址和物理地址的關(guān)系.如果要理解這個關(guān)系必須先了解什么是頁目錄,頁表,還有頁。
  • 虛擬地址32位,在32位中分成3個部分:10 + 10 + 12
  • 頁目錄 頁表 頁
  • 1024項(xiàng) 1024項(xiàng) 1024項(xiàng)
也就是說我們可以把上面的頁目錄,頁表,頁都看成是數(shù)組,而虛擬地址分成的三個部分就是這三個數(shù)組的下標(biāo)
  • 0x12345678
  • 0001001000 1101000101 011001111000
4、使能并且開啟MMU
5、進(jìn)入到init/main.c中執(zhí)行start_kernel函數(shù)
  • 執(zhí)行setup_arch();
    • ==>setup_machine_fdt();接收了u-boot傳遞給內(nèi)核的設(shè)備樹地址然后去解析設(shè)備樹內(nèi)容
    • console_init()控制臺初始化函數(shù),如果在它之前調(diào)用printk則輸入信息會被臨時存放到緩存區(qū)中
    • vfs_caches_init()
    • ==>mnt_init();
    • ==>sysfs_init()初始化sysfs文件系統(tǒng),它的作用在驅(qū)動中講
    • rest_init()
    • ==>kernel_thread(kernel_init,,);
    • kernel_init_freeable();
    • ==>sys_open();//在應(yīng)用層中的open調(diào)用了sys_open,sys_open()函數(shù)最終幫助我們找到了驅(qū)動接口
    • ==>prepare_namespace();
    • ==>mount_root();
    • ==> mount_nfs_root()通過nfs服務(wù)來掛載rootfs文件夾的

設(shè)備樹:

  • 設(shè)備樹是干嘛的?設(shè)備樹是描述硬件信息的。
  • 在操作系統(tǒng)內(nèi)核中驅(qū)動、設(shè)備、總線
  • 總線上可以理解為既掛載了設(shè)備文件又掛載了驅(qū)動程序??偩€幫助我們?nèi)テヅ潋?qū)動和設(shè)備。
  • 所以在使用總線的前提下我們要寫一個驅(qū)動程序和一個設(shè)備程序。這兩種程序都會被最終編譯到uImage文件中。
  • 設(shè)備樹命名:.dts(設(shè)備樹的源文件) .dtb(設(shè)備樹的二進(jìn)制文件) .dtsi(設(shè)備樹的頭文件)
  • vi arch/arm/boot/dts/exynos4412-fs4412.dts
設(shè)備樹的基本語法:
節(jié)點(diǎn)和屬性:
  • 每個設(shè)備樹文件都是從根節(jié)點(diǎn)開始的。其它的所有節(jié)點(diǎn)都必須包含于根節(jié)點(diǎn)。
/{
    model = "字符串";對平臺或芯片的描述語句,這個屬性不重要。
    compatible = "fs4412,key";在驅(qū)動中的某個結(jié)構(gòu)體成員內(nèi)容也必須是"fs4412,key"
    reg = <寄存器首地址1 偏移量1 寄存器首地址2 偏移量2>;
    節(jié)點(diǎn)@地址{ 為什么某些節(jié)點(diǎn)的后面會出現(xiàn)地址?這個地址為了區(qū)分同種設(shè)備中的不同子設(shè)備
    };

    標(biāo)號:節(jié)點(diǎn){為什么會有標(biāo)號?如果后面的設(shè)備需要調(diào)用當(dāng)前設(shè)備的所有信息的話,只需要調(diào)用標(biāo)號就可以了

    };

    interrupt-parent = <&gpx0>; 中斷父節(jié)點(diǎn),其中g(shù)px0是某個頭文件中一個標(biāo)號,引用標(biāo)號的方法要加&
    interrupts = <中斷類型 中斷號 中斷觸發(fā)方式>
    中斷類型:0代表SPI 1代表PPI
    中斷號:6代表了EINT[6]來索引中斷號
    觸發(fā)方式:1上升沿觸發(fā) 2下降沿觸發(fā) 4高電平 8低電平
};
根文件系統(tǒng):
  • etc/:
  • inittab:每行都有4個域,用:分隔
  • 域1:域2:域3:域4
  • 在嵌入式中前兩個幾乎不用.第三個域是一種動作,第四個域是完成具體動作使用到的命令或者腳本
  • tmpfs、proc、sysfs都是文件系統(tǒng)類型,其中tmpfs可以被掛載多次,但是proc必須掛載到proc目錄下,sysfs必須掛載到/sys目錄下
  • mount命令只能臨時掛載
  • fstab文件可以永久掛載
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容