潘亞文,李宏華,蔣紫韻,吳春法
(閩南科技學院 光電信息學院,福建 泉州 362332)
嵌入式系統開發包括裸機程序開發、系統移植和應用程序開發。啟動是指系統上電后CPU從運行的第一條指令開始到運行裸機程序或應用程序為止的過程。其中裸機程序開發和系統移植會涉及到啟動過程,目前的啟動文獻絕大多數都是介紹基于系統移植U-boot的啟動運行[1-3],實際上還有很多裸機程序的啟動運行,這兩者的啟動有很大區別。實際應用中許多嵌入式系統開發都是裸機程序開發,因此理清這一啟動過程,有助于整個嵌入式系統的開發。
裸機程序開發[4]從本質來說就是三個問題:一是怎樣生成裸機.bin可執行程序;二是怎樣將裸機.bin可執行程序燒到SoC中并啟動運行;三是裸機程序的啟動過程。第一個問題涉及到嵌入式開發環境,目前有集成開發環境和交叉編譯開發環境兩種[5-7]。第二個問題總體來說包括三類燒寫方法:第一類是直接通過集成軟件將.bin文件燒寫到存儲介質并運行[8];第二類是通過第三方軟件將.bin文件直接燒寫到存儲介質中運行[9];第三類是通過U-boot燒寫.bin文件并運行。對于第三個問題裸機程序的啟動過程與第二個問題息息相關,燒寫方法不同,啟動過程也有所不同,下文將詳細論述。
在單片機應用中,裸機程序的開發只需要在Keil集成開發環境中就可以完成,簡單容易上手。而嵌入式系統開發相對復雜,針對目前嵌入式系統裸機程序的開發可以分為兩種開發環境:一種是集成開發環境,另一種是自己搭建的免費交叉編譯開發環境。
由于目前嵌入式系統芯片80%以上都是ARM內核,所以在此主要介紹針對ARM內核芯片的集成開發環境。一個嵌入式可執行程序的開發分為源程序編輯,匯編、編譯、鏈接生成.bin二進制文件,調試、運行等開發步驟。所謂集成就是把上述幾個步驟同時集成到一個開發環境之中。目前世界上針對不同的芯片集成開發環境有很多種,ARM公司針對ARM系列芯片面向全球開發者提供ADS和Keil MDK兩大主流集成開發環境。ADS2020最新版支持Cotex-M、Cotex-A、Cotex-R系列最新芯片,Keil MDK完美支持Cortex-M、Cortex-R4、ARM7和ARM9等系列芯片。集成開發環境使用簡單方便,功能齊全,開發效率高,但因它是收費軟件,阻攔了大部分中小公司對其的使用。許多高校及個人仍然使用一些低版本的集成開發環境,以利于學習。
因為集成開發環境需要收費,所以ARM+Linux免費交叉編譯開發環境成為越來越多的中小企業和眾多愛好者的選擇。目前ARM+Linux免費交叉編譯開發環境是一種主流,對于進入嵌入式系統世界的開發人員這也是需要掌握的必備技能。X86架構是通用計算機芯片的架構,ARM是嵌入式系統的芯片架構,在通用計算機系統里編譯出可以在ARM架構下運行的程序就是交叉編譯,其結構如圖1所示。ARM+Linux交叉開發環境需要開發者自己在Linux操作系統下搭建編譯環境,選擇合適的ARM編譯工具鏈,因此,開發者需要掌握Linux下的各種開發流程。這種開發方式源程序編輯一般在主機Windows下編輯,可執行的.bin文件在Linux下生成,而運行又在目標機嵌入式系統里執行,因此,這種方式比較復雜。

