Linux SkyEye安裝交叉編譯器
Linux SkyEye對于電腦使用的玩家的常用軟件,然后我就學習及深入的研究Linux SkyEye,在這里和大家一起探討Linux SkyEye的使用方法,希望對大家有用。Linux SkyEye是一個可以運行嵌入式操作系統的硬件仿真工具,這樣就可以在沒有硬件條件下來進行嵌入式系統的開發。
以下操作均在Fedora Core 1.0里通過。Linux SkyEye項目資源列表http://gro.clinux.org/projects/Linux SkyEye/
1、什么是Linux SkyEye?
Linux SkyEye是開源軟件的一個項目,Linux SkyEye的目標是在Linux和Windows操作系統里提供一個完全的仿真環境。Linux SkyEye仿真環境相當于一個嵌入式計算機系統,你可以在Linux SkyEye里運行一些嵌入式Linux操作系統,如ARMLinux,uClinux,uc/OS-II(ucos-ii)等,并能分析和調試它們的源代碼。
如果你想知道關于Linux SkyEye和嵌入式系統更詳細的信息,請訪問下面的站點:www.Linux SkyEye.org http://www.Linux SkyEye.org/index_cn.html通過Linux SkyEye能仿真下面的硬件:CPU核心:ARM7TDMI, ARM720T, ARM9, StrongARM, XScaleCPU: Atmel AT91/X40, Cirrus CIRRUS LOGIC EP7312, Intel SA1100/SA1110, Intel XScale PXA 250/255, CS89712, samsung 4510B,
- samsung 44B0(還不全)內存: RAM, ROM, Flash周邊設備:
- Timer, UART, ne2k網絡芯片, LCD, 觸摸屏等目前能在Linux SkyEye上運行下面的操作系統和系統軟件:
- uC/OSII-2.5.x(支持網絡)
- uClinux(基于Linux2.4.x內核, 支持網絡)
- ARM Linux 2.4.x/2.6.x
- lwIP on uC/OSII
- 基于uC/OSII, uClinux, ARM Linux的應用程序
2.Linux SkyEye可以做什么事情?
1. 通過Linux SkyEye可以幫助促進嵌入式系統的學習,在不需要額外硬件的情況下學習和分析uclinux操作系統和其它嵌入式操作系統,如ucosII等。
2. Linux SkyEye可用于嵌入式系統的教學。
3. 希望通過Linux SkyEye促進操作系統的研究,如ucosII,uclinux+RTAI,uclinux2.5.x等。
4. 可以基于Linux SkyEye進行仿真特定硬件模塊的研究。
5. Linux SkyEye可以作為嵌入式集成開發環境開發嵌入式系統(當然需要對Linux SkyEye做大量的工作)。
注:引自陳渝《Linux SkyEye Project FAQ》
3、安裝Linux SkyEye
到http://gro.clinux.org/projects/Linux SkyEye/下載Linux SkyEye-0.7.0.tar.bz2包:tar jxvf Linux SkyEye-v0.7.0.tar.bz2進入解壓后的Linux SkyEye目錄,如果Linux SkyEye的版本低于0.6.0,則運行下面的命令:/configure --target=arm-elf --prefix=/usr/local --without-gtk-prefix --without-gtk-exec-prefix --disable-gtktest如果Linux SkyEye的版本高于0.6.0,則運行下面的命令:/configure --target=arm-elf --prefix=/usr/local
接下來執行:
- make
- make install安裝完成后執行Linux SkyEye
注意:
- a.如果你使用的是Mandrake Linux發行版,那么你在編譯Linux SkyEye時遇到錯誤,并且錯誤與readline, ncurse, termcap等有關,你可以試試下面的方法:ln -s /usr/include/ncurses/termcap.h /usr/local/include/termcap.h接著再make和make install看能否成功!
- b.如果你的Linux發行版是Debian Linux,那么不要使用gcc 2.95或是gcc 3.0,請使用gcc 3.2+
- c.gcc的版本要在2.96或以上
- d.如果Linux SkyEye的版本大于0.6.0,那么使用LCD仿真需要在Linux系統里安裝GTK軟件。
4、安裝arm-elf交叉編譯器
下載arm-elf-tools-20030314.shftp://166.111.68.183/pub/embed/uclinux/soft/tools/arm或到ftp://166.111.8.229/OS/Embeded執行:chmod a+x arm-elf-tools-20030314.sh然后:./arm-elf-tools-20030314.sh ls /usr/local/bin/你應能看到以arm-elf開頭的可執行文件,其中arm-elf-gcc就是用來編譯你目標平臺的編譯器的,當然還有一些小工具,后面將一一講來。
5、測試你的arm-elf-gcc編譯器
先寫一個小程序hello.cPHP 代碼:#include <stdio.h>
- int main(void)
- {
- int i;
- for(i = 0; i < 6; i++){
- printf("i = %d ",i);
- printf("Hello, embedded linux!"n");
- return 0;
- }
然后執行:arm-elf-gcc -Wl,-elf2flt -o hello hello.c-elf2flt參數是將elf文件格式轉為flat文件格式,這個工具是在你安裝交叉編譯器產生的。或者你可以寫個Makefile文件,執行:make這里是我的Makefile文件,僅供參考:PHP 代碼:# begin
- CC = arm-elf-gcc
- CFLAGS = -D__PIC__ -fpic -msingle-pic-base -O2 -pipe -Wall -g
- LDFLAGS = -Wl,-elf2flt
- LIBS =
- OBJS = hello.o
- all:hello
- hello: $(OBJS)
- $(CC) $(CFLAGS) $(LDFLAGS) -o hello $(OBJS) $(LIBS)
- clean:
- rm -rf *.o *.elf *.gdb hello
- # end
如果編譯通過,就會產生hello可執行文件。用下面的命令:file hello你會發現,它是BFLT(binary FLAT),你目標平臺所支持的文件格式。
6、執行你的hello程序
這里,我們將借助genromfs這個小工具來完成測試,這個工具就是你在安裝交叉編譯器時產生的,你可以直接使用它。到http://gro.clinux.org/projects/skyey...-1.0.4.tar.bz2包:
- tar jxvf Linux SkyEye-binary-testutils-1.0.4.tar.bz2
- cd testsuits/at91/uclinux2(當然你還可以用別的)
- mkdir romfs(建一個目錄,后面用)
- mount -o loop boot.rom /mnt/xxx
- cp -r /mnt/xxx/* romfs
另外,把你編譯好的可執行程序拷貝到/romfs/bin目錄里,這里就是hello了!genromfs -f boot.rom -d romfs/注:可以用genromfs -h來獲得幫助!
OK!執行下面的命令:
- Linux SkyEye linux
- (Linux SkyEye)target sim
- (Linux SkyEye)load
- (Linux SkyEye)run
- kernel start.....
很熟悉了吧。。。cd /binhello可以看到結果了嗎?其實到了這一步,你就可以開發自己的程序了!
7、一個應用程序的開發實例
下面介紹的程序主要是完成一個網絡應用,網絡應用的標準模型是客戶機-服務器模型,它的主要執行過程如下:
(1)系統啟動服務器執行。服務器完成一些初始化操作,然后進入睡眠狀態,等待客戶機請求;
(2)在網絡的某臺機器上,用戶執行客戶機程序;
(3)客戶機進程與服務器進程建立一條連接;
(4)連接建立之后,客戶機通過網絡向服務器發出請求,請求某種服務;
(5)服務器接收到客戶機請求后,根據客戶機請求的內容進行相應的處理,然后將處理結果返回;
(6)服務器斷開與客戶機的連接,繼續睡眠,等待其他客戶機的請求;
Linux系統中的很多服務器是在系統初啟時啟動的,如時間服務器、打印服務器、文件傳輸服務器和電子郵件服務器等。大多數時間這些服務器進程處于睡眠狀態,等待客戶機的請求。
下面這兩個客戶機-服務器程序比較簡單,主要是對網絡客戶機-服務器模型的實際運行有大致印象。這個客戶機-服務器的操作過程非常簡單:客戶機與服務器建立連接之后,服務器向客戶機返回一條消息。
服務器程序的源代碼如下:
PHP 代碼:
- /* tcpserver.c */
- #include <stdlib.h>
- #include <stdio.h>
- #include <errno.h>
- #include <string.h>
- #include <netdb.h>
- #include <sys/types.h>
- #include <netinet/in.h>
- #include <sys/socket.h>
- #define WAITBUF 10
- int main(int argc, char *argv[])
- {
- int sockfd, new_fd;
- struct sockaddr_in server_addr;
- struct sockaddr_in client_addr;
- unsigned int sin_size, portnumber;
- char hello[]="Hello! Socket communication world!"n";
- if(argc != 2)
- {
- fprintf(stderr, "Usage:%s portnumber"a"n", argv[0]);
- exit(1);
- }
- if((portnumber = atoi(argv[1])) < 0)
- {
- fprintf(stderr, "Usage: %s portnumber error"a"n", argv[0]);
- }
- if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
- {
- fprintf(stderr, "Socket error:%s"n"a", strerror(errno));
- exit(1);
- }
- bzero(&server_addr, sizeof(struct sockaddr_in));
- server_addr.sin_family = AF_INET;
- server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
- server_addr.sin_port = portnumber;
- if(bind(sockfd,(struct sockaddr *)(&server_addr), sizeof(struct sockaddr)) == -1)
- {
- fprintf(stderr, "Bind error:%s"n"a", strerror(errno));
- exit(1);
- }
- if(listen(sockfd, WAITBUF) == -1)
- {
- fprintf(stderr, "Listen error:%s"n"a", strerror(errno));
- exit(1);
- }
- while(1)
- {
- sin_size = sizeof(struct sockaddr_in);
- if((new_fd = accept(sockfd, (struct sockaddr *)(&client_addr), &sin_size)) == -1)
- {
- fprintf( stderr, "Accept error:%s"n"a", strerror(errno));
- exit(1);
- }
- fprintf(stderr, "Server get connection from %s"n", inet_ntoa(client_addr.sin_addr));
- if(send(new_fd, hello, strlen(hello), 0) == -1)
- {
- fprintf(stderr, "Write Error:%s"n", strerror(errno));
- exit(1);
- }
- close(new_fd);
- }
- close(sockfd);
- exit(0);
- }
給服務器程序寫一個Makefile文件,如下:
PHP 代碼:
- # start
- CC = arm-elf-gcc
- CFLAGS = -D__PIC__ -fpic -msingle-pic-base -O2 -pipe -Wall -g
- LDFLAGS = -Wl,-elf2flt
- LIBS =
- OBJS = tcpserver.o
- all:tcpserver
- tcpser: $(OBJS)
- $(CC) $(CFLAGS) $(LDFLAGS) -o tcpserver $(OBJS) $(LIBS)
- clean:
- rm -rf *.o *.elf *.gdb hello
- # end
客戶機程序的源代碼如下:
PHP 代碼:
- /* tcpclient.c */
- #include <stdlib.h>
- #include <stdio.h>
- #include <errno.h>
- #include <string.h>
- #include <netdb.h>
- #include <sys/types.h>
- #include <netinet/in.h>
- #include <sys/socket.h>
- #define RECVBUFSIZE 1024
- int main(int argc, char *argv[])
- {
- int sockfd;
- char buffer[RECVBUFSIZE];
- struct sockaddr_in server_addr;
- int portnumber, nbytes;
- if(argc != 3)
- {
- fprintf(stderr, "Usage:%s hostname portnumber"a"n", argv[0]);
- exit(1);
- }
- if((portnumber=atoi(argv[2])) < 0)
- {
- fprintf(stderr,"Usage:%s hostname portnumber"a"n", argv[0]);
- exit(1);
- }
- if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
- {
- fprintf(stderr, "Socket Error:%s"a"n", strerror(errno));
- exit(1);
- }
- bzero(&server_addr, sizeof(server_addr));
- server_addr.sin_family = AF_INET;
- server_addr.sin_port = portnumber;
- server_addr.sin_addr.s_addr = inet_addr(argv[1]);
- if(connect(sockfd, (struct sockaddr *)(&server_addr), sizeof(struct sockaddr)) == -1)
- {
- fprintf(stderr, "Connect Error:%s"a"n", strerror(errno));
- exit(1);
- }
- if((nbytes = recv(sockfd, buffer, RECVBUFSIZE, 0)) == -1)
- {
- fprintf(stderr, "Read Error:%s"n", strerror(errno));
- exit(1);
- }
- buffer[nbytes]='"0';
- printf("I have received:%s"n", buffer );
- close(sockfd);
- exit(0);
- }
最后,Linux SkyEye-binary-testutils-1.1.0.tar.bz2/at91x40/uclinux1包里提取boot.rom,用步聚6中的方法,把tcpserver程序放在boot.rom的bin目錄中在目標板上運行tcpserver 2000在主機上運行./tcpclient 10.0.0.2 2000看看結果!程序的源碼的注釋因篇幅不在這給出,大家可以參考一些Linux網絡編程的書籍,我也會在我的主頁上更新一些資料,有需要的朋友可以去下載!
8、編譯并運行uClinux-dist-20030909.tar.gz
到ftp://166.111.68.183/pub/embed/uclinux/soft/或到ftp://166.111.8.229/OS/Embeded/uclinux/pub/uClinux/dist下載uClinux-dist-20030909.tar.gz假設把它下載到/usr/src/目錄下.
然后依次執行下面的命令:tar zxvf uClinux-dist-20030909.tar.gzv cd uClinux-dist/在圖形方式下可用命令make xconfig或在命令行方式下用命令make menuconfig vendor/product中選擇GDB/ARMulator kernel版本選擇2.4然后save and exit
運行下面這兩條命:
make dep
make
此時在/usr/src/uClinux-dist/linux-2.4.x目錄下會生成可執行文件linux在/usr/src/uClinux-dist/images/會生成romfs.img等文件在uClinux-dist目錄下建立仿真AT91的Linux SkyEye配置文件Linux SkyEye.conf,內容如下:
- cpu: arm7tdmi
- mach: at91
- mem_bank: map=M, type=RW, addr=0x00000000, size=0x00004000
- mem_bank: map=M, type=RW, addr=0x01000000, size=0x00400000
- mem_bank: map=M, type=R, addr=0x01400000, size=0x00400000, file=images/romfs.img
- mem_bank: map=M, type=RW, addr=0x02000000, size=0x00400000
- mem_bank: map=M, type=RW, addr=0x02400000, size=0x00008000
- mem_bank: map=M, type=RW, addr=0x04000000, size=0x00400000
- mem_bank: map=I, type=RW, addr=0xf0000000, size=0x10000000
這個時候就可以用Linux SkyEye來調試運行kernel了,在/usr/src/uClinux-dist執行如下命令:
- Linux SkyEye linux-2.4.x/linux
- (Linux SkyEye)target sim
- (Linux SkyEye)load
- (Linux SkyEye)run
- kernel start.....
注意:要在Linux SkyEye.conf所在目錄下執行Linux SkyEye linux-2.4.x/linux
9、加入網絡功能
a.用root用戶進行操作。
b.你要看你的/lib/modules/'uname -r'/kernel/drivers/net/目錄里有沒有tun.o如果沒有的話你就需要編譯你的linux內核來獲得tun.o了。
c.(1)運行tun設備模塊:
- #insmod /lib/modules/'uname -r'/kernel/drivers/net/tun.o如果你沒有該設備,那你就要用下面的命令來創建它:
- #mkdir /dev/net
- #mknod /dev/net/tun c 10 200
(2)運行vnet(虛擬集線器)設備模塊(這一步不是必需的):獲取vnet的源碼,然后創建設備:
- #mknod /dev/net/vnet c 10 201
- #chmod 666 /dev/net/vnet
- 創建vnet.o#make vnet.o插入模塊vnet.o#insmod vnet.o進入test目錄,用test來測度vnet.o
- #cd test
- #make
- #./testvnet1
d.配置Linux SkyEye.conf文件
- cpu: arm7tdmi
- mach: at91
- mem_bank: map=M, type=RW, addr=0x00000000, size=0x00004000
- mem_bank: map=M, type=RW, addr=0x01000000, size=0x00400000
- mem_bank: map=M, type=R, addr=0x01400000, size=0x00400000, file=images/romfs.img
- mem_bank: map=M, type=RW, addr=0x02000000, size=0x00400000
- mem_bank: map=M, type=RW, addr=0x02400000, size=0x00008000
- mem_bank: map=M, type=RW, addr=0x04000000, size=0x00400000
- mem_bank: map=I, type=RW, addr=0xf0000000, size=0x10000000
- # format: state=on/off mac=xx:xx:xx:xx:xx:xx ethmod=tuntap/vnet hostip=dd.dd.dd.dd
- net: state=on, mac=0:4:3:2:1:f, ethmod=tun, hostip=10.0.0.1
下面將對上面的一些參數作下說明:state=on/off意思是仿真的NIC(網絡接口板)是有線的還是無線的;mac=仿真適配器的MAC地址;ethmod=tuntap/vnet在主機環境里使用的虛擬設備;hostip=意思是主機環境與keyeye交互用的IP格式: state=on/off mac=xx:xx:xx:xx:xx:xx ethmod=tuntap/vnet hostip=dd.dd.dd.dd
- For example:
- #set nic info state=on/off mac=xx:xx:xx:xx:xx:xx ethmod=tuntap/vnet hostip=dd.dd.dd.dd
- net: state=on, mac=0:4:3:2:1:f, ethmod=tun, hostip=10.0.0.1
- 或
- net: state=on, mac=0:4:3:2:1:f, ethmod=vnet, hostip=10.0.0.1
注意:
如果你想在同一時刻運行兩個或更多的Linux SkyEye,那么請為每一個Linux SkyEye使用不同的Linux SkyEye.conf e.運行Linux SkyEye linux-2.4.x/linux
10、安裝完成Linux SkyEye后,下一步將做什么?
1、對于嵌入式操作系統的初學者和入門者和入門的學生而言,他們可以先看一些有關操作系統和嵌入式操作系統方面的教材和書籍,如與uC/OS、Minix、uClinux、Linux相關的書籍等。然后可以在Linux SkyEye上開發一些簡單的應用程序例子(如進程間通信、進程優先級、死鎖情況、網絡應用等),對某些操作系統功能(如進程調度、內存管理、網絡子系統、文件子系統等)進行簡單的修改和擴展,并通過Linux SkyEye進行運行和調試,看看會發生什么情況。
2、對于有一定經驗的軟件工程師而言,在Linux SkyEye上完成一定的應用系統原型開發是值得一做的事情。比如移植或開發一個文件子系統或網絡子系統到一個特定的操作系統中,相信比在一個真實的開發板上開發要容易一些。在Linux SkyEye上進行一些操作系統的移植和開發(如移植RTLinux、RTAI等其它操作系統到Linux SkyEye上)也是很有挑戰性的工作。
3、對于硬件工程師而言,對Linux SkyEye進行擴充,設計新的硬件仿真(如USB、IDE硬盤等)使得Linux SkyEye的硬件仿真功能更加強大,支持更多功能的軟件,是很有意義的事情。
參考:Linux SkyEye項目站點里的一篇中文文檔;陳渝《Linux SkyEye Project FAQ》;Linux SkyEye-0.7.0中的README文檔。
后記:為了讓大家能快速上手,進行實際的開發工作,我趕湊了一篇文檔,很粗糙。但我堅信隨著更多的有經驗的人的加入;隨著我們自己水平的提高,一定會出現更多、更好的文章來。就讓我們快點行動起來吧!
最后,我再次建議大家看一下《嵌入式Linux技術與應用》這本書。可以到http://www.Linux SkyEye.org/document.htm或是ftp://166.111.68.183/pub/embed/Linux SkyEye/document/或是http://www.huihoo.org/mirrors/Linux SkyEye/下載文檔,可以獲得更多有關Linux SkyEye和嵌入式Linux開發的知識和經驗.
【編輯推薦】