拿到一塊YC2440(s3c2440)的開發板,經過幾天的學習,我對arm-linux系統開發步驟有了一些認識。就以開發這個開發板為例,arm-linux開發工作大概分4個部分
1. 硬件(hardware)
2. 引導加載器(bootloader)
3. 內核(kernel)
4. 文件系統(file system)
硬件
我並不是硬件工程師,但我知道硬件的設計基本上是從性能,結構,可靠性等方面的需求方面來考慮。比如串口調試很常用,那么硬件就需要設計串口。在比如硬件需要接LCD,就必須提供LCD接口。
bootloader
bootloader是什么?
bootloader是一個引導程序,它最主要的功能是加載內核,所謂加載內核就是讓內核代碼常駐內存,並且得到執行。
bootloader因為什么而存在?
每一種CPU都有自己的啟動方式
a) CPU上電后從某個地址開始取指令運行,這樣的指令往往是已經固化的,因為RAM剛上電時,里面的內容是沒有意義的,很多單片機是這樣方式。可以說這根本不是boot
b) CPU上電后從ROM讀代碼到RAM,然后跳到RAM里開始執行,這種方式的CPU一般會拷貝固定長度的二進制代碼到RAM,因為它不知道有效代碼有長,只有一個固定的長度拷貝完成后,CPU才知道拷貝工作完成,以便從RAM執行。這就是boot
c) 方式二只能拷貝固定長度的代碼到RAM運行,為了拷貝更多的代碼到RAM運行,方式二就做了改進,首先進入RAM的代碼不是一個功能固件,而是另一個功能代碼的加載器(loader),這就是bootloader了
arm的bootloader
arm會拷貝4K長度的代碼運行。顯然arm不是為4K的固件設計的。拷貝代碼到RAM並不需要很多指令,因為ARM對RAM的管理需要一個MMU控制器(可以讓CPU訪問更多的RAM或許)而這個控制器需要配置相關寄存器,所以代碼可能要多一點,另外可能還有許多別的功能,所以代碼可能會更多。當然都不超過4K時都沒問題,但往往還是要過4K的。所以真正arm-linux的bootloader一般有兩步驟:
a) 拷貝4K代碼到RAM,開始執行
b) 拷貝另一段代碼到RAM並初始化一些必須的硬件設置,開始執行
u-boot
u-boot是一種很流行的bootloader,除了加載內核,它還提供了許多其他功能。基本上u-boot是一個精簡的linux,它提供人機交換的,一般現在linux開發都采用串口方式使用u-boot。
關於u-boot的說明有很多,我簡單說明一下
a) u-boot可以被打斷,通過串口向u-boot輸入命令后,u-boot中斷,可以執行各種命令,這些命令有專門的手冊可以查詢。串口其實就是u-boot的一個遠程終端。
b) u-boot可以設置網絡,通過tftp服務,u-boot可以下載代碼到RAM然后執行,也可以燒寫到flash
c) u-boot之所以有這么多功能是因為里面集成了許多驅動,如果要讓u-boot有更多的功能可以在u-boot源代碼里添加,如果要用硬件就需要添加驅動。
d) 如果要修改u-boot需要。。編譯。。。。。。。。。。。。
內核
Linux內核部分是工作量比較多的部分
1. 交叉編譯
2. BSP
3. Kconfig以及內核裁減
4. 鏡像制作和燒寫
交叉編譯
關於交叉編譯,網絡上有很多文章。以ubuntu 8.10說明一下:
a) 下載編譯器,比如arm-linux-gcc 3.4.1
b) sudo tar vxjf arm-linux-gcc 3.4.1.bz2 –C /
c) 命令行編譯需要設置環境變量
sudo gedit /etc/bash.bashrc
在文件最后添加 export PATH=$PATH:/usr/local/arm/3.4.1/bin
重新登錄
d) arm-linux-gcc –v 查看版本便知道交叉編譯器是否安裝成功
BSP
Linux的BSP其實就是外設驅動集合。比如擴了一個串口,需要編寫設備驅動。關於設備驅動編寫是一個很大的話題,我想這是另外需要一本書的《Linux Device Driver.3rd Edition》。看不懂可以看看參考http://www.deansys.com/doc/ldd3/index.html。
Kconfig以及內核裁減
Kconfig是用於定制內核的,有了交叉環境、BSP以及內核源碼后,就可以做Kconfig.源碼包的Makefile需要從.config得到信息以便把需要的東西編譯到內核,不需要的東西不放進來,這樣的內核是最精簡有效的。問題是這些信息是龐大的,正如管理一個大的工程用Makefile一樣,管理一個越來越復雜的內核用Kconfig。
以下引用自互聯網
Kconfig文檔的作用
內核源碼樹的目錄下都有兩個文檔Kconfig(2.4版本是Config.in)和Makefile。分布到各目錄的Kconfig構成了一個分布式的內核配置數據庫,每個Kconfig分別描述了所屬目錄源文檔相關的內核配置菜單。在內核配置make menuconfig(或xconfig等)時,從Kconfig中讀出菜單,用戶選擇后保存到.config的內核配置文檔中。在內核編譯時,主Makefile調用這個.config,就知道了用戶的選擇。
*上面的內容說明了,Kconfig就是對應着內核的配置菜單。假如要想添加新的驅動到內核的源碼中,能夠修改Kconfig,這樣就能夠選擇這個驅動,假如想使這個驅動被編譯,要修改Makefile
so添加新的驅動時需要修改的文檔有兩種(注意不只是兩個)
*Kconfig
*Makefile
要想知道怎么修改這兩種文檔,就要知道兩種文檔的語法結構
Kconfig
每個菜單都有一個關鍵字標識,最常見的就是config
語法:
config
symbol是個新的標記的菜單項,options是在這個新的菜單項下的屬性和選項
其中options部分有:
1、類型定義:
每個config菜單項都要有類型定義,bool布爾類型、 tristate三態:內建、模塊、移除 string字符串、 hex十六進制、 integer整型
例如config HELLO_MODULE
bool "hello test module"
bool類型的只能選中或不選中,tristate類型的菜單項多了編譯成內核模塊的選項,假如選擇編譯成內核模塊,則會在.config中生成一個CONFIG_HELLO_MODULE=m的配置,假如選擇內建,就是直接編譯成內核影響,就會在.config中生成一個CONFIG_HELLO_MODULE=y的配置.
2、依賴型定義depends on或requires
指此菜單的出現和否依賴於另一個定義
config HELLO_MODULE
bool "hello test module"
depends on ARCH_PXA
這個例子表明HELLO_MODULE這個菜單項只對XScale處理器有效。
3、幫助性定義
只是增加幫助用關鍵字help或---help---
內核的Makefile
在linux2.6.x/Documentation/kbuild目錄下有周詳的介紹有關kernel makefile的知識。
內核的Makefile分為5個組成部分:
Makefile 最頂層的Makefile
.config 內核的當前配置文檔,編譯時成為定層Makefile的一部分
arch/$(ARCH)/Makefile 和體系結構相關的Makefile
s/ Makefile.* 一些Makefile的通用規則
kbuild Makefile 各級目錄下的大概約500個文檔,編譯時根據上層Makefile傳下來的宏定義和其他編譯規則,將源代碼編譯成模塊或編入內核
頂層的Makefile文檔讀取 .config文檔的內容,並總體上負責build內核和模塊。Arch Makefile則提供補充體系結構相關的信息。 s目錄下的Makefile文檔包含了任何用來根據kbuild Makefile 構建內核所需的定義和規則。
(其中.config的內容是在make menuconfig的時候,通過Kconfig文檔配置的結果。
舉個例子:
假設想把自己寫的一個flash的驅動程式加載到工程中,而且能夠通過menuconfig配置內核時選擇該驅動該怎么辦呢?能夠分三步:
第一:將您寫的flashtest.c 文檔添加到/driver/mtd/maps/ 目錄下。
第二:修改/driver/mtd/maps目錄下的kconfig文檔:
config MTD_flashtest
tristate “ap71 flash"
這樣當make menuconfig時 ,將會出現 ap71 flash選項。
第三:修改該目錄下makefile文檔。
ü 添加如下內容:obj-$(CONFIG_MTD_flashtest) += flashtest.o
這樣,當您運行make menucofnig時,您將發現ap71 flash選項,假如您選擇了此項。該選擇就會保存在.config文檔中。當您編譯內核時,將會讀取.config文檔,當發現ap71 flash 選項為yes 時,系統在調用/driver/mtd/maps/下的makefile 時,將會把 flashtest.o 加入到內核中。即可達到您的目的
make menuconfig后這個藍色的終端里,有許多復雜的配置,根據需要配置好后保存就可以了。
ubuntu 8.10出現make menuconfig失敗,一堆錯誤,這個需要
sudo apt-get install libncurses5-dev
鏡像制作和燒寫
內核鏡像是被bootloader加載的,比如u-boot可以把內核鏡像加載到RAM並執行。制作u-boot可加載的鏡像需要使用mkimage工具,所以
sudo cp ~/tools/mkimage /usr/bin
make uImage
需要注意的是如果mkimage權限不對make uImage是會出錯的,可以設置一下權限
sudo chmod 777 /usr/bin/mkimage
如果一切成功那么在linux-xxxx/arch/arm/boot下就有uImage文件了。
如果要更清楚里面的細節,需要對mkimage做進一步了解。
燒寫的工作還是交給u-boot吧,大概工作是這樣的:
a) 中斷u-boot
b) 需要一個tftp服務器,比如Windows XP下安裝tftpwin就可以了
c) 調用u-boot命令啟動下載燒寫
轉:https://www.cnblogs.com/iwasmu/archive/2009/05/29/1491570.html