圖1 交叉編譯開發環境
以A8處理器為例,其交叉編譯環境的搭建過程如下:
(1)在PC端安裝虛擬機VMware軟件。
(2)在VMware里安裝發行版Linux操作系統。
(3)從官方網站http://www.crosstool-ng.org下載已制作好的適合Cotex-A8的交叉編譯工具鏈,如arm-cotex_a8-linux-gnueabi.tar.bz2。
(4)解壓下載好的工具鏈。
$ cd /opt
$ tar xjf arm-cotex_a8-linux-gnueabi.tar.bz2
(5)在環境變量PATH里添加工具鏈的bin目錄。
$ export PATH=$PATH:/opt/tools/arm-cotex_a8-linuxgnueabi.tar.bz2
(6)在/etc/environment文件里添加bin目錄使當前用戶不失效工具鏈命令。
這里啟動是指嵌入式系統啟動運行生成的.bin文件,由于S3C2240芯片是以一款ARM9為內核入門級的經典芯片,資料豐富,所以以S3C2440芯片為例說明從NAND FLASH和NOR FLASH啟動裸機程序的過程。
2.1.1 NAND FLASH啟動
以S3C2440芯片為例說明從NAND FLASH啟動。NAND FLASH存儲介質的特點是容量大、體積小、速度慢、價格低廉,但不能作為運行內存,常作為存儲介質[10]。但是對于S3C2440芯片,如果從NAND FLASH啟動,芯片會自動把NAND FLASH前4 KB的內容復制到S3C2440內部的SRAM(steppingstone)中,SRAM也只有4 KB,同時把內部的SRAM映射到內存nGCS0片選空間0x00000000,系統從SRAM的0x00000000開始運行。因此如果裸機程序的.bin文件小于4 KB,可以將程序燒寫到NAND FLASH中直接啟動,這是一種啟動裸機程序的方式,但是源程序一開始需要做必要的芯片級初始化工作。
另一種NAND FLASH的啟動方式是將U-boot放在NAND FLASH中,前4 KB的內容非常寶貴,做最基本的初始化包括初始化SDRAM的工作。然后通過U-boot將裸機程序的.bin文件下載到SDRAM中,然后跳到SDRAM中運行.bin裸機程序。這也是一種常見而簡單的運行.bin裸機程序的方法。
2.1.2 NOR FLASH啟動
同樣以S3C2440芯片為例說明NOR FLASH啟動。NOR FLASH的特點是容量很小、體積大、速度快、價格貴,主要是CPU能直接對其總線式讀操作,因此常作為啟動介質[11]。如果S3C2440選擇NOR FLASH啟動,NOR FLASH被映射到0x00000000,CPU直接從NOR FLASH開始運行。因此裸機程序的.bin文件可以直接燒寫到NOR FLASH中運行。需要注意的是源程序一開始需要通過匯編程序做必要的芯片級初始化工作。
Cotex-A8處理器是一款高端處理器,主頻最高可達1 GHz,目前應用在上網本、機頂盒、數字電視、家庭網絡、打印機、智能家居等領域。其啟動方式也很多,下面介紹以Cotex-A8為內核三星公司的S5PV210芯片啟動運行程序的過程。
S5PV210系統上電后先從具有類似NOR FLASH功能的內部IROM中讀取預先設置的代碼BL0并執行。這一段IROM代碼是三星出廠前設置的,由于不知道將來怎樣外接SDRAM,因此這一段IROM是不能初始化外接SDRAM的,這一段IROM代碼只能做一些基本的芯片級初始化工作。同時這一段代碼會通過OM0~OM5引腳電平判斷選擇啟動模式,S5PV210支持的幾種啟動模式見表1所列,然后從相應的外部存儲介質去讀取啟動代碼到內部IRAM中執行。基于上述過程,第一種方法可以把裸機程序.bin文件放入表1的存儲介質中就可以啟動運行;第二也可以直接把裸機程序下載到內部IRAM中運行,經驗證通過USB方式把.bin文件下載到內部SRAM的0xd0000010處可以運行裸機程序;第三可以通過U-boot下載運行裸機程序的.bin文件,這需要先啟動U-boot,然后下載裸機程序的.bin文件并運行。

