现在的位置: 首页 > 综合 > 正文

Linux Kernel SMP (Symmetric Multi-Processors) 開機流程解析 Part(1) Boot-Rom與UBoot.

2013年12月07日 ⁄ 综合 ⁄ 共 6177字 ⁄ 字号 评论关闭

http://loda.hala01.com/category/loda%E7%9A%84%E6%8A%80%E8%A1%93%E6%96%87%E7%AB%A0%E5%88%86%E4%BA%AB/page/3/

本文主要針對Linux Kernel支援ARM MPCore架構下所需的多核心開機流程作一個介紹,所涉及的內容會以筆者認為值得進一步說明的內容為主,從目前市面上的產品來分析,雖然都是針對ARM
MPCore
的產品,然而這些流程上都還是有所出入,也因此,本文的內容主要是提供實作上的介紹與例子,實際的產品開發,請以所參與的MPCore
SoC
計畫為主其實只要能掌握好ARM處理器的行為,有關MPCoreLinux
Kernel SMP
的支援相信都是能夠游刃有餘的.

由於筆者時間關係,本文會分段刊登,還請見諒.

Linux Kernel對多核心的支援

LinuxKernel 2.0開始,就已經加入對SMP (Symmetric
Multi Processors)
的支援,Linux Kernel會以Process或是Kernel Thread為單位來對排程,也就是說ProcessKernel
Thread
都有機會會被安排在一個處理器上運作.到了Kernel 2.2,Linux SMP已經支援UltraSparc,
SparcServer, Alpha 
與 PowerPC相關處理器. Linux上的Thread是透過 clone的方式產生的,也就是說Thread會共享父Process的資源與記憶體空間.對多核心處理器而言,這些Thread也會有自己的Process
Id
Priority,並且會一同參與多核心處理器的多工排程.

make mnuconfig選項中,選擇 Processor type and features —>Symmetric multi-processing support 就可以開啟Kernel對於多核心的支援.

軟體識別目前所在的處理器

執行時期,軟體可以透過 CPU ID Register知道目前是MPCore中哪個處理器執行該程式碼,CPU
Id
儲存在CP15 c0,長度為32bits,只能在特權等級(也就是SVC
Mode
)被讀取,

讀取的範例如下程式碼所示

MRC p15,0,<Rd>,c0,c0,5; returns CPU ID register

31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
SBZ Cluster ID SBZ CPU ID

說明如下,

1,Cluster ID: 用以支援 Multi-MPCore架構下的Cluster識別之用 (The
Cluster ID field value is set by the CLUSTERID configuration pins.)

2,CPU ID: 視處理器的個數,例如四個處理器ID依序為 0×00,0×01,0×020×03

多核心的開機

一般我們稱為Boot Loader就是在OS前處理載入流程的動作,通常也稱為Boot
Code
或是Boot Monitor (ARM本身所出的Boot
Loader),
由於並非所有的Flash裝置都支援XIP
(Execute-in-Place),
因此針對像是NAND或是SD/eMMC這類裝置,就會需要有在SoC
BootRom
上的Boot Code支援對於Block裝置的讀取,以便順利載入第二階段的BootLoader,讓後續的流程如規劃進行.

筆者在整理本文時,有看到這篇文章"Booting
ARM Linux SMP on MPCore" (in 
http://geek43.springnote.com/pages/7909760?print=1 
或 http://www.linux-arm.org/pub/LinuxPlatform/RealViewLink/Booting_ARM_Linux_SMP_on_MPCore.doc),對於Linux
Kernel SMP
有興趣的讀者除了本文外,建議也可以參考.

由於NAND Flash需要處理 Bad
Block,
且軟體在作業系統檔案系統本身,針對NAND
Flash
裝置也需要支援ECC,FTL(Flash Translation Layer)與 Wear-Leveling機制,藉以避免在NAND
Flash
上的正確性問題,也因此,附帶上述演算法的硬體實現ControllereMMC也就被目前許多消費性產品所使用,一般而言,在低階的產品上NAND
Flash
還是有價格上的優勢,而在大容量儲存媒體的消費性產品中,eMMC則會有較高的性價比.

BootRom

MPCore,每個ARM的處理器一開始的記憶體位址都是0×00000000,通常我們可以有兩種方式提供啟動程式碼的執行,

1,NOR Flash

2,Boot Rom

