本文分析 4412 的 uboot 源碼,結(jié)合 uboot 源碼來分析 uboot 完成了哪些工作。分析的源碼文件是“cpu/ARM_cortexa9/start.S”文件。 1 源碼分析
1.jpg (11.92 KB, 下載次數(shù): 101)
下載附件
2019-8-1 11:32 上傳
.globl _start :globl 類似 C 語言中的 Extern,類似定義一個(gè)全局函數(shù)_start,外部可以訪問_start,_start 是整個(gè) uboot 的入口,第一行代碼就是從這里開始執(zhí)行的。
_start: b reset :_start:表示進(jìn)入到“全局函數(shù)”_start 的主體結(jié)構(gòu); b reset 表示跳到 reset。類似 c 語言中的 goto reset,跳轉(zhuǎn)到 reset。_start 中在正常啟動(dòng)的時(shí)候只運(yùn)行一條語句“b reset”,就跳轉(zhuǎn)到 reset,剩余部分不會(huì)執(zhí)行。
_start“全局函數(shù)”剩下的部分,在出現(xiàn)異常情況下,它會(huì)強(qiáng)制跳到異常處理代碼中。
ldr pc, _undefined_instruction //“未定義指令”的時(shí)候,系統(tǒng)所要去執(zhí)行的代碼。
ldr pc, _software_interrupt //軟件中斷
ldr pc, _prefetch_abort //預(yù)取指錯(cuò)誤
ldr pc, _data_abort //數(shù)據(jù)錯(cuò)誤
ldr pc, _not_used //未定義
ldr pc, _irq //(普通)中斷
ldr pc, _fiq //快速中斷 以下代碼是異常向量地址。
2.jpg (19.04 KB, 下載次數(shù): 117)
下載附件
2019-8-1 11:32 上傳
下面的代碼表示接下來的代碼,都要 16 字節(jié)對(duì)齊,不足之處,用 0xdeadbeef 填充
3.jpg (6.05 KB, 下載次數(shù): 113)
下載附件
2019-8-1 11:32 上傳
接著看一下 reset 主體部分,將其中#IF 0 等無關(guān)部分去掉,有效代碼如下所示。
可以先直接看注釋,不具體看每一行匯編的含義。
將 CPU 設(shè)置為 SVC32 模式。
4.jpg (40.24 KB, 下載次數(shù): 106)
下載附件
2019-8-1 11:32 上傳
cache 初始化和關(guān)閉。
5.jpg (9.68 KB, 下載次數(shù): 103)
下載附件
2019-8-1 11:32 上傳
6.jpg (14.59 KB, 下載次數(shù): 99)
下載附件
2019-8-1 11:32 上傳
關(guān)閉 TLBs,和 icache。
7.jpg (10.05 KB, 下載次數(shù): 104)
下載附件
2019-8-1 11:32 上傳
關(guān)閉 MMU 和 caches。
8.jpg (18.55 KB, 下載次數(shù): 105)
下載附件
2019-8-1 11:32 上傳
大家可能對(duì)以上名詞比較陌生,事實(shí)上不理解這部分,并不影響我們移植新的 uboot,只需要將這部分和新的 uboot 這部分對(duì)比,有不同的地方修改下就成。 4412 開發(fā)板,使用的處理器是 Exynos 4412,它是采用 arm v7 指令集(體系結(jié)構(gòu)),cortex a9 架構(gòu)(CPU 核心內(nèi)構(gòu)),關(guān)于 cache、MMU 和 TLBs 等概念,在 4412 的datasheet 中是沒有描述。如果大家感興趣,可以在 ARM 官網(wǎng)中搜索文檔。 arm 官網(wǎng)網(wǎng)址:
https://developer.arm.com/
作者下載了 A9 架構(gòu)“DDI0388I_cortex_a9_r4p1_trm.pdf”的文檔,這個(gè)文檔中有關(guān)于這幾個(gè)寄存器詳細(xì)介紹,如果大家非常感興趣,可以讀一讀。
在移植新的 uboot 時(shí),這部分只需要將代碼 copy 過去即可,更多的情況是,uboot 新版的源碼中自帶這部分源碼。 這里給大家簡(jiǎn)要介紹下上面的幾個(gè)重要名詞概念。
3.2.2 ARM 的協(xié)處理器
作者將介紹前面涉及到的寄存器(SVC32、MMU 和 iCACHE 等寄存器),對(duì)應(yīng)的 ARM官方英文文檔來來回回看了好多遍,發(fā)現(xiàn)“協(xié)處理器”這個(gè)翻譯讓人很困惑。
“協(xié)助處理器”在網(wǎng)上有人這么描述“協(xié)處理器是一種芯片,用于減輕系統(tǒng)微處理器的特定處理任務(wù)。”
關(guān)于 ARM 處理器的協(xié)處理器,有這樣定義的“協(xié)處理器可以附屬于 ARM 處理器。一個(gè)協(xié)處理器通過擴(kuò)展指令集或提供配置寄存器來擴(kuò)展內(nèi)核處理功能。一個(gè)或多個(gè)協(xié)處理器可以通
過協(xié)處理器接口與 ARM 內(nèi)核相連。”
如果定義“協(xié)處理器”為一般用來指輔助 CPU 的芯片,這樣獨(dú)立顯卡中的芯片也可以稱為協(xié)處理器。如果使用“協(xié)處理器可以附屬 ARM...”,那么 4412 中的硬件解碼、3D 圖形處理等也可以稱為協(xié)處理器。
作者覺得還是要看 ARM 官網(wǎng)文檔是如何描述這部分內(nèi)容,如下圖所示。
9.jpg (22.84 KB, 下載次數(shù): 92)
下載附件
2019-8-1 11:32 上傳
上面紅色框中,第一行翻譯為“系統(tǒng)控制協(xié)處理器”,我覺得用“系統(tǒng)控制協(xié)處理器”還是容易理解,可以接收。它包含了 15 個(gè)特殊的寄存器,主要提供“所有的系統(tǒng)控制和配置”、“MMC 控制和管理”、“cache 控制和管理”和“系統(tǒng)性能監(jiān)控”功能。
在 ARM 的匯編代碼中,凡是看到“mrc”和“mcr”指令,就表明接下來有一小段代碼用來控制協(xié)處理器(后面全部簡(jiǎn)稱為協(xié)處理器)。具體的含義,可以通過注釋了解下,如果特別感興趣,可以看下關(guān)于文檔,里面對(duì)每一 bit 的作用都有詳細(xì)的描述。
3.2.3 SVC32 模式在協(xié)處理器操作中,首先是將系統(tǒng)設(shè)置為 SVC32 工作模式,ARM 系統(tǒng)有 7 種工作模式:
10.jpg (39.45 KB, 下載次數(shù): 106)
下載附件
2019-8-1 11:32 上傳
除了用戶模式之外的其他 6 種處理器模式稱為特權(quán)模式,特權(quán)模式下,程序可以訪問所有的系統(tǒng)資源,也可以任意地進(jìn)行處理器模式的切換。特權(quán)模式中,除系統(tǒng)模式外,其他 5 種模式又稱為異常模式。大多數(shù)的用戶程序運(yùn)行在用戶模式下,此時(shí),應(yīng)用程序不能夠訪問一些受操作系統(tǒng)保護(hù)的系統(tǒng)資源,應(yīng)用程序也不能直接進(jìn)行處理器模式的切換。用戶模式下,當(dāng)需要進(jìn)行處理器模式切換時(shí),應(yīng)用程序可以產(chǎn)生異常處理,在異常處理中進(jìn)行處理器模式的切換。
svc 模式是特權(quán)模式,可以訪問受限制的資源,它和 sys 模式所用的寄存器組是一樣的,但是 svc 模式下的一些資源是 sys 模式不能訪問的。
uboot 要完成初始化硬件的工作,最終目標(biāo)是啟動(dòng) kernel,在 uboot 跳轉(zhuǎn)到 kernel 之前,MPU 需要設(shè)置為 svc 模式。
結(jié)合在 uboot 完成初始化硬件和引導(dǎo)內(nèi)核的功能來分析,在 uboot 初始化階段就應(yīng)該將uboot 設(shè)置為 svc 模式。
3.3.4 MMU 內(nèi)存管理單元在協(xié)處理器中,最重要的是內(nèi)存管理單元。它是一種負(fù)責(zé)處理中央處理器的內(nèi)存訪問請(qǐng)求的計(jì)算機(jī)硬件。它的功能包括虛擬地址到物理地址的轉(zhuǎn)換(即虛擬內(nèi)存管理)、內(nèi)存保護(hù)、中央處理器高速緩存的控制。
如果學(xué)習(xí)過驅(qū)動(dòng)教程,會(huì)了解到在內(nèi)核源碼中,操作 GPIO 的時(shí)候,操作的是虛擬地址,而不是物理地址。MMU 是物理地址和虛擬地址轉(zhuǎn)化的控制單元。
cache 是高速緩存,cpu 的處理速度越來越快,假如 CPU 直接和內(nèi)存通信,內(nèi)存的速度仍然達(dá)不到要求,CPU 要通過高速緩存來和內(nèi)存通信,高速緩存的速度比內(nèi)存要快。
TLB 是用于鏈接 cache 和內(nèi)存,mmu 用于鏈接內(nèi)存和物理地址。
這里我們需要理解的是,在系統(tǒng)啟動(dòng)過程中,cpu 和內(nèi)存之間要完成通信,首先需要 TLB實(shí)現(xiàn) cache 和內(nèi)存之間的地址映射,通過 mmu 實(shí)現(xiàn)虛擬地址和物理地址之間的映射。
如果不將 mmu、TLB 以及 cache 關(guān)閉,cpu 可能會(huì)直接去 cache 取值,這個(gè)時(shí)候內(nèi)存和 cache 之間可能還無法正常通信,可能導(dǎo)致 cpu 讀取數(shù)據(jù)出現(xiàn)錯(cuò)誤。
關(guān)于協(xié)處理器就介紹完畢了,涉及到的匯編指令,這部分建議只通過附錄來了解一下。我們要盡快掌握全貌,不能陷入到某一個(gè)概念中,而且這部分也不影響最終目標(biāo)--uboot 的移植。
|