表1 S5PV210的啟動模式
下面開始介紹三個開發板,三種不同的啟動流程,以理解嵌入式裸機程序的啟動及運行。
這里的集成開發環境是武漢創維特公司開發的ADT集成開發環境,開發板SOC是S3C2440,實驗中是將裸機程序下載到NOR FLASH中運行。由于在集成開發環境中編輯源程序及燒寫程序到NOR FLASH中并執行的過程簡單,這里不在祥述。需要注意的是這樣的裸機源程序由一段匯編代碼和C代碼組成,匯編代碼做基本的初始化工作并最終跳到C代碼中執行,C代碼是完成裸機程序功能的代碼段。匯編代碼段的功能:關看門狗;關總中斷;關SUB子中斷;配置時鐘寄存器以減少PLL鎖相時間;配置MPLL設置時鐘頻率;設置內存控制寄存器;初始化棧;設置IRQ中斷處理程序;初始化存儲器中的數據;跳轉到C代碼main函數中運行。
這里的交叉編譯環境選擇ARM+Linux,默認在Windows下通過虛擬機已搭建好,U-boot也已經燒錄到NAND FLASH中。開發板搭載內核為Cortex-A53系列高性能八核三星處理器S5P6818,其最高主頻高達1.4 GHz。由于是通過U-boot將裸機程序燒寫到SDRAM中運行,U-boot一開始做了許多初始化工作,所以源程序編輯不需要匯編代碼,只需要C代碼就可以。其啟動及運行過程如下:
(1)編輯需要運行的裸機C代碼;
(2)將C代碼移動到VMWare下的Linux操作系統下;
(3)利用交叉編譯工具鏈編譯C代碼得到.bin文件;
(4)將.bin文件移動到Windows系統下;
(5)配置超級終端,使開發板與主機連接;
(6)啟動開發板,進入U-boot模式;
(7)配置開發板IP和主機IP使相互之間可以ping通;
(8)將裸機.bin文件上傳到TFTPD32軟件里;
(9)U-boot下燒 寫.bin文件到SDRAM,例如 tftp 0x40000000 pwm.bin;
(10)跳到SDRAM下執行裸機代碼.bin,例如 go 0x40000000。
經過上述步驟,裸機程序就可以通過U-boot在SDRAM中啟動運行。
這里的交叉編譯環境是ARM+Linux,默認在Windows下通過虛擬機已搭建好。開發板搭載內核為Cortex-A8 系列高性能三星處理器S5PV210。由于IROM中的啟動代碼BL0做了芯片級初始化工作,所以這里的源程序不需要匯編代碼來初始化。S5PV210裸機程序啟動流程如圖2所示,其運行過程如下:
(1)編輯需要運行的裸機C代碼;
(2)將C代碼移動到VMWare下的Linux操作系統下;
(3)利用交叉編譯工具鏈編譯C代碼得到.bin文件;
(4)將.bin文件移動到SD卡里;
(5)選擇相應的OM管腳電平開機即可啟動目標板運行裸機程序。

圖2 S5PV210裸機程序啟動流程
將.bin文件移到SD卡后,開機目標板,首先運行S5PV210內部IROM中的程序BL0,并根據OM管腳選擇,將SD卡的.bin文件讀到S5PV210內部的IRAM中運行,裸機程序得以運行。
綜上所述,啟動運行裸機程序的方法有很多,但不論哪種方法都需要理清開機運行從第一行代碼,直到整個裸機程序結束的過程才能很好地進行嵌入式開發。需要注意的是有的啟動方法源程序是由基本初始化的匯編代碼和C代碼組成,有的啟動方法只需要C代碼。只需要C代碼的啟動方法中,C代碼運行之前一定是在其他地方提前做好了初始化工作,比如通過U-boot下載運行裸機程序,U-boot事先做了初始化,其中S5PV210通過SD卡啟動,S5PV210在內置的IROM里BL0做了基本的初始化。