首發(fā):嵌入式客棧
作者:逸珺
導(dǎo)讀:前文對U-Boot架構(gòu)設(shè)計(jì)做了分析,本文來梳理一下U-Boot在具體板子上的移植工作,主要記錄整體思路、要點(diǎn),以觸類旁通而記之。
1.收集Boot相關(guān)信息
NanoPC-T3 是友善之臂為企業(yè)用戶設(shè)計(jì)的主板,采用三星八核Cortex -A53架構(gòu)的S5P6818處理器。其主要技術(shù)參數(shù):
- CPU: S5P6818, 動態(tài)運(yùn)行主頻400Mhz--1.4GHz 8核
- DDR3 RAM: 1GB,采用2片K4B4G1646D
- SD: 標(biāo)準(zhǔn)SD卡槽一個(gè)
- eMMC:8GB
- HDMI: HDMI 1.4a, Type A型口,1080P高清顯示
- DVP Camera接口: 24pin, 0.5mm間距,FPC貼片豎座
- GPIO擴(kuò)展接口: 4個(gè)UART, 1路I2C, 1路SPI, 3路PWM,9個(gè)GPIO
- …
- 1SOC Boot相關(guān)信息
需要將采用該SOC的方式以U-Boot引導(dǎo),那么首先應(yīng)該將Boot的相關(guān)信息進(jìn)行收集分析。
支持的Boot模式:
-
外部靜態(tài)存儲器ExternalStatic Memory Boot
復(fù)位首條指令直接從外部靜態(tài)存儲器引導(dǎo)。
- 內(nèi)部ROM boot
- NAND boot with Error Correction
- SD/MMC/SDFS (SD FAT File system) boot
- SPI Serial EEPROM boot
- UART boot
- USB Boot
自< SEC/_S5P6818X/_Users/_Manual/_preliminary/_Ver/_0.00.pdf>
SOC內(nèi)置了20KB的iROMBOOT,這是一段固化的boot程序,通過識別外部Boot配置進(jìn)入相應(yīng)的Boot模式,完成內(nèi)部boot到用戶boot程序的第一階段Boot。
從datasheet 看見該SOC內(nèi)部實(shí)現(xiàn)了iROMBOOT,而SPL(Secondaryprogramloader)是u-boot第一階段執(zhí)行的代碼。主要負(fù)責(zé)搬移u-boot第二階段的代碼到。iROMBOOT已經(jīng)實(shí)現(xiàn)了這一功能,故不需要用戶實(shí)現(xiàn)SPL了。
1.2 NanoPC-T3 板級信息
由于boot一般與板子的設(shè)計(jì)配置相關(guān),大多由IO口配置進(jìn)行選擇,既然支持上述如何之多的Boot模式,那么拿到的板子又支持哪些引導(dǎo)模式呢?
可見nanoPC T3僅支持SDMMC Boot模式,進(jìn)入對應(yīng)的章節(jié),可看出支持三個(gè)SD通道。通過從SD存儲卡,MMC存儲卡和eMMC中讀取iROMBOOT并通過使用SDHC模塊將其加載到內(nèi)存中,iROMBOOT執(zhí)行用戶啟動代碼。此方法稱為SDHCBOOT。SDCLK輸出400 kHz用于識別,輸出24 MHz用于數(shù)據(jù)傳輸。
SD3已經(jīng)電路下拉為低:
- 默認(rèn)CAM1/_D3為高,用戶boot通道默認(rèn)為CH0,電路板設(shè)計(jì)為SD卡
SD卡是(secure digital memory card)安全數(shù)碼卡,是一種基于半導(dǎo)體快閃記憶器的新一代記憶設(shè)備,是在MMC基礎(chǔ)上發(fā)展起來的,其內(nèi)部存儲介質(zhì)大都為NAND Flash增加了兩個(gè)主要特色:
可以設(shè)置所存儲的使用權(quán)限,防止數(shù)據(jù)被他人復(fù)制;第二是傳輸速度比2.11版mmc卡快。
特性:
1)可選通信協(xié)議:SD模式和SPI模式
2)可變時(shí)鐘頻率:0~25MHz
3)通信電壓范圍:2.0~3.6V
4)數(shù)據(jù)壽命:10萬次編程/擦除
5)正向兼容MMC卡;
6)運(yùn)行在25M的頻率上,數(shù)據(jù)帶寬是4位,因此最大傳輸速率是12.5MHz(12.5兆字節(jié)每秒) <自百度知道>
eMMC (Embedded Multi Media Card)是MMC協(xié)會訂立、主要針對手機(jī)或平板電腦等產(chǎn)品的內(nèi)嵌式存儲器標(biāo)準(zhǔn)規(guī)格。eMMC在封裝中集成了一個(gè)控制器,提供標(biāo)準(zhǔn)接口并管理閃存,使得手機(jī)廠商就能專注于產(chǎn)品開發(fā)的其它部分,并縮短向市場推出產(chǎn)品的時(shí)間。其內(nèi)部存儲介質(zhì)大都為NAND Flash。
硬件地址空間:
該SOC具有兩個(gè)內(nèi)存控制器:
- MCU-A:DDR3 / LVDDR3(低壓DDR3)/ LPDDR3 / LPDDR2
- MCU-A由DREX和DDRPHY組成
- 支持DDR3 /LVDDR3(低壓DDR3)/ LPDDR3 / LPDDR2內(nèi)存
- 支持2 GB的8/16/32位SDRAM
- 單個(gè)存儲區(qū)(32位數(shù)據(jù)總線寬度)
- 支持掉電模式
- 支持自我刷新模式
- MCU-S:靜態(tài)存儲器
- 靜態(tài)內(nèi)存
- Static兩個(gè)靜態(tài)存儲芯片選擇
- NAND閃存接口
- 23位地址支持使用鎖存器地址
- SLC NAND,帶ECC的MLC NAND(支持BCH算法)
- 靜態(tài)內(nèi)存映射陰影
板上網(wǎng)口采用什么芯片需要,RTL8211E-VB-CG 集成 10/100/1000M 以太網(wǎng)收發(fā)器,顯示接口:RGB LCD接口/HDMI
至此,第一階段收集了那些為移植需要準(zhǔn)備的信息?
- S5P6818 ,8核,armv8,64位SOC
- Boot模式,SDMMC Boot模式,支持兩個(gè)通道,默認(rèn)通道Ch0板載eMMC, 按住Boot 按鍵,CH0:SD Boot,不需要SPL
- 內(nèi)存地址:0x40000000—7FFF FFFF 1G DDR3(2片K4B4G1646D 4Gbit/chip)
- 控制臺:UART0
- 網(wǎng)口:RTL8211E-VB-CG集成10/100/1000M 以太網(wǎng)收發(fā)器。
- LCD:RGB LCD接口/HDMI
2.移植
2.1 明確移植內(nèi)容
在具體實(shí)施之前,首先須總體上明確How to do:
2.2明確Boot流程
明確Boot流程,需要明確有哪些地方需要根據(jù)所選SOC,板級硬件設(shè)計(jì)做出移植:
如前文分析,u-boot的啟動流程主要分亮部分。
第一階段:芯片復(fù)位,執(zhí)行復(fù)位跳轉(zhuǎn),從自各自芯片的start.S開始執(zhí)行匯編代碼
一般而言,start.S 位于- arch/ic/_xxx/cpu/start.S
如:
- arch/arm/cpu/armv7/start.S
- arch/powerpc/cpu/mpc83xx/start.S
-arch/mips/cpu/start.S
為什么這是復(fù)位入口呢?這取決于如何鏈接,由u-boot.lds指定:
鏈接文件位于./arch/arm/cpu/armv8/u-boot.lds
注:因?yàn)閚anoPC-T3 S5P6818的SOC是一顆8核A53核,A53是armv8架構(gòu)。
第二階段:lowlevel/_init(),board/_init/_f(),board/_init/_r():
lowlevel/_init():
- 目的:允許執(zhí)行達(dá)到oard/_init/_f()的基本初始化
- 沒有g(shù)lobal/_data或BSS。
- 沒有堆棧(ARMv7可能有一個(gè)堆棧,但是很快就會被刪除)
- 不得設(shè)置SDRAM或使用控制臺
- 必須只做最少的工作,以允許執(zhí)行繼續(xù)到board/_init/_f()
- 幾乎不需要
- 從此函數(shù)正常返回
board/_init/_f():
- 目的:初始化CPU運(yùn)行環(huán)境以準(zhǔn)備運(yùn)行board/_init/_r():即初始化SDRAM和UART
- global/_data可用
- 堆棧位于SRAM中
- BSS不可用,因此您不能使用全局/靜態(tài)變量,只能使用堆棧變量和global/_data
- 非SPL特定說明:
- 調(diào)用dram/_init()設(shè)置DRAM。 如果已經(jīng)在SPL中完成,則無法執(zhí)行任何操作
- SPL特定說明:
- 可以根據(jù)需要使用自己的版本覆蓋整個(gè)board/_init/_f()函數(shù)。
- preloader/_console/_init()可以在依據(jù)需要調(diào)用
- 須初始化SDRAM,以及初始化UART
- -不需要清除BSS段,由crt0.S完成
- -必須從此函數(shù)正常返回(不要直接調(diào)用board/_init/_r())
此處清除了BSS。對于SPL,如果定義了CONFIG/_SPL/_STACK/_R,則此時(shí)將堆棧和global/_data重定位到CONFIG/_SPL/_STACK/_R/_ADDR之下。 對于非SPL,U-Boot被重定位以在內(nèi)存頂部運(yùn)行。
board/_init/_r():
- 目的:主要執(zhí)行,通用代碼
- global/_data可用
- SDRAM可用
- BSS可用,可以使用所有靜態(tài)/全局變量
- 執(zhí)行最終繼續(xù)到main/_loop()
- 非SPL特定說明:
- U-Boot重定位到內(nèi)存頂部,并且現(xiàn)在從那里開始運(yùn)行。
- SPL特定說明:
-
如果定義了CONFIG/_SPL/_STACK/_R并且
CONFIG/_SPL/_STACK/_R/_ADDR指向SDRAM,則堆棧可選地位于SDRAM中
- 在這里可以調(diào)用preloader/_console/_init()-通常是通過定義CONFIG/_SPL/_BOARD/_INIT然后提供包含此調(diào)用的spl/_board/_init()函數(shù)來完成的
- 加載U-Boot或(在falcon模式下)Linux
以上關(guān)于lowlevel/_init(),board/_init/_f(),board/_init/_r()翻譯自./README
這里有幾個(gè)概念需要進(jìn)一步解析,方便下面理解:
- 堆(heap):堆的管理由C庫實(shí)現(xiàn)的,Linux中是一般由Glibc,取決于選用什么C庫。內(nèi)存的獲取與釋放由程序員通過調(diào)用C庫中的malloc/free進(jìn)行操作,C庫中的動態(tài)內(nèi)存管理單元具體實(shí)現(xiàn)。大體上在工程中指定堆的大小,C庫中的堆管理器將這片內(nèi)存進(jìn)行動態(tài)管理,這里需要用到一些數(shù)據(jù)結(jié)構(gòu)算法對這片內(nèi)存區(qū)進(jìn)行動態(tài)管理。如果要對堆的管理實(shí)現(xiàn)進(jìn)行分析,可以參考glibc的源代碼。
- 棧(stack):由編譯器實(shí)現(xiàn)棧的管理,由編譯器自動分配釋放 ,存放函數(shù)的參數(shù)值,局部變量的值等。其操作方式類似于數(shù)據(jù)結(jié)構(gòu)中的棧。
堆/棧的大小由下面的宏定義:
- CONFIG/_SYS/_MALLOC/_LEN 指定堆大小
- CONFIG/_SYS/_RESERVE/_MEM/_SIZE/ CONFIG/_SYS/_MALLOC/_LEN 一起指定棧大小
Stack size= CONFIG/_SYS/_RESERVE/_MEM/_SIZE-
CONFIG/_SYS/_MALLOC/_LEN
這幾個(gè)宏定義了內(nèi)存上界、堆上下界、棧的上下界有編譯器、C庫實(shí)現(xiàn)越界保護(hù)機(jī)制。
global/_data:
該結(jié)構(gòu)體收集板子的基本信息,內(nèi)存,名稱,CPU時(shí)鐘,環(huán)境變量,標(biāo)準(zhǔn)IO,設(shè)備驅(qū)動句柄等等。
紅色部分信息將堆分配情況與U-Boot全局?jǐn)?shù)據(jù)結(jié)構(gòu)關(guān)聯(lián)。
- bss段:bss段(bss segment)通常是指用來存放程序中未初始化的全局變量的一塊內(nèi)存區(qū)域。bss是英文Block Started by Symbol的簡稱。bss段屬于靜態(tài)內(nèi)存分配。
- data段:數(shù)據(jù)段(data segment)通常是指用來存放程序中已初始化的全局變量的一塊內(nèi)存區(qū)域。數(shù)據(jù)段屬于靜態(tài)內(nèi)存分配。
-
text段:代碼段(code segment/text segment)通常是指用來存放程序執(zhí)行代碼的一塊內(nèi)存區(qū)域。這部分區(qū)域的大小在程序運(yùn)行前就已經(jīng)確定,并且內(nèi)存區(qū)域通常屬于只讀(某些架構(gòu)也允許代碼段為可寫,即允許修改程序)。在代碼段中,也有可能包含一些只讀的常數(shù)變量,例如字符串常量等。
一個(gè)程序本質(zhì)上由這三個(gè)段由鏈接器鏈接而成。
2.3 創(chuàng)建板子文件
位置board/my/_vendor/my/_board/my/_board.c, 對于nanoPC-T3而言
./board/s5p6818/nanopi3/ board.c
- dram/_init 實(shí)現(xiàn)內(nèi)存初始化
-
board/_init 實(shí)現(xiàn)GPIO初始化、啟動設(shè)備初始化等操作,這與板子的硬件息息相關(guān)。
需聲明DECLARE/_GLOBAL/_DATA/_PTR指針,因?yàn)楸灸K需要對gd成員進(jìn)行初始化,ARM32等價(jià)于r9寄存器,ARM64等價(jià)于寄存器x18
位于./arch/arm/include/asm/global/_data.h
2.4 創(chuàng)建Kconfig配置文件
board/my/_vendor/my/_board/Kconfig
需定義Kconfig對于board需要的相關(guān)變量SYS/_BOARD,SYS/_VENDOR,SYS/_CONFIG/_NAME。
由于S5P6818是一顆64位芯片,那么32位/64位將變成可選配置。故這里新創(chuàng)建了S5P6818/_FEATURES用以配置32位/64位,當(dāng)取值為no表示為32位配置。
- SYS/_BOARD,SYS/_VENDOR 用于給kuild識別在那個(gè)board,verder目錄需去編譯相應(yīng)源文件
- SYS/_CONFIG/_NAME 用于給kuild識別在哪里去尋找板子頭文件
include/configs/SYS/_CONFIG/_NAME.h
2.6創(chuàng)建板子Makefile
board/my/_vendor/my/_board/Makefile 對nanoPC-T3而言:
obj-y:=board.o hwrev.o onewire.o lcds.o
由于需要實(shí)現(xiàn)LCD以及單線觸摸控制器,則需要將上述文件編譯。
2.7 創(chuàng)建板子defconfig
configs/my/_board/_defconfig, 對nanoPC-T3而言:
s5p6818/_nanopi3
/_defconfig
對于新版的U-boot已支持make menuconfig,可以運(yùn)行該命令進(jìn)行其他配置,然后將生成的.config文件拷貝至此。
mv .config ./configs/s5p6818/_nanopi3/_defconfig
主要裁剪支持的驅(qū)動,以及shell命令等
注:舊版本的U-Boot使用boards.cfg添加板子。
2.8創(chuàng)建板子頭文件
include/confi gs/my/_board.h,對nanoPC-T3而言:
include/confi gs/ s5p6818/_nanopi3.h
環(huán)境變量:
這些定義由./common下環(huán)境變量管理模塊負(fù)責(zé)維護(hù),其結(jié)構(gòu)體定義如下,主要為字符串常量。
2.8 引導(dǎo)分析
為了能夠重新映射內(nèi)存,U-Boot隨后跳至其鏈接地址。為了能夠在C中實(shí)現(xiàn)初始化代碼,在內(nèi)部雙端RAM中設(shè)置了一個(gè)(很小的)初始堆棧(如果CPU提供了諸如MPC8xx或MPC8260之類的功能),或者在數(shù)據(jù)的鎖定部分中緩存。之后,U-Boot初始化CPU內(nèi)核,緩存和SIU。
接下來,使用初步映射來映射所有可用的存儲體。例如,將它們放在512 MB邊界上(0x20000000的倍數(shù):0x00000000和0x20000000上的SDRAM,0x40000000和0x60000000上的Flash,0x80000000上的SRAM)。然后,將UPMA編程用于SDRAM訪問。使用臨時(shí)配置,將運(yùn)行簡單的內(nèi)存測試,以確定SDRAM存儲區(qū)的大小。
如果有多個(gè)SDRAM存儲區(qū),并且存儲區(qū)的大小不同,則首先映射最大的存儲區(qū)。對于相等的大小,將首先映射第一個(gè)存儲區(qū)(CS2#)。第一個(gè)映射始終是針對地址0x00000000的,后面緊跟著任何其他存儲區(qū)以創(chuàng)建從0開始的連續(xù)存儲器。
然后,監(jiān)視器將自身安裝在SDRAM區(qū)域的高端,并分配內(nèi)存供malloc()和全局Board Info數(shù)據(jù)使用;同樣,將異常矢量代碼復(fù)制到低RAM頁面中,并建立最終堆棧。
只有在此重定位之后,才能擁有“正常”的C環(huán)境。由于受到多種方式的限制,主要是因?yàn)閺腞OM運(yùn)行,并且必須將代碼重定位到RAM中的新地址運(yùn)行。
至于上述過程重定向,主要利用鏈接綁定以實(shí)現(xiàn)符號表位置可知,從將u-boot映象拷貝到內(nèi)存可實(shí)現(xiàn)運(yùn)行切換。
/*指定輸出格式elf64-littleaarch64*/
而在./arch/arm/lib/sections.c 定義了對應(yīng)的全局符號,這樣就實(shí)現(xiàn)了鏈接地址綁定:
char __bss_start[0] __attribute__((section(".__bss_start")));
下面對crt0/_64.S 匯編代碼做簡要注釋幫助理解重定向過程:
ENTRY(_main)/*聲明入口*/
總結(jié):
- 思路須清楚,不要一開始關(guān)注細(xì)節(jié)
- 采用漸進(jìn)明細(xì)、逐步迭代的方法論
- u-boot 其核心在于將系統(tǒng)成功引導(dǎo)。
_—END_—
審核編輯 黃昊宇-
u-boot
+關(guān)注
關(guān)注
0文章
122瀏覽量
38845 -
深度學(xué)習(xí)
+關(guān)注
關(guān)注
73文章
5561瀏覽量
122811
發(fā)布評論請先 登錄
U-boot的基本介紹

嵌入式系統(tǒng)中U-Boot 基本特點(diǎn)及其移植方法
嵌入式系統(tǒng)中U-Boot 基本特點(diǎn)及其移植方法
基于S3C44B0的U-Boot啟動分析和移植實(shí)現(xiàn)
U-Boot的啟動及移植分析
嵌入式U-BOOT的啟動流程及移植
基于S3C6410的u-boot分析與移植
剖析基于nanoPC-T3的U-Boot移植過程

U-boot的QSPI驅(qū)動移植方法及驗(yàn)證方法

評論