由於單位儲存成本NOR Flash較高,因此在需要大儲存空間的產品上,會選擇透過NAND
Flash
儲存BootLoader與作業系統,因此為了讓系統可以順利的執行開機流程,就會透過晶片上的Boot
Rom
定位到位址0×00000000,並在其中儲存支援MPCore的程式碼.

在系統尚未啟動前,只有RTC Clock時脈為32.768KHz,而在系統啟動時,PLL(Phase
Locked Loop)
起震前,只有Boot Rom或是NOR Flash這類裝置可以用來執行處理器的指令集,因此在Boot
Rom
NOR Flash中的程式碼,就必須讓系統的PLL正常,以便可以達到最佳的處理器與平台效能,在系統初始化外部記憶體前,所使用的Stack或是可寫入的記憶體區塊就必須是 OnChipSRAM,直到外部記憶體被初始化後,才可以使用外部記憶體.

以支援NAND Boot的行為來說,Boot Rom會需要執行以下的行為

1,CPU0執行主要開機流程,其它的處理器進入WFI. (在啟動時,每個處理器可以透過CPU
ID
得知自己是否為CPU0,如果不是,就進入WFI的程式碼中.)

2,初始化外部記憶體與執行系統的初始化

3,設定 Stack

4,BootRom程式碼複製到外部記憶體中

5,重新Mapping 記憶體位置 (0×00000000位址對應到外部記憶體
或 I-TCM如果 0×00000000位址要跑中斷表的話(or 中斷表對應到0xffff0000))

6,把第二階段的BootLoader載入到外部記憶體中 or OnChip SRAM.

7,執行第二階段的BootLoader

到這階段為止,系統會維持在低速的運作中(例如 :P LL=19.2MHz)或是直接初始化PLL到最後的頻率(視所實作的SoC需求而定),外部記憶體也會進行初始化(包括要判斷記憶體的大小與初始化流程),讓第二階段的BootLoader載入到記憶體後可以直接執行.

U-Boot

NANDeMMC的方案中,UBoot通常會被Linux的產品定義為第二階段的BootLoader
(
也因為它所支援的互動命令介面彈性.).

首先,各位取得u-boot-2011.06-rc3版本的UBoot程式碼後,會看到包括如下的Source
Code
目錄,簡要說明如下

目錄 說明
api 提供包括Device Read/Write/Enum, Environment Get/Set/Enum,SysCall,Timers,Storage相關的介面.
common 主要為跟硬體與系統架構無關的檔案,包括透過Console控制命令處理與環境變數配置.
tools 提供包括GDB,Flash Updater..etc工具.
lib 提供CRC,BZLib,MD5,SHA1,軟體除法實作…etc函式庫
arch 為依據不同對應處理器架構與型號相關的底層程式碼,包括處理器arm,avr32,blackfin,m68k,microblaze,mips,nios2,powerpc,sh,sparcx86.

arch/arm/cpu配置為例,Cortex處理器的支援是在armv7目錄下,目前支援的Cortex處理器產品包括 TI的 omap3/omap4,Samsung的 s5pc1xx/s5pc2xx,Freescale的 mx5,ST-Ericsson的 u8500與 Nvidia的 tegra2
,

其他有關的檔案包括

u-boot.lds=>用以描述u-boot binary檔案的配置,以筆者手中的版本來說,在啟動u-boot,最先執行的為arch/arm/cpu/armv7/start.o

對應到Source Code為 arch/arm/cpu/armv7/start.S,我們可以透過這個檔案為起點,來追蹤u-bootCortex下的啟動流程.

cpu.c:支援在正式進入Linux,L1/L2 CacheFlush與啟用.Nvidia
Tegra2
處理器產品為例,有關的檔案還有

ap20.c:初始化 Cache,UART,PLL,Clock,CoreSight,Snoopy Control Unit(Cache Coherency Bus),啟動JTAG,暫停CPU1Clock,
PMU (Power Management Unit)
控制,CPU進入Reset (Tegra2為雙核),

board.c: 確認在板子上的記憶體顆粒大小,支援256,5121GB
RAM Size,
初始化DRAM,

lowlevel_init.S:初始化I/D-Cache,SMP Mode,支援 CPU/AVP Mode的冷開機(Cold
Boot).

timer.c:支援 Timerudelay相關函式.

board 主要為現有支援的板子,包括外部記憶體位址,硬體配置與u-boot.lds都會跟這目錄下對應的開發版硬體有關,由於支援的板子數量很多,Nvidia為例,共支援兩款板子harmonyseaboard
drivers UBoot支援豐富的Driver周邊,並且也從Linux Driver中擷取有關的資源,目前共支援以下Drvers種類

