嵌入式linux內核和根文件系統可以存放在各種可能的存儲設備中,一般情況下我們將內核和根文件系統直接燒入到Flash中(包括NOR和NAND flash),這種方法的缺點是在內核和根文件系統出現修改時我們就不得不得重新對flash進行擦除和燒寫工作,這個非常耗時,在產品開發調試階段非常不適合,只有在最終成品時才比較適用。哪在開發階段採用哪種方式比較好呢?先還是看看現在都有些常用的存儲設備吧。我們常見的存儲設備有:硬盤,U 盤,SD卡,Flash,還有一種其實是藉助網絡而將其存儲到遠程機器上的方法,我們常聽說的網絡硬盤,就是藉助TCP/IP協議從遠處將數據下載到機器來進行工作,很多網吧就採用這樣的“無盤系統”技術,其實並不是沒有盤,而只是這個存儲設備不在本地機器上而已。
從上面這些我們可以得出幾種加載引導linux內核的方法:
1.網絡。即將內核和根文件系統存儲在PC機上,通過網絡協議來將數據下載到開發板中。內核和根文件系統都可以通過tftp或者ftp下載到目標板上,當然根文件系統其實是沒有必要下載到目標板上,我們可以採用NFS文件系統來掛載。
2.SD/MMC 卡引導。將內核和根文件系統存儲在SD卡中,在啓動時通過讀SD卡,來將內核讀入到內存中。根文件可以讀到內存中,也可以由內核直接將SD卡直接掛載爲根文件系統。這裏需要文件系統的支持,常用的有FAT和EXT2。這樣在內核和根文件系統更新時,只需要從新寫SD卡就可以了。
3.U盤引導。這個需要目標板有USB HOST接口。同時也需要文件系統支持。其操作與SD卡引導類似。
4.硬盤/CF卡引導。這個也前面兩個類似,只需要其操作起來也不方便。主要因爲硬盤目前不支持熱拔插,而且對目標板也有要求,一般的嵌入式設備很少需要硬盤。
5.flash引導。這個就是我們最常用的,可以常用非常多中方式和多種文件系統,包括ext2,jffs2,yaffs2,cramfs等等。
另外一種引導的方式就是通過串口直接下載內核和文件系統到內存中,或者使用調試器與仿真器通過調試通道將內核和根文件系統加載到內核,然後在調試器中通過命令引導內核。
要實現這些引導方式,那麼bootloader就必須要支持上面需要的功能,我們來看看這個bootloader可能的需求:
1.支持TCP/IP協議,並實現tftp或者ftp協議。
2.文件系統的支持。可能需要支持fat,ext2,jffs2,yaffs2,cramfs等。
3.SD/MMC協議支持
4.USB Host驅動代碼
5.基於MTD的Flash驅動和設備的支持。
6.IDE/CF接口的支持(不必要)。
要完成這些功能並不簡單,從零開發的話,可以說是非常大的項目,如果再加一個調度器的話那就是一個小的操作系統了,還是先看看現有的各種bootloader吧。常見的有:
1.uboot
2.redboot
3.vivi
其實uboot中就已經實現了我們需要的所有功能了,而且它支持非常多的目標板和體系結構。redboot是ecos的一部分,其功能沒有uboot那麼強大,而且其移植也並不那麼簡單,支持的開發板也少,而且資料不怎麼太好找。vivi主要從的三星的芯片上,功能也不多,而且侷限很多。所以推薦使用 uboot,最新的uboot應該是u-boot-2009.08。其與原來的uboot-1.1.6修改很多,配置方面有所修改。
上面這幾種引導方式,在開發階段選擇一種就好了。把一種調試好了就進行內核和驅動的開發吧。當然花費在其上的時間是不會浪費的。“磨刀不誤砍柴工”。推薦使用網絡引導方案,先通過tftp下載內核到內存,再通過NFS掛載根文件系統,調試和開發都方便。如果沒有網絡可用,可以考慮SD或U盤引導,SD卡引導要簡單點,最後實在沒辦法那就直接燒寫flash吧。對於學習我們可以試嘗用這幾種方法來比較一下,並好好總結,等到上戰場的時候就可以用上了。最好要有積累。如果我們做的好的話,各種功能都是模塊化,就算開發開發一個bootloader也只是一個各種模塊的組裝和平臺相關的移植。
最後當然也可以自己動手去實現一個bootloader,這個雖然很費時間,但意義還是很重大的。各種功能可以慢慢的加上,先設計可以基本功能的 bootloader,可以邊做邊參考uboot,你會發現自己在寫代碼的水平會有一個很大的飛躍。像如何編寫平臺無關代碼;怎樣進行代碼抽象;如何編寫可移植性,適應性強,健壯的代碼;C語言的各種特性的使用特別是指針和函數的使用;學會如何實現程序的可配置等等。
-------------------------------------------------------------網絡方式示例-------------------------------------------------------------
驅動開發前期準備工作(NFS掛載):
那爲什麼要用NFS掛載來作爲驅動開發的首選呢?因爲你在未開發正確的驅動的時候,你要不停地做修改,如果你每改一次就要燒寫一次根文件系統這樣很浪費時間,而NFS掛載是把你的根文件系統放在你的開發機上,而開發板上並沒有,所以有修改,立刻可以體現在開發板上。
言歸正傳,首先講一下應該怎樣NFS掛載根文件系統,我也是網上搜集了一些資料和跟同事要了一些資料,如果跟別人寫的一樣的,那請見諒,因爲這些資料我也不知道來源。
平臺:Windows7用虛擬機Fedora14
準備已經編譯好的u-boot.bin uImage rootfs。
一、u-boot編譯與燒寫
1、打開DNW,選擇NOR端口,輸入“v”,講u-boot.bin燒寫進nand flash
2、選擇NAND端口,重啓開發板,出現以下界面:(此爲超級終端下運行)
二、U-BOOT相關設置
1、在超級終端下鍵入u-boot的命令
# setenv ipaddr ****** (開發板IP)
# setenv serverip ****** (虛擬機IP)# setenv gatewayip ****** (網關)
(以上爲設置環境參數)
# saveenv (保存環境參數到flash)
(由於要進行tftp下載,所以要先搭建tftp服務器)
三、TFTP服務器搭建(Linux環境下)
1.安裝以下兩個軟件(安裝程序見TFTP安裝包)
[root@localhost Packages]# rpm -ivhxinetd-2.3.14-32.fc14.i686.rpm[root@localhost Packages]# rpm -ivhtftp-server-0.49-6.fc14.i686.rpm
2.修改配置文件
修改文件vi /etc/xinetd.d/tftp。
主要是設置TFTP服務器的根目錄,開啓服務。修改後的文件如下:
service tftp
{
socket_type =dgram
protocol =udp
wait =yes
user =root
server =/usr/sbin/in.tftpd
server_args =-s /home/user/tftproot -c
disable =no
per_source =11
cps =100 2
flags =IPv4
}
修改項server_args= -s <path> -c,其中<path>處可以改爲你的tftp-server的根目錄,參數-s指定chroot,-c指定了可以創建文件
3.創建tftp根目錄,啓動tftp-server
#mkdir /home/user/tftpboot
#chmod 777 /home/user/tftpboot
#/etc/init.d/xinetd restart
這樣,tftp-server就啓動了。
4.測試
可以使用#netstat -a |grep tftp命令察看是否啓動tftp服務,如果出現
udp 0 0 *:tftp *:* 則起動了
檢查tftp服務是否打開
[root@localhostbtools]#chkconfig –list
(查看是否有xinetd這一項)
如果tftp的服務沒有打開,則用下面命令打開tftp服務開關
[root@localhostbtools]#chkconfig tftp on
重啓服務
#/etc/init.d/xinetdrestart
四、下載內核到開發板內存
1、先確定開發板是否能ping通虛擬機下的Linux,如果是:host192.168.1.111 is alive,那麼就表示連接 成功。
2、將編譯好的uImage放入/home/user/tftpboot目錄中。(Linux下)
3、在超級終端下輸入:
# tftp uImage (將uImage鏡像下載到開發板的SDRAM的0x30008000位置)
# nand erase 80000 size (擦除Nand Flash中80000開始大小爲size的空間)
# nand write 30008000 80000 size (將內存中30008000位置開始的內容拷貝到NandFlash 中80000開始的位置大小爲size)
備註:TFTP下載內核映像時傳輸的數據總量會在完成時顯示(down_size),而燒寫 nand_flash時數據大小必須是2k對齊的,所以我們要對下載的數據大小做一點小小的改變以適應nand_flash,如果down_size百位>8,則size= down_size+1000 後把低3位清零;如果down_size百位<8,則size = down_size低3位清零+800。比如down_size **a967,則size = **b000;down_size **a567,則size = **a800。
如:
五、利用nfs掛載根文件系統
1、在Linux下設置共享目錄
運行命令:gedit/etc/exports
編輯nfs服務的配置文件(第一次打開時文件是空的),添加以下內容
/opt/rootfs *(rw,sync,no_root_squash) //自己根文件系統路徑
*:表示所有的客戶機都可以掛載此目錄
rw:表示掛接此目錄的客戶機對該目錄有讀寫的權限
no_root_squash:表示允許掛接此目錄的客戶機享有該主機的root身份
2、運行命令:service iptables stop 關閉防火牆
3、啓動NFS 服務
在命令行下運行:
#/etc/init.d/nfs start
這將啓動nfs 服務,可以輸入以下命令檢驗 nfs 該服務是否啓動。
# mkdir /mnt/nfs
# mount -t nfs -o nolock 192.168.1.232(主機IP):/opt/rootfs(需要掛載的文件的路徑) /mnt/nfs
如果沒有出現錯誤信息,您將可以瀏覽到 /mnt/nfs 目錄中的內容和/opt/rootfs 是一致的。
使用這個命令可以停止 nfs 服務:
#/etc/init.d/nfs stop
六、在U-BOOT設置環境變量
1、setenv bootargs "noinitrd root=/dev/nfs rw nfsroot=192.168.1.232:/opt/rootfs/ ip=192.168.1.25:192.168.1.232:192.168.1.254:255.255.255.0 console=ttySAC0,115200 init=/linuxrc mem=64M"
(192.168.1.25)是開發板的臨時IP
(192.168.1.232)開發主機IP
(192.168.1.254)目標板上網關
(255.255.255.0)子網掩碼
注意:如果使用的是虛擬機,則使用虛擬機的IP。
2、# setenv bootcmd “nand read 30008000 80000500000;bootm 30008000”
(將bootcmd命令改成上面的內容,因爲我們內核鏡像在Nand Flash的位置是80000,所以u-boot執行完之後,內核的入口點就在80000這個位置。)
3、重啓開發板。