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處理器的行為,有關MPCore與Linux
Kernel SMP的支援相信都是能夠游刃有餘的.
由於筆者時間關係,本文會分段刊登,還請見諒.
Linux Kernel對多核心的支援
Linux從Kernel 2.0開始,就已經加入對SMP (Symmetric
Multi Processors)的支援,Linux Kernel會以Process或是Kernel Thread為單位來對排程,也就是說Process或Kernel
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×02與0×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上的正確性問題,也因此,附帶上述演算法的硬體實現Controller的eMMC也就被目前許多消費性產品所使用,一般而言,在低階的產品上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或是可寫入的記憶體區塊就必須是 OnChip的SRAM,直到外部記憶體被初始化後,才可以使用外部記憶體.
以支援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
到這階段為止,系統會維持在低速的運作中(例如 LL=19.2MHz)或是直接初始化PLL到最後的頻率(視所實作的SoC需求而定),外部記憶體也會進行初始化(包括要判斷記憶體的大小與初始化流程),讓第二階段的BootLoader載入到記憶體後可以直接執行.
U-Boot
在NAND或eMMC的方案中,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,sparc與x86.
以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-boot在Cortex下的啟動流程.
cpu.c:支援在正式進入Linux前,對L1/L2 Cache的Flush與啟用.以Nvidia
ap20.c:初始化 Cache,UART,PLL,Clock,CoreSight,Snoopy Control Unit(Cache Coherency Bus),啟動JTAG,暫停CPU1的Clock,
board.c: 確認在板子上的記憶體顆粒大小,支援256,512與1GB
lowlevel_init.S:初始化I/D-Cache,SMP Mode,支援 CPU/AVP Mode的冷開機(Cold timer.c:支援 Timer與udelay相關函式. |
board | 主要為現有支援的板子,包括外部記憶體位址,硬體配置與u-boot.lds都會跟這目錄下對應的開發版硬體有關,由於支援的板子數量很多,以Nvidia為例,共支援兩款板子harmony與seaboard |
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
mmc : 用以支援MMC/SD這類記憶卡周邊的控制介面,並包括ARM pci : 用以支援PCI Bus,包括IXP,SH,Freescale,Tundra ..etc相關的PCI控制介面 qe : QE 全名為 QUICCQUICC(Quad Integrated Communications Controller) Engine 是一個Freescale在PowerPC下的介面,QE設計目的在於讓CPU或DSP,不需要去處理通訊端的封包,透過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 input : 可用以支援Intel 8042/PS2介面的Keyboard與Mouse,在筆者拿到的這版Code中(u-boot-2011.06-rc3),Mouse的部份是被Ignore的.
mtd : 為Memory Technology Device的介面,可用以支援包括NAND/OneNAND/SPI/Jedec/CFI(Common pcmcia : 用以支援PCMCIA介面 rtc : 為 Real-Time Clock Controller 的驅動 twserial : 為一個Serial控制介面,例如 rtc4543 就須透過這個Serial介面進行Read/Write
watchdog : 支援 WatchDog (如果你認為所在平台需要的話),目前有FTWDT010與Atmel dma : 用以支援不同平台的Direct Memory Access Controller. hwmon : 主要支援硬體的感知器,像是Thermometer misc : 用以支援包括LED Service Light或PMIC..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 Flash把UBoot載入到記憶體後,執行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 ,有興趣的開發者,可以自行參閱.在Uboot的Source
Code中