(坦白說我覺得UBoot做的有點太強大了,除了沒有多工排程,完整的TCPIP,MM,其他功能都算是頗有規模了)

bios_emulator : 可用以模擬x86 Real-Mode BIOS.

fpga : 用以支援 Xilinx,Altera,Virtex, Spartan, Stratix, Cyclon, Lattice的 FPGA開發環境.

i2c : 這在有包括 i2c的共用程式碼,以及針對每個平台,例如 TI
OMAP,Samsung,ST-Erricsson u8500..etc
系列的I2C控制介面

mmc : 用以支援MMC/SD這類記憶卡周邊的控制介面,並包括ARM
PL180,Atmel,PXA,OMAP,MX
相關處理器的平台.

pci : 用以支援PCI Bus,包括IXP,SH,Freescale,Tundra ..etc相關的PCI控制介面

qe : QE 全名為 QUICCQUICC(Quad Integrated Communications Controller) Engine 是一個FreescalePowerPC下的介面,QE設計目的在於讓CPUDSP,不需要去處理通訊端的封包,透過RISC處理器的可程式化通訊協定加速引擎,只要修改微程式碼就能支援不同的通訊協定及功能(包括IP/Ethernet,ATM,QoS).

spi : 用以支援 SPI介面,包括 Altera,Atmel,MX,OMAP,SH..etc.

video : 用以支援Display的介面,可在Uboot啟動過程中顯示圖像在LCM/LCD,

block : 用以支援 SCSI/MGDISK/IDE/SATA..etc介面的Block儲存媒體

gpio : 用以支援GPIO介面.包括會根據平台的差異,有各自的Base
Address
與行為.

input : 可用以支援Intel 8042/PS2介面的KeyboardMouse,在筆者拿到的這版Code(u-boot-2011.06-rc3),Mouse的部份是被Ignore.

mtd : Memory Technology Device的介面,可用以支援包括NAND/OneNAND/SPI/Jedec/CFI(Common
Flash Interface)
介面的Flash裝置,讓上層不需要去處理不同儲存媒體的差異,只要統一透過MTD介面操作即可.

pcmcia : 用以支援PCMCIA介面

rtc : 為 Real-Time Clock Controller 的驅動

twserial : 為一個Serial控制介面,例如 rtc4543 就須透過這個Serial介面進行Read/Write

watchdog : 支援 WatchDog (如果你認為所在平台需要的話),目前有FTWDT010Atmel
AT91SAM9x
上的實作

dma : 用以支援不同平台的Direct Memory Access Controller.

hwmon : 主要支援硬體的感知器,像是Thermometer

misc : 用以支援包括LED Service LightPMIC..etc

net :用以支援包括RealTek在內的各類網卡Driver

power :用以支援包括Faraday,TI平台的電源控制

serial :用以支援各類UART Serial Port.

usb : 用以支援 USB Ethernet,Host/Gadget Controller,提供包括OMAP,BlackFin,..etc相關平台..etc

post 全名為 power on self test,其中包括處理器,驅動與對應的Board形式
net 支援NFS,DNS,TFTP,SNTP..etc網路協定
fs 支援CramFS,Ext2,FAT,FDOS,JFFS2,ReiserFS,UbiFS,Yaffs2檔案系統
disk 主要為支援IDE/SCSI/SATA/MGDISK/USB DISK/MMC/SD Card的儲存媒體裝置,讓上層可以透過DISK裝置例如以LBA
Mode
去存取相關的DISK Sector,包括DISK裝置的Partition Table讀取,或是光碟裝置的ISO檔案,都可以加以識別與存取.
mmc_spl

onenand_ipl

nand_spl

用以支援存MMC/SD,OneNand或是Nand FlashUBoot載入到記憶體後,執行UBoot的環境,一般而言,我們可以選擇透過Boot
Rom
直接載入UBoot,或是透過NAND Flash裝置最前面可以保證出廠時不是Bad Block的區塊,來存放載入UBoot的前置載入程式.可以透過在lds檔案中加入ASSERT
(
例如:nand_spl/board/freescale/mpc8313erdb/u-boot.lds),確保NAND Flash Bootstrap不會超過目標  NAND
Flash
裝置第一個區塊的大小.

Uboot的維護網站在 http://www.denx.de/wiki/U-Boot ,有興趣的開發者,可以自行參閱.UbootSource
Code

抱歉!评论已关闭.