作者: Arnoldas Bagdonas 微控制器制造商的開(kāi)發(fā)板,以及他們與開(kāi)發(fā)板一起提供的軟件項目例程,在工程師著(zhù)手一個(gè)新設計時(shí)可以提供很大幫助。但在設計項目完成其早期階段后,進(jìn)一步設計時(shí),制造商提供的軟件也可能會(huì )導致一些問(wèn)題。 使用實(shí)時(shí)操作系統作為應用程序代碼平臺的設計還面臨著(zhù)許多挑戰,比如如何將功能分配給不同的并行任務(wù)、如何設計高可靠的進(jìn)程間通信、以及如何在硬件上測試整個(gè)軟件包等問(wèn)題。 越來(lái)越多的OEM廠(chǎng)商發(fā)現,避免上述兩個(gè)問(wèn)題的最好方式,是使用基于開(kāi)源、經(jīng)過(guò)驗證、可擴展、可運行在不同硬件平臺的操作系統Linux開(kāi)始新的設計。就已經(jīng)被移植到各種計算機硬件平臺的操作系統的數量來(lái)說(shuō),Linux首屈一指。Linux的衍生版本已運行在非常廣泛的嵌入式系統中,包括:網(wǎng)絡(luò )路由器、移動(dòng)電話(huà)、建筑自動(dòng)化控制、電視機和視頻游戲控制臺。 雖然Linux被成功使用,但并不意味著(zhù)它很容易使用。Linux包含的代碼超過(guò)一百萬(wàn)行,其運作帶有鮮明的Linux方法論味道,初學(xué)者可能難以迅速掌握。 因此,本文的主旨是為使用Linux的嵌入式操作系統版本——μClinux,開(kāi)始一個(gè)新的設計項目,該指南共分為五個(gè)步驟。為了說(shuō)明該指南,本文介紹了在意法半導體的STM32F429微控制器(ARM Cortex-M4內核,最高180MHz)上的一個(gè)μClinux項目實(shí)現,使用了Emcraft的STM32F429 Discovery Linux板支持包(BSP)。 步驟1:Linux工具和項目布局 每個(gè)嵌入式軟件設計都從選擇合適的工具開(kāi)始。 工具鏈是一組連接(或鏈接)在一起的軟件開(kāi)發(fā)工具,它包含諸如GNU編譯器集合(GCC)、binutils(一組包括連接器、匯編器和其它用于目標文件和檔案工具的開(kāi)發(fā)工具)和glibc(提供系統調用和基本函數的C函數庫)等組件;在某些情況下,還可能包括編譯器和調試器等其它工具。 用于嵌入式開(kāi)發(fā)的工具鏈是一個(gè)交叉工具鏈,更常見(jiàn)的叫法是交叉編譯器。 GNU Binutils是嵌入式Linux工具鏈的第一個(gè)組件。GNU Binutils包含兩款重要工具: ●“as”,匯編器,將匯編代碼(GCC所生成)轉換成二進(jìn)制代碼 ●“l(fā)d”,連接器,將離散目標代碼段連接到庫或形成可執行文件 編譯器是工具鏈的第二個(gè)重要組成部分。在嵌入式Linux,它被稱(chēng)為GCC,支持許多種微控制器和處理器架構。 接下來(lái)是C函數庫。它實(shí)現Linux的傳統POSIX應用編程接口(API),該API可被用來(lái)開(kāi)發(fā)用戶(hù)空間應用。它通過(guò)系統調用與內核對接,并提供高階服務(wù)。 工程師有幾種C函數庫選擇: ●glibc是開(kāi)源GNU項目提供的可用C函數庫。該庫是全功能、可移植的,它符合Linux標準。 ●嵌入式GLIBC(EGLIBC)是一款針對嵌入式系統優(yōu)化的衍生版。其代碼是精簡(jiǎn)的,支持交叉編譯和交叉測試,其源代碼和二進(jìn)制代碼與GLIBC的兼容。 ●uClibc是另一款C函數庫,可在閃存空間有限、和/或內存占用必須最小的情況下使用。 調試器通常也是工具鏈的一部分,因為在目標機上調試應用程序運行時(shí),需要一個(gè)交叉調試器。在嵌入式Linux領(lǐng)域,GDB是常用調試器。 上述工具是如此地不可或缺,但當它們各自為戰時(shí),會(huì )花太長(cháng)時(shí)間來(lái)編譯Linux源代碼并將其整合成最終映像(image)。幸運的是,Buildroot(自動(dòng)生成交叉編譯工具的工具)會(huì )自動(dòng)完成構建一個(gè)完整嵌入式系統的過(guò)程,并通過(guò)產(chǎn)生下述任一或所有任務(wù),簡(jiǎn)化了交叉編譯: ●交叉編譯工具鏈 ●根文件系統 ●內核映像 ●引導映像 對嵌入式系統設計師來(lái)說(shuō),還可以方便地使用一種工具(utility)聚合工具,如BusyBox,這種工具將通常最需要的工具整合在一起。根據BusyBox的信息頁(yè)面介紹,“它將許多常用UNIX工具的微型版本整合成一個(gè)小的可執行文件。它提供了對大多數你通常會(huì )在GNU fileutils和shellutils等工具中看到的工具的替代。BusyBox里的工具通常比其全功能GNU對應版本的選擇少;但所包含選項所提供的預期功能和行為則與對應的GNU所提供的幾無(wú)差別。對任何小或嵌入式系統來(lái)說(shuō),BusyBox提供的環(huán)境都是相當完整的! 最后一個(gè)重要工具是一款BSP,是為搭載了項目目標MCU或處理器的主板專(zhuān)門(mén)做的。 BSP包括預先配置的工具,以及將操作系統加載到主板的引導加載程序。它還為內核和器件驅動(dòng)器提供源代碼(見(jiàn)圖1)。 ![]() 圖1:用于STM32F429 Discovery板的Emcraft BSP的主要部件。 步驟2:引導序列、時(shí)鐘系統、存儲器和串行接口 典型的嵌入式Linux啟動(dòng)順序執行如下: 1)引導加載程序固件(示例項目里的U-Boot)運行于目標MCU內置閃存(無(wú)需外部存儲器),并在上電/復位后,執行所有必需的初始化工作,包括設置串口和用于外部存儲器(RAM)訪(fǎng)問(wèn)的存儲器控制器。 2)U-Boot可將Linux映像從外部Flash轉移到外部RAM,并將控制交接到RAM中的內核入口點(diǎn)?蓧嚎sLinux映像以節省閃存空間,代價(jià)是在啟動(dòng)時(shí)要付出解壓縮時(shí)間。 3)Linux進(jìn)行引導并安裝基于RAM的文件系統(initramfs)作為根文件系統。在項目構建時(shí),Initramfs被填充以所需的文件和目錄,然后被簡(jiǎn)單地鏈接到內核。 4)在Linux內核下,執行/sbin/init。/sbin/init程序按照/etc/inittab中配置文件的描述對系統進(jìn)行初始化。 5)一旦初始化進(jìn)程完成運行級執行和/sbin/init里的命令,它會(huì )啟動(dòng)一個(gè)登錄進(jìn)程。 6)殼初始化文件/etc/profile的執行,標志著(zhù)啟動(dòng)過(guò)程的完成。 通過(guò)使能就地執行(Execute In Place——XIP)可以顯著(zhù)縮短啟動(dòng)時(shí)間、提升整體性能,XIP是從閃存執行代碼的方法。通常,Linux代碼是從閃存加載到外部存儲器,然后從外部存儲器執行。通過(guò)從閃存執行,因不再需復制這步,從而只需較少的存儲器,且只讀存儲器不再占程序空間。 本文的示例項目基于STM32F429 MCU。事實(shí)上,用戶(hù)可能會(huì )發(fā)現,開(kāi)始時(shí),STM32F4系列MCU的外設初始化不容易掌握。幸運的是,意法半導體開(kāi)發(fā)了一些工具來(lái)幫助解決這一問(wèn)題。STM32CubeMX初始化代碼生成器(部件編號UM1718)屬于最新的。該工具包括外設初始化的每一個(gè)細節,在配置外設時(shí),會(huì )顯示警告和錯誤、并警告硬件沖突。 對小型嵌入式Linux項目來(lái)說(shuō),STM32F429 MCU內部閃存足夠用。重要的是要記。呵度胧絃inux項目中使用多個(gè)二進(jìn)制映像(引導加載程序、Linux內核和根文件系統):這些都需要閃存扇區邊界對齊。這就避免了在裝載一個(gè)圖像時(shí),另一圖像被部分刪除或損壞的風(fēng)險。 步驟3:在主機上安裝Linux 要構建一個(gè)嵌入式Linux項目,一臺Linux主機是必需的。對于Windows PC,最好是安裝Oracle VirtualBox,以創(chuàng )建“一臺”512Mbyte RAM和16Gbyte硬盤(pán)的新虛擬機。 有許多Linux版本可用;據筆者的經(jīng)驗,Debian就是與VirtualBox環(huán)境相匹配的一款。這款Linux主機必須能夠訪(fǎng)問(wèn)互聯(lián)網(wǎng),以便下載針對這款ARM Cortex-M目標MCU的GNU交叉編譯工具。設計師將創(chuàng )建一個(gè)類(lèi)似于圖1所示的樹(shù)形結構,并將交叉構建工具提存到/tools文件夾。 在這點(diǎn)上,有必要建立一個(gè)ACTIVATE.sh腳本。只需使用下列代碼就可實(shí)現。(<......>是提取到的GNU工具文件夾路徑): export INSTALL_ROOT=<.......> export PATH=$INSTALL_ROOT/bin:$PATH export CROSS_COMPILE=arm-uclinuxeabiexport CROSS_COMPILE_APPS=arm-uclinuxeabiexport MCU=STMDISCO export ARCH=arm 在干凈的Linux系統中安裝GNU工具,但其使用并非自給自足,實(shí)際上還需要其它系統的配合。其運行實(shí)際上依賴(lài)于若干其它系統組件(如主機C/C++編譯器、標準C函數庫頭文件,以及一些系統工具)。獲得這些必要組件的一種方法是安裝用于C的Eclipse集成開(kāi)發(fā)環(huán)境(IDE)。除解決這個(gè)迫在眉睫的問(wèn)題外,Eclipse IDE還可在開(kāi)發(fā)過(guò)程中的許多其它方面提供幫助,當然,詳述Eclipse IDE的特性不是本文目的。 現在,是時(shí)候啟用Linux終端工具了:點(diǎn)擊“應用程序(Applications)”,然后“附件(Accessories)”和“終端(Terminal)”(見(jiàn)圖2)。 ![]() 圖2:Linux包含的“終端(Terminal)”工具和“文件(Files)”、一種類(lèi)似Windows資源管理器的圖形化工具。 終端是用于配置Linux主機和構建嵌入式Linux應用程序的主要工具。鍵入以下命令來(lái)安裝Eclipse和其它所需工具: su [輸入根用戶(hù)密碼] apt-get install eclipse-cdt apt-get install genromfs apt-get install libncurses5-dev apt-get install git apt-get install mc 準備該Linux項目的最后一步是下載STM32F429 Discovery Buildroot,并解壓到/uclinux文件夾。 步驟4:用Buildroot構建μClinux 現在有必要關(guān)閉先前使用根用戶(hù)配置文件的終端,并啟動(dòng)一個(gè)新終端。在命令行中輸入“mc”,并使用導航器導航到“Documents”,然后輸入“uClinux”命令。按Ctrl+O并激活Linux ARM Cortex-M開(kāi)發(fā)部分,并運行“.ACTIVATE.sh”命令。再次按下Ctrl+O并進(jìn)入“stm32f429-linux-builder-master”文件夾。 用戶(hù)現在有兩個(gè)選擇。如果使用VirtualBox中的示例項目,請遵循“make clean”和“make all”命令序列。如果準備一個(gè)全新環(huán)境,使用“make”命令。約30分鐘后,新的μClinux映像將可用,如下所示: out\uboot\u-boot.bin out\kernel\arch\arm\boot\ xipuImage.bin out\romfs.bin 將這些新映像寫(xiě)入閃存。如果使用Windows和ST-LINK工具,下面的代碼將工作: ST-LINK_CLI.exe -ME ST-LINK_CLI.exe -P “u-boot.bin” 0x08000000 ST-LINK_CLI.exe -P “xipuImage.bin” 0x08020000 ST-LINK_CLI.exe -P “romfs.bin” 0x08120000 將串行調試器(serial console)連接到目標電路板(外部RX=>PC10、外部TX=>PC11、115200bits/s、8個(gè)數據位、無(wú)奇偶校驗、1個(gè)停止位模式),然后按下復位按鈕,該μClinux項目將啟動(dòng)運行。開(kāi)機輸出將顯示在串行調試器上,顯示屏將出現Linux的企鵝標識。 步驟5:創(chuàng )建“你好,世界”應用 現在,按照代碼示例和下面的說(shuō)明,將一個(gè)用戶(hù)應用添加到μClinux項目中。 創(chuàng )建:“stm32f429-linux-builder-master/user/src/hello.c”文件: #include int main() { printf(“Hello, world\n”); return 0; } 必要時(shí)使用Tab鍵,創(chuàng )建:“stm32f429-linux-builder-master/user/Makefile”文件: CC = $(CROSS_COMPILE)gcc LDFLAGS ?=$(CFLAGS) target_out ?= out all: checkdirs [Tab] $(CC) $(LDFLAGS) src/hello/hello.c -o $(target_out)/bin/ hello $(LDLIBS) [Tab] -rm -rf $(target_out)/bin/*.gdb checkdirs: [Tab] mkdir -p $(target_out)/bin clean: [Tab] -rm -rf $(target_out) 通過(guò)activate.sh腳本,在不激活交叉編譯環(huán)境下,在主機測試“Hello, world”這個(gè)應用。 在/user文件夾下,輸入: make all ./out/bin/hello 為將hello.c嵌入到Linux Buildroot里的腳本,修改mk/rootf.mak文件,必要時(shí),使用Tab鍵。(粗體字表示新行開(kāi)始處): . . . user_hello: [Tab] make -C $(user_dir) CROSS_COMPILE=$(CROSS_ COMPILE) CFLAGS=$(ROOTFS_CFLAGS) target_ out=$(target_out_user) $(rootfs_target): $(rootfs_dir) $(target_out_busybox)/.config user_hello [Tab] cp -af $(rootfs_dir)/* $(target_out_romfs) [Tab] cp -f $(target_out_kernel)/fs/ext2/ext2.ko $(target_out_romfs)/lib/modules [Tab] cp -f $(target_out_kernel)/fs/mbcache.ko $(target_out_romfs)/lib/modules [Tab] cp -f $(target_out_user)/bin/* $(target_out_romfs)/usr/bin … 需對mk/defs.mak文件做最后修改。加入以下幾行: . . . user_dir := $(root_dir)/user target_out_user := $(target_out)/user user_dir := $(root_dir)/user target_out_user := $(target_out)/user 一旦在目標MCU上建成、下載并運行映像,就可在/usr/bin目錄中找到該應用程序以及其它已有的應用程序。在連接到Discovery板的終端上鍵入“hello[回車(chē)]”,可對該應用進(jìn)行測試。 |