uClinux在S3C44B0X上的移植
裝有Linux系統(tǒng)的主機(具備c編譯環(huán)境),立宇泰公司的ARMSYS44B0開發(fā)版(集成Samsung的S3C44b0X芯片)及各種連線,uClinux源代碼,交叉編譯工具arm-elf-tools
1.uClinux簡介,基本結構,內(nèi)核結構(略)
2.如果有產(chǎn)品的附帶光盤,那路徑/arm7/uClinux/uClinux下就包括了uClinux源代碼,uClinux-armsys-050101.tar.gz,另外在這個目錄下還提供了交叉編譯工具arm-elf-tools-20030314.sh
如果手頭沒有這張光盤,也可以去立宇泰公司的網(wǎng)站(http://www.hzlitai.com.cn/download/default.asp)查找下載所需資料,但其中的uClinux源代碼包是uClinux-dist-20040408.tar.gz
3.1.1 對于uClinux-armsys050101.tar.gz這個包,我們首先將它轉(zhuǎn)移到/home目錄下(當然在其他目錄可以同樣進行操作)
如果對Linux不太熟悉并希望能像在Windows下那樣進行圖形化的文件操作,最好以超級用戶(root)登錄,這是為了避免接下來的操作中出現(xiàn)權限限制.
如果是命令行操作,方法如下:
普通用戶更換到超級用戶,在提示下輸入root密碼(為了防止被掃描,密碼輸入時屏幕沒有相應顯示)
[Jiang@localhost ~]$ su -
Password:
用cp(拷貝命令),其中yourdir更改成你系統(tǒng)中arm7的目錄
[root@localhost ~]# cp /yourdir/arm7/uClinux/uClinux/uClinux-armsys-050101.tar.gz /home
然后跳轉(zhuǎn)到/home
[root@localhost ~]# cd /home
3.1.2 對uClinux-armsys-050101.tar.gz進行解壓縮
[root@localhost ~]# tar xzvf uClinux-armsys-050101.tar.gz
參數(shù)說明:
x 從檔案文件中釋放文件
z 用gzip來壓縮/解壓縮文件,加上該選項后可以將檔案文件進行壓縮,但還原時也一定要使用該選項進行解壓縮
v 詳細顯示tar處理的文件信息
f 使用檔案文件或設備,這個選項通常是必選的
這個過程大約需要幾分鐘,完成后在當前目錄(/home)下多了一個文件夾uClinux-dist,進入,我們可以看到里面的文件或文件夾
[root@localhost home]# cd uClinux-dist/
[root@localhost uClinux-dist]# ls
autoconf.h kernel_44b0.cfg romfs
bin kernel_44b0.cfg.old SOURCE
config kernel_4510.cfg tools
config.arch kernel_4510.cfg.old uClibc
config.in lib uClinux-20040408-ARMSYS.patch
COPYING linux-2.4.x user
Documentation Makefile vendors
freeswan Makefile.orig
images README
其 中images文件夾下有3個文件,這是我們最終所需要的,估計這個文件夾是lyt公司打包時自己加上去的,在一般源代碼中這個文件夾是沒有的,到編譯成 功后會自動生成,所以我把這個文件夾剪切到了其他地方.另外這里還有一個文件uClinux-20040408-ARMSYS.patch,這是 uClinux-dist-20040408.tar.gz針對S3C44B0X結構的補丁,因為uClinux-armsys- 050101.tar.gz已經(jīng)針對S3C44B0X硬件結構做了參數(shù)的修改,用不著這個補丁.這里,我們可以用rm -fr直接把這兩個文件刪掉.
如果在Windows環(huán)境下進行解壓縮可能會產(chǎn)生一些錯誤,所以推薦在Linux中解壓.
3.1.3 安裝交叉編譯環(huán)境
首先進入到arm-elf-tools-20030314.sh所在的目錄,然后
[root@localhost home]#sh arm-elf-tools-20030314.sh
執(zhí)行后在/usr/local/bin路徑下可以看到各種實用工具
[root@localhost uClinux-dist]# ls /usr/local/bin
arm-elf-addr2line arm-elf-g++ arm-elf-objcopy arm-elf-strings
arm-elf-ar arm-elf-gasp arm-elf-objdump arm-elf-strip
arm-elf-as arm-elf-gcc arm-elf-protoize arm-elf-unprotoize
arm-elf-c++ arm-elf-gdb arm-elf-ranlib elf2flt
arm-elf-c++filt arm-elf-ld arm-elf-readelf flthdr
arm-elf-elf2flt arm-elf-ld.real arm-elf-run genromfs
arm-elf-flthdr arm-elf-nm arm-elf-size
3.1.4內(nèi)核的編譯
其實這一步也很容易,有人形容是易如反掌,但有一些細節(jié)處理不好的話也很容易出錯
首 先根據(jù)需要配置內(nèi)核.內(nèi)核提供了各種功能,支持很多的硬件,因而有許多東西需要配置.可以配置的各種選項通過帶有CONFIG前綴的表示符來表示.這些配 置項要么可以二選一,要么可以三選一.二選一就是yes or no.三選一可以有yes,no和module.module意味著該配置被選定了,但編譯的時候這部分功能的實現(xiàn)代碼是以模塊的形式生成.驅(qū)動程序一般 是三選一的.
內(nèi)核提供了各種不同的工具來簡化內(nèi)核配置.make config是一個字符界面下的命令行工具,該工具會挨個遍歷所有配置,要求用戶進行選擇,耗時巨大.make menuconfig和make xconfig都是圖形界面工具,都對配置項進行了分類存放,其中后者基于X11,支持鼠標.這里我們采用第二種工具make menuconfig
[root@localhost uClinux-dist]# make menuconfig
注意:
1.是在uClinux-dist目錄下;否則報報錯:
make: *** 沒有規(guī)則可以創(chuàng)建目標“menuconfig”。 停止。
2.如果是在終端窗口執(zhí)行的話,要保證窗口的大小,如果窗口過小,則會顯示出錯信息:]
Your display is too small to run Menuconfig!
It must be at least 19 lines by 80 columns.
You have not saved your config, please re-run make config
make: *** [menuconfig] 錯誤 1
執(zhí)行后在終端顯示uClinux v3.1.0 Configuration窗口,主要使用[Y],[N],[M],Enter,和方向鍵.4個主菜單項
│ │ Vendor/Product Selection ---> │ │
│ │ Kernel/Library/Defaults Selection ---> │ │
│ │ --- │
│ │ Load an Alternate Configuration File │ │
│ │ Save Configuration to an Alternate File
首先使用方向鍵選擇 "制造商/產(chǎn)品 選擇"選項,回車進入下級菜單,uClinux-armsys-050101.tar.gz已經(jīng)默認了Samsung和44b0x,所以我們可以直接退回到上級目錄.
選中"內(nèi)核/庫/默認 選擇",回車進入這個菜單,看到
│ │ --- Kernel is linux-2.4.x │ │
│ │ (uClibc) Libc Version │ │
│ │ [ ] Default all settings (lose changes) │ │
│ │ [ ] Customize Kernel Settings (NEW) │ │
│ │ [ ] Customize Vendor/User Settings │ │
│ │ [ ] Update Default Vendor Settings │ │
第一行內(nèi)核選擇了Linux2.4系列,uClinux-armsys-050101.tar.gz只提供了這一唯一選項.
第二行是c庫的選擇
│ │ ( ) uC-libc │ │
│ │ (X) uClibc │ │
默認是uClibc,它是uC-libc的派生物,能更好的支持標準c.如果要將c庫更改為uC-libc,方向鍵+回車就可以了,自動退回到上級菜單.
第三行不作改變,所有配置項都取默認值.
第四行定制內(nèi)核設置,如果需要可以用方向鍵移動到此菜單項按[Y],在[ ]中顯示*.
第五行是定制制造商/用戶選項設置,選擇方法與定制內(nèi)核完全一致
第六行更新默認的制造商設置
make menuconfig執(zhí)行結束后,自動將配置結果保存為.config文件,并沒有將前一次配置結果丟棄,備份為.config.old文件(.文件是Linux的隱藏文件,可以用ls -a查看 ).
下面開始對uClinux源代碼包進行編譯,步驟如下:
1.[root@localhost uClinux-dist]#make dep
尋找代碼之間的倚賴關系(在內(nèi)核2.6系列以后自動維護代碼間倚賴關系,以前的這一步必需)
2.[root@localhost uClinux-dist]#make clean(可選步驟)
清除構造內(nèi)核時生成的所有目標文件,模塊文件和一些臨時文件
3.[root@localhost uClinux-dist]#make lib_only
編譯庫文件
4.[root@localhost uClinux-dist]#make user_only
編譯用戶應用程序文件
5.[root@localhost uClinux-dist]#make romfs
生成romfs文件系統(tǒng)
6.[root@localhost uClinux-dist]#make image
生成內(nèi)核映象文件
7.[root@localhost uClinux-dist]#make
通過各個文件夾中的Makefile文件進行編譯
其中除了make romfs和make image兩步較快外,其他各步都需要一段時間的執(zhí)行.
編譯成功后會在當前目錄(/uClinux-dist)看到images文件夾,里面有兩個內(nèi)核文件image.rom和image.ram,另外還有一個img文件romfs.img.
3.1.5 當然這是極順利的內(nèi)核編譯,在編譯uClinux難免有錯誤出現(xiàn),現(xiàn)總結如下:
1.如果在內(nèi)核定制的時候選的c庫是uC-libc則一路編譯下來幾乎沒有問題,當執(zhí)行到make image這一步時會出現(xiàn)兩個錯誤:
arm-elf-objcopy: /home/uClinux-dist/linux-2.4.x/linux: ?????????
make[1]: *** [image] 錯誤 1
make[1]: Leaving directory `/home/uClinux-dist/vendors/Samsung/44B0
make: *** [image] 錯誤 2
這是因為第一次編譯時還沒有romfs.o,所以出錯;等romfs.o編譯好以后,如果再進行內(nèi)核編譯,就不會出現(xiàn)這個錯誤了.它完全不影響內(nèi)核的編譯,可以不必理會這個錯誤,繼續(xù)下一步.
2.如果在內(nèi)核定制時選的c庫是uClibc,那么當編譯進行到make user_only時會出現(xiàn)以下錯誤:
login.elf2flt: In function `main:
/home/uClinux-dist/user/login/login.c:168: undefined reference to `crypt_old
collect2: ld returned 1 exit status
make[2]: *** [login] 錯誤 1
make[2]: Leaving directory `/home/uClinux-dist/user/login
make[1]: *** [all] 錯誤 2
make[1]: Leaving directory `/home/uClinux-dist/user
make: *** [user_only] 錯誤 2
這是由于對crypt_old的未定義引用而引起報錯,打開/home/uClinux-dist/user/login路徑下的login.c文件會看到這么一段條件編譯:
#ifdef OLD_CONFIG_PASSWORDS
#include
#endif
crypt_old ()正是定義在crypt_old.h文件中,所以我認為這是沒有設置OLD_CONFIG_PASSWORDS的緣故.嘗試著注釋掉這個條件編譯,直接 將頭文件crypt_old.h包含進來,包括同一目錄下的passwd.c,再進行用戶應用程序文件的編譯,本以為這樣可以解決問題的,但編譯結果還是 報錯.(疑問:OLD_CONFIG_PASSWORDS定義在哪個文件中?把它設成yes能否解決問題?)
解決方法一.
編譯之前,進入/uClinux-dist/user,更改其中的Makefile文件,加上一句
LIBCRYPT +=-lcrypt_oldz
再編譯,正確結束.
解決方法二.
在內(nèi)核配置時選擇
[*] Customize Vendor/User Settings
定制用戶選項設置,在其主菜單里進入Core Applications一項,去掉對login和old password的選擇,然后編譯通過.
如果修改過用戶配置,去http://www.hzlitai.com.cn/download/linux/config_user下載配置文件config_user,放到/uClinux-dist/config目錄下覆蓋原來的文件就還原到原來的設置.
3.2.1 如果手頭uClinux的源代碼是uClinux-dist-20040408.tar.gz版本,則還需要下載補丁uClinux-20040801- ARMSYS.patch(http://www.hzlitai.com.cn/download/default.asp)
首先解壓源代碼到/home,將補丁uClinux-20040801-ARMSYS.patch拷貝到/home/uClinux-dist.運行補丁程序
[root@localhost uClinux-dist]# patch -p1
...
Hunk #1 FAILED at 5.
Hunk #2 FAILED at 40.
Hunk #3 FAILED at 187.
3 out of 3 hunks FAILED -- saving rejects to file Makefile.rej
patching file linux-2.4.x/arch/armnommu/vmlinux-armv.lds.in
Hunk #1 succeeded at 63 (offset 4 lines).
cant find file to patch at input line 16504
Perhaps you used the wrong -p or --strip option?
The text leading up to this was:
--------------------------
|
|diff -Naur uClinux-dist/vendors/Samsung/44B0/Makefile vendors/Samsung/44B0/Makefile
|--- uClinux-dist/vendors/Samsung/44B0/Makefile 2004-04-08 08:27:25.000000000 +0800
|+++ uClinux-dist/vendors/Samsung/44B0/Makefile 2004-08-01 02:43:50.000000000 +0800
--------------------------
File to patch:
這是由于源代碼uClinux-dist/vendors/Samsung/路徑下的文件夾名是4510B,而不存在44B0這個文件夾,所以報錯.解決辦法很簡單,直接將4510B改名成44B0就OK了.
[root@localhost uClinux-dist]# mv vendors/Samsung/4510B vendors/Samsung/44B0
也可以根據(jù)補丁文件的描述自己手動地改寫源代碼,這樣就不需要再打補丁了.
接下來就是代碼的編譯了.
4.內(nèi)核的下載,燒錄
在下載內(nèi)核之前確保板子上已經(jīng)燒錄了引導裝載程序bootloader,可以根據(jù)超級終端的顯示來判斷,如果出現(xiàn)了
...
1.Download code to SDRAM.
2.Download code to SDRAM & Nandflash.
3.Burn flashROM.
4.Copy code from flashROM to SDRAM.
5.Run at specify address.
6.Run code in Nandflash.
7.Start uClinux.
8.Format Nandflash.
9.Test hardware
這9個選項,說明已經(jīng)有bootloader燒錄到板子了,否則還要進行bootloader的燒錄.
4.1bootloader.bin的燒錄
燒錄方法一:使用fluted燒錄工具
燒錄步驟
S1.連線.使用并口線和20針排線,通過JTAG模塊,連接主板(開發(fā)板)和宿主機主板并口
S2.打開主板電源,運行JTAG.exe
S3.將bootloader.bin拷貝到programmer目錄下,運行F.bat(Win2000 or XP運行F_2000xp.bat),開始燒錄.
Fluted燒錄分三個過程:擦除,寫入,校驗.如果沒有報錯,則燒錄成功.可以按復位鍵,觀察超級終端顯示.
燒錄方法二:使用flashprgm工具
它是一個工程文件,需要在ADS或SDT中編譯運行.其優(yōu)點是速度快.
在SDT中的燒錄步驟:
S1.連接 jtag口,編譯工程,啟動ADW
S2.菜單|file|get files...,填寫地址0xc200000,打開bootloader.bin,ADW就開始下載
S3.下載完成后點工具欄上(GO)圖標執(zhí)行flashprgm程序,開始燒錄.
4.2下載image.ram到開發(fā)板
uClinux的運行有兩種模式:一種是用USB或Xmodem下載內(nèi)核映象文件到SDRAM指定位置,直接運行;另一種是先將內(nèi)核壓縮文件燒錄到flashROM,再從flashROM解壓縮到SDRAM開始運行.
將image.ram下載到開發(fā)板的步驟:
S1.開發(fā)板上電,用USB供電就可以了(反正需要USB下載器);啟動JTAG.exe,打開超級終端
S2.在bootloader的9個選項中選擇功能項1
S3.根據(jù)超級終端提示輸入下載地址,默認是0xc8000,所以如果不用其它地址的話可以直接按回車鍵
S4.提示使用哪種下載工具,USB下載器orXmodem,選擇前者按[U],后者按[X]
S5.按下[U],出現(xiàn)提示信息:
USB Interface is active!
You can use USBdownload.exe to download *.bin file!
這樣就可以開始使用USB下載器進行程序下載了
提示信息也可能是這樣的
...(以前看到過,具體什么忘了)failed!
可以按復位鍵重啟bootloader,基本可以解決問題
注意:在使用USB下載器地時候最好斷開jtag口.
S6.USB下載器的使用.菜單|file|open file...,先選擇要下載的文件,它提供了三種格式的文件:.bin,.txt,還有.ram,然后點擊主界面上的"下載文件"按鈕開始下載,有提示信息顯示和進度條變化.這里有兩個問題:
1.如果直接選擇image.ram,會發(fā)現(xiàn)它的大小只有幾十k,而且到下一步啟動uClinux時就死機了,所以我們將.ram文件改成.bin文件;
2.下載imageram.bin文件并不是每一次都可以成功,有時可能提示超時,那就多試幾次(具體原因再作了解)
S7.下載成功后,選擇功能項5,從指定位置運行程序,因為我們需要地址0xc8000,直接回車就可以了,這樣就可以看到uClinux的啟動畫面了
4.3燒錄image.rom到主板
image.rom是image.ram的壓縮版本.
燒錄步驟:
S1.復位開發(fā)板.選功能項1,輸入地址0xc200000,回車
S2.USB下載器下載bootloader.bin(可以在光盤找到)
S3.下載成功后,再次選擇功能項1,輸入地址0xc220000,回車
S4.USB下載器下載imagerom.bin
S5.下載成功后,還是選擇功能項1,輸入地址0xc8000,回車
S6.USB下載器下載flashprgm目錄下的44bapp.bin
S7.下載成功后,選功能項5,從指定位置0xc8000運行程序
S8.flashprgm開始運行,超級終端顯示詢問是否開始燒錄,按[Y],開始燒錄,可以看到開發(fā)板上綠色發(fā)光管的變化.燒錄完成提示是否再次燒錄,回答[N]
S9.復位開發(fā)板,輸入7,運行uClinux
可以看到啟動界面:
...
Load image.rom...
Start uClinux
Uncompressing Linux.............................................................Linux version 2.4.24-uc0 (root@localhost) (gcc version 2.95.3 20010315 (release5Processor: Samsung S3C44B0X revision 0
Architecture: S3C44B0X
On node 0 totalpages: 2048
zone(0): 0 pages.
zone(1): 2048 pages.
zone(2): 0 pages.
Kernel command line: root=/dev/rom0 init=/linuxrc
Calibrating delay loop... 31.84 BogoMIPS
Memory: 8MB = 8MB total
Memory: 6044KB available (1799K code, 170K data, 44K init)
Dentry cache hash table entries: 1024 (order: 1, 8192 bytes)
Inode cache hash table entries: 512 (order: 0, 4096 bytes)
Mount cache hash table entries: 512 (order: 0, 4096 bytes)
Buffer cache hash table entries: 1024 (order: 0, 4096 bytes)
Page-cache hash table entries: 2048 (order: 1, 8192 bytes)
POSIX conformance testing by UNIFIX
Linux NET4.0 for Linux 2.4
Based upon Swansea University Computer Society NET3.039
Initializing RT netlink socket
Starting kswapd
ttyS0 at I/O 0x1d00000 (irq = 3) is a S3C44B0
ttyS1 at I/O 0x1d04000 (irq = 2) is a S3C44B0
ne.c:v1.10 9/23/94 Donald Becker (becker@scyld.com)
Last modified Nov 1, 2000 by Paul Gortmaker
NE*000 ethercard probe at 0x8000000: 52 54 ab 12 34 56
eth0: NE1000 found at 0x8000000, using IRQ 22
Blkmem copyright 1998,1999 D. Jeff Dionne
Blkmem copyright 1998 Kenneth Albanowski
Blkmem 1 disk images:
0: C0ECA80-C1D4E7F [VIRTUAL C0ECA80-C1D4E7F] (RO)
RAMDISK driver initialized: 16 RAM disks of 1024K size 1024 blocksize
NET4: Linux TCP/IP 1.0 for NET4.0
IP Protocols: ICMP, UDP, TCP
IP: routing cache hash table of 512 buckets, 4Kbytes
TCP: Hash tables configured (established 512 bind 512)
VFS: Mounted root (romfs filesystem) readonly.
Freeing init memory: 44K
Shell invoked to run file: /etc/rc
Command: hostname Samsung
Command: /bin/expand /etc/ramfs.img /dev/ram0
Command: /bin/expand /etc/ramfs2048.img /dev/ram1
Command: mount -t proc proc /proc
Command: mount -t ext2 /dev/ram0 /var
Command: mount -t ext2 /dev/ram1 /ramdisk
Command: chmod 777 /ramdisk
Command: mkdir /var/config
Command: mkdir /var/tmp
Command: mkdir /var/log
Command: mkdir /var/run
Command: mkdir /var/lock
Command: cat /etc/motd
Welcome to
____ _ _
/ __| ||_|
_ _| | | | _ ____ _ _ _ _
| | | | | | || | _ | | | | / /
| |_| | |__| || | | | | |_| |/
| ___/____|_||_|_| |_|/____|/_//_/
| |
|_|
For further information check:
http://www.uclinux.org/
Command: ifconfig lo 127.0.0.1
Command: route add -net 127.0.0.0 netmask 255.255.255.0 lo
Command: ifconfig eth0 192.168.253.2 netmask 255.255.255.0 up
Command:
Execution Finished, Exiting
Sash command shell (version 1.1.1)
/>
附:uClinux的通用c庫:uC-libc和uClibc的區(qū)別概述
uClinux通常使用兩種c庫:uC-libc和uClibc.盡管它們名字近似,但有很大區(qū)別.本文是對它們不同點的快速瀏覽.
uC-libc是uClinux的原始c 庫,它基于Linux-8086 c庫,該c 庫是ELKs 工程的一部分,支持m68000結構.uC-libc是一個相當全面的c 庫,但它的一些API是非標準的,一些通用庫例程現(xiàn)在已不再使用.目前它能穩(wěn)定地支持m68000,ColdFire和ARM(不帶MMU)結構 .其主要設計目標是小型化和輕量級.它力圖符合通用標準,它的API也與絕大多數(shù)的c 庫兼容,但與標準難免有出入.
uClibc是uC-libc的派生體,用來解決uC-libc存在的問題.它讓所有的API都標準化(正確的類型,參數(shù)等),補充了許多缺失的例程,并 且已經(jīng)移植到許多結構中.大體上講,它通過提供glibc兼容使得應用程序移植到較小的c 庫時相當?shù)萌菀? 它能夠應用到帶虛擬存儲的Linux和uClinux上.在大多數(shù)帶MMU部件的平臺上為使它更加緊湊,它也能夠編譯成共享庫.uClibc支持許多處理 器:m68000,ColdFire,ARM,MIPS,v850,x86,i960,Sparc,SuperH,Alpha,PowerPC和 Hitachi 8.uClibc能更加容易地適應新的體系結構,它所支持的平臺數(shù)目至今仍在增長證實了這一點.
可以根據(jù)你的需要來選擇uClinux使用uC-libc或者uClibc編譯環(huán)境.對m68000和ColdFire平臺通常選擇uC-libc, 因為它支持共享庫,是這些處理器上使用最廣泛的c 庫.uClibc also works quite well with almost all platforms supported by the distribution.你的需要將最終決定到底選擇哪一種c庫.
評論