?前言:
本文是根據嗶哩嗶哩網站上“Arm(iMX6U)Linux系統移植和根文件系統構鍵篇”視頻的學習筆記,在這里會記錄下正點原子 I.MX6ULL 開發板的配套視頻教程所作的實驗和學習筆記內容。本文大量引用了正點原子教學視頻和鏈接中的內容。
引用:
正點原子IMX6U倉庫 (GuangzhouXingyi) - Gitee.com
《【正點原子】I.MX6U嵌入式Linux驅動開發指南V1.5.2.pdf》
正點原子資料下載中心 — 正點原子資料下載中心 1.0.0 文檔
正點原子imx6ull-mini-Linux驅動之Linux I2C 驅動實驗(21)-CSDN博客
正文:
本文是 “Arm(iMX6U)Linux系統移植和根文件系統構鍵篇--9 Linux內核編譯和體驗。本節將參考正點原子的視頻教程和配套的正點原子開發指南文檔進行學習。
?
0. 概述
看完 Linux 內核的頂層 Makefile 以后再來看 Linux 內核的大致啟動流程, Linux 內核的啟動流程要比 uboot 復雜的多,涉及到的內容也更多,因此本章我們就大致的了解一下 Linux 內核的啟動流程。
1 鏈接腳本 vmlinux.lds
要分析 Linux 啟動流程,同樣需要先編譯一下 Linux 源碼,因為有很多文件是需要編譯才會生成的。首先分析 Linux 內核的連接腳本文件 arch/arm/kernel/vmlinux.lds,通過鏈接腳本可以找到 Linux 內核的第一行程序是從哪里執行的。 vmlinux.lds 中有如下代碼:
arch/arm/kernel/vmlinux.lds
?第 493 行的 ENTRY 指明了了 Linux 內核入口,入口為 stext, stext 定義在文件arch/arm/kernel/head.S 中 , 因 此 要 分 析 Linux 內 核 的 啟 動 流 程 , 就 得 先 從 文 件arch/arm/kernel/head.S 的 stext 處開始分析。
arch/arm/kernel/head.S
?2 Linux 內核啟動流程分析
2.1 Linux 內核入口 stext
stext 是 Linux 內核的入口地址,在文件 arch/arm/kernel/head.S 中有如下所示提示內容:
根據示例代碼 36.2.1.1 中的注釋, Linux 內核啟動之前要求如下:
①、關閉 MMU。
②、關閉 D-cache。
③、 I-Cache 無所謂。
④、 r0=0。
⑤、 r1=machine nr(也就是機器 ID)。
⑥、 r2=atags 或者設備樹(dtb)首地址。
Linux 內核的入口點 stext 其實相當于內核的入口函數, stext 函數內容如下:
?第 92 行,調用函數 safe_svcmode_maskall 確保 CPU 處于 SVC 模式,并且關閉了所有的中斷。 safe_svcmode_maskall 定義在文件 arch/arm/include/asm/assembler.h 中。
第 94 行,讀處理器 ID, ID 值保存在 r9 寄存器中。
第 95 行,調用函數__lookup_processor_type 檢查當前系統是否支持此 CPU,如果支持就獲取 procinfo 信 息 。 procinfo 是 proc_info_list 類 型 的 結 構 體 , proc_info_list 在 文 件arch/arm/include/asm/procinfo.h 中的定義如下:
Linux 內核將每種處理器都抽象為一個 proc_info_list 結構體,每種處理器都對應一個procinfo。因此可以通過處理器 ID 來找到對應的 procinfo 結構, __lookup_processor_type 函數找到對應處理器的 procinfo 以后會將其保存到 r5 寄存器中。
繼續回到示例代碼 36.2.1.2 中,第 121 行,調用函數__vet_atags 驗證 atags 或設備樹(dtb)的合法性。函數__vet_atags 定義在文件 arch/arm/kernel/head-common.S 中。
第 128 行,調用函數__create_page_tables 創建頁表。
第 137 行,將函數__mmap_switched 的地址保存到 r13 寄存器中。 __mmap_switched 定義在文件 arch/arm/kernel/head-common.S, __mmap_switched 最終會調用 start_kernel 函數。
第 144 行 , 調 用 __enable_mmu 函 數 使 能 MMU , __enable_mmu 定 義 在 文 件arch/arm/kernel/head.S 中。 __enable_mmu 最終會通過調用__turn_mmu_on 來打開 MMU,__turn_mmu_on 最后會執行 r13 里面保存的__mmap_switched 函數。
2.2 __mmap_switched 函數
__mmap_switched 函數定義在文件 arch/arm/kernel/head-common.S 中,函數代碼如下:
第 104 行最終調用 start_kernel 來啟動 Linux 內核, start_kernel 函數定義在文件 init/main.c中。
init/main.c