講稿(嵌入式設(shè)計(jì)與實(shí)現(xiàn))
目 錄
第1章 嵌入式硬件開(kāi)發(fā)環(huán)境 2
1.1 嵌入式系統(tǒng)的概念 2
1.2 熟悉OURS PXA270RP實(shí)驗(yàn)箱的硬件環(huán)境 2
第2章 Linux常用命令 2
第3章 搭建嵌入式Linux開(kāi)發(fā)環(huán)境 4
3.1 vwaretools的安裝與共享設(shè)置 4
3.2 tslib-1.4的編譯安裝 4
3.3 qtX11和qtE4的編譯安裝 5
3.4 PATH與LD_LIBRARY_PATH的設(shè)置 6
3.5 配置交叉編譯器 6
3.6 配置minicom、tftp和NFS 7
第4章bootloader、Linux內(nèi)核及文件系統(tǒng)制作與移植 12
4.1 bootloader 12
4.2 Linux內(nèi)核編譯與移植 12
4.3文件系統(tǒng)制作與移植 13
第5章 Qt圖形編程 14
5.1 嵌入式GUI簡(jiǎn)介 14
5.2 Qt/Embedded開(kāi)發(fā)入門(mén) 14
5.2.1 Qt/Embedded介紹 14
5.2.2 Qt/Embedded圖形界面 15
5.2.3 Qt/Embedded信號(hào)和槽機(jī)制 17
5.2.4 Qt/Embedded網(wǎng)絡(luò)編程 18
第6章 聊天系統(tǒng)設(shè)計(jì)與實(shí)現(xiàn) 18
6.1 聊天軟件需求分析 18
6.2 界面設(shè)計(jì) 18
6.3 網(wǎng)絡(luò)相關(guān)部分的實(shí)現(xiàn) 18
6.4 項(xiàng)目運(yùn)行 24
第7章 系統(tǒng)移植與調(diào)試 24
第1章 嵌入式硬件開(kāi)發(fā)環(huán)境
1.1 嵌入式系統(tǒng)的概念
以應(yīng)用為中心,以計(jì)算機(jī)技術(shù)為基礎(chǔ)、軟硬件可裁剪、適應(yīng)應(yīng)用系統(tǒng)對(duì)功能、可靠性、成本、體積、功耗嚴(yán)格要求的專用計(jì)算機(jī)系統(tǒng)。開(kāi)發(fā)機(jī)稱為宿主機(jī),應(yīng)用機(jī)稱為目標(biāo)機(jī)。
1.2 熟悉OURS PXA270RP實(shí)驗(yàn)箱的硬件環(huán)境
1、認(rèn)識(shí)核心板和擴(kuò)展板
2、認(rèn)識(shí)nor flash、nand flash、sdram、ARM處理器
3、熟悉電源接口、并口、JTAG接口、串口、網(wǎng)口、USB接口
4、熟練掌握將PC機(jī)與開(kāi)發(fā)實(shí)驗(yàn)箱的連接
第2章 Linux常用命令
Shell與用戶間的關(guān)系如圖 2.1 所示。用戶在提示符下輸入的命令都由Shell 先解釋然后傳給 Linux 內(nèi)核。
圖 2.1 內(nèi)核、Shell 和用戶的關(guān)系
小知識(shí):命令的使用可以通過(guò)man 命令名或命令名 -–help的方式獲得幫助。
1、ls: 列出目錄的內(nèi)容,常用參數(shù)有-l(長(zhǎng)文件名顯示格式)和-a(顯示所有文件), 顯示格式為:
文件類型與權(quán)限 鏈接數(shù) 文件屬主 文件屬組 文件大小 修改的時(shí)間 名字
2、find: 在指定目錄中搜索文件,常用參數(shù)為-name,如find /usr/qpe/pic/ -name *.png
3、cd: 改變工作目錄。可使用“cd –”回到前次工作目錄?!?/”代表當(dāng)前目錄,“../”代表上級(jí)目錄。
4、mkdir: 創(chuàng)建一個(gè)目錄,可以一次建立多個(gè)目錄,常用參數(shù)有-p(自動(dòng)創(chuàng)建指定路徑中不存在的目錄),如mkdir /home/lny/myfile
5、rm: 刪除一個(gè)目錄中的一個(gè)或多個(gè)文件或目錄,常用參數(shù)-f(刪除已存在的目標(biāo)文件而不提示),-i(在覆蓋目標(biāo)文件前要求用戶確認(rèn)),-r(遞歸地刪除該目錄及其子目錄下的所有內(nèi)容)
6、cp: 將給出的文件或目錄復(fù)制到另一文件或目錄中,常用參數(shù)有-a(保留鏈接、文件屬性、并復(fù)制其子目錄),-f(同rm),-i(同rm)
7、mv: 為文件或目錄改名或?qū)⑽募梢粋€(gè)目錄移入另一個(gè)目錄中,常用參數(shù)-f(同rm),-i(同rm)
8、ln: 為某一個(gè)文件在另外一個(gè)位置建立一個(gè)符號(hào)鏈接,常用參數(shù)-s(建立符號(hào)鏈接),如在當(dāng)前目錄下創(chuàng)建/usr/qpe/lib/fonts的軟鏈接可以用命令
ln -s /usr/qpe/lib/fonts/ ./fonts
9、fdisk: 可以查看硬盤(pán)分區(qū)情況,并可對(duì)硬盤(pán)進(jìn)行分區(qū)管理,如fdisk -l
10、mount:磁盤(pán)掛載命令。如掛載根目錄mount –o soft,timeo=100,rsize=1024 192.168.0.100:/ /mnt;
掛載U盤(pán)mount –t vfat /dev/sdb1 /mnt/usb
掛載windows目錄為mount -o username=administrator,password=pldy123,iocharset=utf8 //172.21.28.71/c /mnt/c
若想設(shè)置在開(kāi)機(jī)時(shí)自動(dòng)掛載,可在文件“/etc/fstab”中加入相應(yīng)的設(shè)置行即可。
11、echo: 顯示字符串
12、export: 設(shè)置新的環(huán)境變量,如export QTDIR=/usr/local/Trolltech/Qt-4.4.3
export LD_LIBRARY_PATH=$QTDIR/lib:$LD_LIBRARY_PATH
13、chmod: 改變文件的訪問(wèn)權(quán)限. 文件的訪問(wèn)權(quán)限可表示成:- rwx rwx rwx。在此設(shè)有三種不同的訪問(wèn)權(quán)限:讀(r)、寫(xiě)(w)和運(yùn)行(x);三個(gè)不同的用戶級(jí)別:文件擁有者(u)、所屬的用戶組(g)和系統(tǒng)里的其他用戶(o)。可增加一個(gè)用戶級(jí)別 a(all)來(lái)表示所有這三個(gè)不同的用戶級(jí)別。
① 對(duì)于第一種符號(hào)連接方式的 chmod 命令中,用加號(hào)“+”代表增加權(quán)限,用減號(hào)“?”刪除權(quán)限,等于號(hào)“=”設(shè)置權(quán)限,如chmod a+rx,u+w /home/lny/myfile
② 對(duì)于第二種八進(jìn)制數(shù)指定的方式,將文件權(quán)限字符代表的有效位設(shè)為“1”,即“rw-”、“rw-”和“r--”的八進(jìn)制表示為“110”、“110”、“100”,把這個(gè) 2 進(jìn)制串轉(zhuǎn)換成對(duì)應(yīng)的 8 進(jìn)制數(shù)就是 6、6、4,也就是說(shuō)該文件的權(quán)限為 664(三位八進(jìn)制數(shù)),如chmod 765 /home/lny/myfile
14、tar: 對(duì)文件目錄進(jìn)行打包或解包,常用參數(shù)有-c(建立新的打包文件),-f(對(duì)普通文件操作),-x(從打包文件中解出文件),-v(處理過(guò)程中輸出相關(guān)信息),-z(調(diào)用gzip來(lái)壓縮打包文件,與-x聯(lián)用時(shí)調(diào)用gzip完成解壓縮),-j(調(diào)用bzip2來(lái)壓縮打包文件,與-x聯(lián)用時(shí)調(diào)用bzip2完成解壓縮)。如tar -zcvf lny.tar.gz /home/lny; tar -jxvf linux-2.6.11.tar.bz2
第3章 搭建嵌入式Linux開(kāi)發(fā)環(huán)境
3.1 vwaretools的安裝與共享設(shè)置
1、安裝VMware tools,以方便鼠標(biāo)內(nèi)外移動(dòng)(確?!疤摂M化”不選),步驟如下:
VM菜單
→VMware tools install
→“是”
→將光驅(qū)(linux中的光驅(qū))的VMware tools 中的Vmwaretools-6.0.2-59824.tar.gz復(fù)制到目錄root下
→在終端對(duì)Vmwaretools-6.0.2-59824.tar.gz進(jìn)行解壓tar –zxvf Vmwaretools-6.0.2-59824.tar.gz
→cd vmware-tools-distrib
→./vmware-install.pl(全部選yes,注意有一個(gè)默認(rèn)為[no]的選項(xiàng)改為yes)
2、設(shè)置windows與linux相互共享:
Windows下訪問(wèn)linux的內(nèi)容:
確保網(wǎng)線正確連接;
確保網(wǎng)絡(luò)端口激活(系統(tǒng)→管理→網(wǎng)絡(luò)→設(shè)置靜態(tài)IP并激活);
確保samba服務(wù)安裝并啟動(dòng)(系統(tǒng)→管理→服務(wù)器設(shè)置→services中勾選smb選項(xiàng));
添加samba用戶(必須是存在的用戶,如果沖突,則注釋/etc/samba/smbusers中對(duì)應(yīng)的用戶名)(“首選項(xiàng)”→samba用戶→添加用戶);
添加共享(選擇共享目錄和設(shè)置共享對(duì)象權(quán)限等)。
通過(guò)\\192.168.11.7即“\\虛擬機(jī)ip”的形式訪問(wèn)。
3、Linux下訪問(wèn)windows的內(nèi)容:
確保安裝時(shí)沒(méi)有選擇“虛擬化”選項(xiàng);
菜單VM
→settings
→options
→shared folds
→add。
在linux系統(tǒng)下通過(guò)/mnt/hgfs目錄訪問(wèn)windows中共享文件夾。
3.2 tslib-1.4的編譯安裝
假設(shè)源碼解壓目錄為: /home/tslib-1.4
1、cd /home/tslib-1.4
./autogen.sh //生成congigure
2、./configure --host=arm-linux --cache-file=arm-linux.cache//加上參數(shù)--prefix=/home/tslib-1.4可以看到頭文件
3、make
出現(xiàn)錯(cuò)誤:undefined reference 'rpl_malloc'
解決:將config.h.in中的
#undef malloc 行注釋掉
重新執(zhí)行make,OK!
4、make install
生成的庫(kù)文件分別在目錄./src、./plugins的.lib目錄中,其中./lib為隱藏目錄,src/.lib中包含libts-0.0.so.0.1.1,libts-0.0.so.0、libts.la、libts.lai、libts.so,plugins/.lib中包含ucb1x00.so、pthres.so、linear.so、input.so、variance.so、dejitter.so等,庫(kù)文件版本為libts-0.0.so.0.1.1
5、拷貝
mkdir tslib-1.4
cd tslib-1.4
mkdir lib etc plugins include tests
目錄lib:將src/.lib/中的libts-0.0.so.0,libts-0.0.so.0.1.1,libts.so拷到其中。
目錄etc: 將etc/中的ts.conf拷到其中。//結(jié)合自己的觸摸屏型號(hào)進(jìn)行相應(yīng)的修改
目錄plugins: 將plugins/.libs/中的*.so拷到其中。//結(jié)合自己的觸摸屏型號(hào),刪除部分庫(kù)文件
目錄tests: 將tests/中的ts_*拷到其中。//只需要保留ts_calibrate和ts_test
目錄include:將src/tslib.h拷到其中。
6、測(cè)試
執(zhí)行測(cè)試程序ts_calibrate時(shí)一直出現(xiàn)錯(cuò)誤:ts_open:no such device
通過(guò)查找ts_calibrate.c發(fā)現(xiàn),編譯時(shí)如果沒(méi)有加參數(shù)--enable-inputapi=no,則應(yīng)將環(huán)境變量定義如下:
export TSLIB_TSDEVICE=/dev/input/event0(出錯(cuò)時(shí)為T(mén)SLIB_TSDEVICE=/dev/touchscreen/ucb1x00,因?yàn)槲业挠|摸屏型號(hào)為 ucb1x00)
export TSLIBDIR=/home/tslib-1.4
export TSLIB_CONFFILE=$TSLIBDIR/etc/ts.conf
export TSLIB_PLUGINDIR=$TSLIBDIR/plugins
export TSLIB_FBDEVICE=/dev/fb0
export TSLIB_CONSOLEDEVICE=none
export POINTERCAL_FILE=/etc/pointercal //生成校準(zhǔn)文件
export LD_LIBRARY_PATH=$TSLIBDIR/lib
export QWS_MOUSE_PROTO=TPanel:/dev/touchscreen/ucb1x00
export TSLIB_CALIBFILE=/etc/pointercal //應(yīng)用校準(zhǔn)文件
[ -f /etc/pointercal ] || /home/tslib-1.4/tests/ts_calibrate //檢查是否存在校準(zhǔn)文件
另外,還要注意的是,ts.conf內(nèi)容如下:
module_raw input
#module_raw ucb1x00 //如果注釋前一句而保留該句,則會(huì)出現(xiàn)意想不到的問(wèn)題。
module pthres pmin=1
module variance delta=30
module dejitter delta=100
module linear
執(zhí)行ts_calibrate順利通過(guò)。
3.3 qtX11和qtE4的編譯安裝
一、QT-X11環(huán)境的配置
1、解壓qt-x11-4.4.3.tar.gz
2、cd 解壓了的目錄 QT-X11
3、 #./configure //生成Makefile
#make //要好幾個(gè)小時(shí)(約3個(gè)半小時(shí))
#make install //安裝完后會(huì)生成目錄/usr/local/Trolltech/QT-4.4.3 ,這時(shí)剛才解壓完得到的QT-X11可以不要了。
4、設(shè)置環(huán)境變量(實(shí)際上是設(shè)置編譯環(huán)境):
在/etc/profile 加入:
#for QT-X11-4.4.3
export QTDIR=/usr/local/Trolltech/Qt-4.4.3
export LD_LIBRARY_PATH=$QTDIR/lib:$LD_LIBRARY_PATH
export PATH=$QTDIR/bin:$PATH
export QMAKESPEC=$QTDIR/mkspecs/linux-g++
5、#source /etc/profile 使環(huán)境變量生效,確保要用的編譯器擺在首位,以屏蔽系統(tǒng)自帶的編譯器。
二、QT-embed環(huán)境的配置
1、把a(bǔ)rm-linux-gcc版本:3.3.2 放目錄/usr/local/arm并在環(huán)境變量PATH中指明
#export PATH=/usr/local/arm/3.3.2/bin:$PATH
2、解壓qt-embedded-linux-4.4.3.tar.gz 得qt-embed
3、配置
支持觸摸屏的參數(shù)配置:
./configure -release -shared -fast -no-largefile -qt-sql-sqlite
-no-qt3support -no-xmlpatterns -no-mmx -no-3dnow -no-sse -no-sse2
-no-svg -no-webkit -qt-zlib -qt-gif -qt-libtiff -qt-libpng -qt-libmng
-qt-libjpeg -make libs -nomake tools -nomake examples -nomake docs
-nomake demo -no-nis -no-cups -no-iconv -no-dbus -no-openssl
-xplatform qws/linux-arm-g++ -embedded arm -little-endian -qt-freetype
-depths 16,18 -qt-gfx-linuxfb -no-gfx-transformed -no-gfx-multiscreen
-no-gfx-vnc -no-gfx-qvfb -qt-kbd-usb -no-glib -qt-mouse-tslib
-I/home/tslib-1.4/include -L/home/tslib-1.4/lib
4、#make
5、#make install
3.4 PATH與LD_LIBRARY_PATH的設(shè)置
參考3.3節(jié)內(nèi)容。
3.5 配置交叉編譯器
修改/etc/profile,在有“pathmunge”命令語(yǔ)句處加上如下命令語(yǔ)句:
Pathmunge /usr/local/arm-linux/bin
3.6 配置minicom、tftp和NFS
1、配置minicom
開(kāi)發(fā)板上的信息顯示給開(kāi)發(fā)人員最常用的就是通過(guò)串口線輸出到宿主機(jī)的顯示器上,這樣,開(kāi)發(fā)人員就可以看到系統(tǒng)的運(yùn)行情況了。Minicom 是 Linux 下串口通信的軟件,它的使用完全依靠鍵盤(pán)的操作,雖然沒(méi)有“超級(jí)終端”那么易用,但是使用習(xí)慣之后讀者將會(huì)體會(huì)到它的高效與便利。下面主要講解如何對(duì)Minicom 進(jìn)行串口參數(shù)的配置。
首先在命令行中鍵入“minicom”,這就啟動(dòng)了 minicom 軟件。Minicom 在啟動(dòng)時(shí)默認(rèn)會(huì)進(jìn)行初始化配置,如圖 3.1 所示。
圖 3.1 minicom 啟動(dòng)
注意 在 Minicom 的使用中,經(jīng)常會(huì)遇到三個(gè)鍵的操作,如“CTRL-A Z”,這表示先同時(shí)按下 CTRL和“A”(大寫(xiě)),然后松開(kāi)此二鍵再按下“Z”。
正如圖 3.1 中的提示,接下來(lái)可鍵入 CTRL+A Z,來(lái)查看 minicom 的幫助,如圖 3.2所示。按照幫助所示,可鍵入“O”(代表 Configure Minicom)來(lái)配置 minicom 的串口參數(shù),當(dāng)然也可以直接鍵入“CTRL-A O”來(lái)進(jìn)行配置,如圖 3.3 所示。
圖3.2 minicom 幫助
圖 3.3 minicom 配置界面
在這個(gè)配置框中選擇“Serial port setup”子項(xiàng),進(jìn)入如圖 3.4 所示配置界面。上面列出的配置是 minicom 啟動(dòng)是的默認(rèn)配置,用戶可以通過(guò)鍵入每一項(xiàng)前的大寫(xiě)字母,分別對(duì)每一項(xiàng)進(jìn)行更改。圖 3.5 所示為在“Change which setting 中”鍵入了“A”,此時(shí)光標(biāo)轉(zhuǎn)移到第 A 項(xiàng)的對(duì)應(yīng)處。
注意 在 minicom 中“ttyS0”對(duì)應(yīng)“COM1”,“ttyS1”對(duì)應(yīng)“COM2”。
圖3.4 minicom 串口屬性配置界面
圖 3.5 minicom 串口號(hào)配置
接下來(lái),要對(duì)波特率、數(shù)據(jù)位和停止位進(jìn)行配置,鍵入“E”,進(jìn)入如圖 3.6 所示的配置界面。
在該配置界面中,可以鍵入相應(yīng)波特率、停止位等對(duì)應(yīng)的字母,即可實(shí)現(xiàn)配置,配置完成后按回車鍵就退出了該配置界面,在上層界面中顯示如圖 3.7 所示配置信息,要注意與圖3.4 進(jìn)行對(duì)比,確定相應(yīng)參數(shù)是否已被重新配置。
圖 3.6 minicom 波特率等配置界面
圖 3.7 minicom 配置完成后界面
到此為止,讀者已經(jīng)能將開(kāi)發(fā)板的系統(tǒng)情況通過(guò)串口打印到宿主機(jī)上了,這樣,就能很好地了解硬件的運(yùn)行狀況。
小知識(shí) 通過(guò)串口打印信息是一個(gè)很常見(jiàn)的手段,很多其他情況如路由器等也是通過(guò)配置串口的波特率這些參數(shù)來(lái)顯示對(duì)應(yīng)信息的。
2、tftp
tftp 協(xié)議是簡(jiǎn)單文件傳輸協(xié)議,它可以看作是一個(gè) FTP 協(xié)議的簡(jiǎn)化版本,與 FTP 協(xié)議相比,它的最大區(qū)別在于沒(méi)有用戶管理的功能。它的傳輸速度快,可以通過(guò)防火墻,使用方便快捷,因此在嵌入式的文件傳輸中廣泛使用。
tftp 分為客戶端和服務(wù)器端兩種。通常,首先在宿主機(jī)上開(kāi)啟 tftp 服務(wù)器端服務(wù),設(shè)置好 tftp 的根目錄內(nèi)容(也就是供客戶端下載的文件),接著,在目標(biāo)板上開(kāi)啟 tftp的客戶端程序(現(xiàn)在很多開(kāi)發(fā)板都已經(jīng)提供了該項(xiàng)功能)。這樣,把目標(biāo)板和宿主機(jī)用直連線相連之后,就可以通過(guò) tftp 協(xié)議傳輸可執(zhí)行文件了。
Linux 下 tftp 的服務(wù)器服務(wù)是由 xinetd 所設(shè)定的,默認(rèn)情況下是處于關(guān)閉狀態(tài)。首先,要修改 tftp 的配置文件,開(kāi)啟 tftp 服務(wù),如下所示:
[root@ateng tftpboot]# vi /etc/xinetd.d/tftp
# default: off
# description: The tftp server serves files using the trivial file transfer \
# protocol. The tftp protocol is often used to boot diskless \
# workstations, download configuration files to network-aware printers, \
# and to start the installation process for some operating systems.
service tftp
{
socket_type = dgram
protocol = udp
wait = yes
user = root
server = /usr/sbin/in.tftpd
server_args = -s /tftpboot
disable = no
per_source = 11
cps = 100 2
flags = IPv4
}
在這里,主要要將“disable=yes”改為“no”,另外,從“server_args”可以看出,tftp服務(wù)器端的默認(rèn)根目錄為“/tftpboot”,用戶若需要可以更改為其他目錄。接下來(lái),重啟 xinetd 服務(wù),使剛才的更改生效,如下所示:
[root@ateng tftpboot]# service xinetd restart
關(guān)閉 xinetd: [ 確定 ]
啟動(dòng) xinetd: [ 確定 ]
接著,使用命令“netstat -au”以確認(rèn) tftp 服務(wù)是否已經(jīng)開(kāi)啟,如下所示:
[root@ateng tftpboot]# netstat -au
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State
udp 0 0 *:32768 *:*
udp 0 0 *:831 *:*
udp 0 0 *:tftp *:*
udp 0 0 *:sunrpc *:*
udp 0 0 *:ipp *:*
這時(shí),用戶就可以把所需要的傳輸文件放到“/tftpboot”目錄下,這樣,主機(jī)上的 tftp 服務(wù)就可以建立起來(lái)了。
接下來(lái),用直連線(注意:不可以使用網(wǎng)線)把目標(biāo)板和宿主機(jī)連起來(lái),并且將其配置成一個(gè)網(wǎng)段的地址,再在目標(biāo)板上啟動(dòng) tftp 客戶端程序(注意:不同的開(kāi)發(fā)板所使用的命令可能會(huì)不同,讀者可以查看幫助來(lái)獲得確切的命令名及格式),如下所示:
=>tftpboot 0x30200000 zImage
TFTP from server 192.168.1.1; our IP address is 192.168.1.100
Filename 'zImage'.
Load address: 0x30200000
Loading: #################################################################
###############################################################
#############################################
done
Bytes transferred = 881988 (d7544 hex)
可以看到,此處目標(biāo)板使用的 IP 為“192.168.1.100”,宿主機(jī)使用的 IP 為“192.168.1.1”,下載到目標(biāo)板的地址為 0x30200000,文件名為“zImage”。
小知識(shí) tftp 是一個(gè)很好的文件傳輸協(xié)議,它的簡(jiǎn)單易用吸引了廣大用戶。但它同時(shí)也存在著較大的安全隱患。由于 tftp 不需要用戶的身份認(rèn)證,因此給了黑客的可乘之機(jī)。因此在使用 tftp 時(shí)一定要設(shè)置一個(gè)單獨(dú)的目錄作為 tftp 服務(wù)的根目錄,如上文所述的“/tftpboot”等。
3、NFS
在/etc/exports中加入語(yǔ)句:
/ 192.168.0.* (rw,inscure,no_root_squash,no_all_squash)
第4章bootloader、Linux內(nèi)核及文件系統(tǒng)制作與移植
4.1 bootloader
1、編譯
cd /pxa270_linux/blob_ours/blob-xscale
make –f Makefile.cvs
./configure –host=arm-linux –with-board=mainstone –with-linux-prefix=/pxa270_linux/linux/ --enable-xli –enable-network
make(保存在/pxa270_linux/blob_ours/blob-xscale/src/blob下)
2、移植(確保開(kāi)發(fā)板上電)
cd /pxa270_linux/tools
./Jflashmm-linux PXA270 blob p(該命令是尋找PXA270.dat文件所指定的CPU,把blob文件燒寫(xiě)到這個(gè)CPU使用的flash中,要求blob,PXA270.dat與Jflashmm-linux在同一個(gè)文件夾中,.dat文件不可以加后綴。
4.2 Linux內(nèi)核編譯與移植
1、編譯
內(nèi)核的編譯根據(jù)不同的情況會(huì)有不同的步驟,但其中最主要分別為3 個(gè)步驟:內(nèi)核配置、建立依存關(guān)系、建立內(nèi)核,其他的為一些輔助功能,如清除文件等。
(1)內(nèi)核配置
cd /pxa270_linux/linux
make menuconfig (菜單式配制)
在menuconfig 的配置界面是圖形化的內(nèi)核裁減界面。通過(guò)此部分,讀者可以方便地選擇,決定哪些部分被加載并編譯入Linux內(nèi)核,哪些部分被編譯為模塊,哪些部分不用,如圖 4.1 所示。“Load an Alternate Configuration File”選項(xiàng)表示裝載一個(gè)已經(jīng)保存好的設(shè)置。也可以選擇“Save Configuration to an Alternate File”選項(xiàng)保存自己的配置文件。
圖 4.1 make menuconfig 配置界面
此外,要注意 2.6 和 2.4 內(nèi)核在串口命名上的一個(gè)重要區(qū)別,在 2.4 內(nèi)核中“COM1”對(duì)應(yīng)的是“ttyS0”,而在 2.6 內(nèi)核中“COM1”對(duì)應(yīng)“ttySAC0”,因此在啟動(dòng)參數(shù)的子項(xiàng)要格外注意,如圖4.3 所示,否則串口打印不出信息。
(2)建立依賴關(guān)系
make dep
由于內(nèi)核源碼樹(shù)中的大多數(shù)文件都與一些頭文件有依賴關(guān)系,因此要順利建立內(nèi)核,內(nèi)核源碼樹(shù)中的每個(gè) Makefile 就必須知道這些依賴關(guān)系。建立依賴關(guān)系往往發(fā)生在第一次編譯內(nèi)核的時(shí)候,它會(huì)在內(nèi)核源碼樹(shù)中每個(gè)子目錄產(chǎn)生一個(gè)“.depend”文件。
(3)建立內(nèi)核
make clean
make zImage
這里建立的為壓縮的內(nèi)核映像,名為zImage,位于/pxa270_linux/linux/arch/arm/boot目錄中。
2、移植
cp zImage /tftpboot –rf (虛擬機(jī)終端)
以下命令在minicom中完成:
blob>tftp zImage –kernel (下載到內(nèi)存0xa0008000處)
blob>fwrite 0xa0008000 0x00040000 0x00200000
表示從內(nèi)存0xa0008000處取出長(zhǎng)度為0x00200000的數(shù)據(jù),寫(xiě)入flash中0x00040000開(kāi)始的地址中。
4.3文件系統(tǒng)制作與移植
1、制作文件系統(tǒng):
cd /pxa270_linux/fs
./mkfs.jffs2 –r rootfs270 –o xscale_fs.jffs2 –e 0x40000 –pad=0x01000000(根文件系統(tǒng))
./mkfs.jffs2 –r junk –o junk.jffs2 –e 0x40000 –pad=0x0dc0000(擴(kuò)展文件系統(tǒng))
其中,-r后面是指令要做成image的文件夾,默認(rèn)為當(dāng)前文件夾;-o后面是指令輸出的文件名,-e表擦除塊的大小,默認(rèn)為64KB,--pad表輸出文件的大小,為了不浪費(fèi)flash空間,這個(gè)值最好符合flash driver所規(guī)劃的區(qū)塊大小,如果不足,則使用0xff來(lái)填充補(bǔ)滿。
2、文件系統(tǒng)移植:
cp xscale_fs.jffs2 /tftpboot –rf (虛擬機(jī)終端)
cp junk.jffs2 /tftpboot –rf (虛擬機(jī)終端)
以下命令在minicom中完成:
blob>tftp xscale_fs.jffs2
blob>fwrite 0xa1000000 0x00240000 0x01000000
blob>tftp junk .jffs2
blob>fwrite 0xa1000000 0x01240000 0x0dc0000
表示從內(nèi)存0xa1000000處取出長(zhǎng)度為0x0dc0000的數(shù)據(jù),寫(xiě)入flash中0x01240000開(kāi)始的地址中。
第5章 Qt圖形編程
5.1 嵌入式GUI簡(jiǎn)介
GUI( 圖形用戶界面)是指計(jì)算機(jī)與其使用者之間的對(duì)話接口,它的存在為使用者提供了友好便利的界面,并大大方便了非專業(yè)用戶的使用,使得人們從煩瑣的命令中解脫出來(lái),可以通過(guò)窗口、菜單方便地進(jìn)行操作。
Qt/Embedded是Trolltech(奇趣)公司為嵌入式系統(tǒng)開(kāi)發(fā)的Qt版本。從Qt 4.1版本開(kāi)始,Qt/Embedded改名為Qtopia Core,又從Qt 4.4.1版本開(kāi)始,又改名為Qt for Embedded Linux。其優(yōu)點(diǎn)是:
1、以開(kāi)發(fā)包的形式提供,包括了圖形設(shè)計(jì)器、Makefile制作工具、字體國(guó)際化工具、Qt的C++類庫(kù)等。
2、支持跨平臺(tái)(如Microsoft Windows、MacOS X、Linux、Solaris等)。
3、類庫(kù)支持跨平臺(tái)(封裝了適應(yīng)不同操作系統(tǒng)的訪問(wèn)細(xì)節(jié))。
4、模塊化,可任意裁減(最小可裁減到幾百KB,但這時(shí)已基本失去了使用價(jià)值)。
缺點(diǎn)是:結(jié)構(gòu)過(guò)于復(fù)雜臃腫,很難進(jìn)行底層的擴(kuò)充、定制和移植。
5.2 Qt/Embedded開(kāi)發(fā)入門(mén)
5.2.1 Qt/Embedded介紹
1、架構(gòu)如下圖所示。
應(yīng)用程序源代碼
Qt API
Qt/Embedded
Qt/X11
Qt/XLib
X Windows Server
幀緩沖
Linux內(nèi)核
Qt/Embedded與Qt/X11的Linux版本的比較
2、Qt的開(kāi)發(fā)環(huán)境
Qt桌面版本:Qt/X11或Qt/Windows,結(jié)合大家熟知的Visual C++或Borland C++就可以進(jìn)行開(kāi)發(fā)了。`
3、Qt的支撐工具
Qmake和Qt designer(圖形設(shè)計(jì)器)
5.2.2 Qt/Embedded圖形界面
Qt提供了一整套的窗口部件,它們組合起來(lái)可用于創(chuàng)建用戶界面的可視元素。窗口部件是QWidget或其子類的實(shí)例,用戶自定義的窗口通過(guò)子類化得到,如下圖所示。
QObject
QTimer
QWidget
QDialog
QFrame
QSpinBox
QLabel
QLineEdit
對(duì)于初學(xué)者來(lái)說(shuō),使用designer工具設(shè)計(jì)程序界面非常方便快捷,如秒表程序stopwatch的界面文件digclock.ui效果如下圖所示。
播放器程序mediaplayer界面文件videoface.ui效果如下圖所示。
對(duì)應(yīng)的.h文件代碼自動(dòng)生成,但比較復(fù)雜,為了熟悉代碼,完全可以用代碼的形式生成用戶界面,如通訊錄程序addressbook中的部分代碼如下:
addressBook::addressBook(QWidget *parent)
{
setWindowTitle(tr("this is addressbook."));
setFixedSize(lcdWidth,lcdHeight);
contacts=new QMap<QString,QString>;
saveBt=new QPushButton(tr("save")) ;
cancelBt=new QPushButton(tr("cancel"));
findBt=new QPushButton(tr("find"));
contactName=new QLabel(tr("name"));
contactTele=new QLabel(tr("telephone"));
nameDetail=new QLineEdit;
teleNo=new QTextEdit ;
QHBoxLayout *hlayout=new QHBoxLayout;
hlayout->addWidget(saveBt,Qt::AlignCenter);
hlayout->addWidget(cancelBt,Qt::AlignJustify);
hlayout->addWidget(findBt,Qt::AlignCenter);
QGridLayout *layout=new QGridLayout;
layout->addWidget(contactName,0,0,Qt::AlignRight);
layout->addWidget(nameDetail,0,1);
layout->addWidget(contactTele,1,0,Qt::AlignTop);
layout->addWidget(teleNo,1,1,Qt::AlignLeft);
layout->addLayout(hlayout,2,1);
setLayout(layout);
connect(saveBt,SIGNAL(clicked()),this,SLOT(saveInform()));
connect(cancelBt,SIGNAL(clicked()),this,SLOT(cancelInform()));
connect(findBt,SIGNAL(clicked()),this,SLOT(findName()));
}
5.2.3 Qt/Embedded信號(hào)和槽機(jī)制
1、機(jī)制概述
信號(hào)(signals)和槽機(jī)制是Qt的核心機(jī)制,是Qt自行定義的一種通信機(jī)制,獨(dú)立于標(biāo)準(zhǔn)的C/C++語(yǔ)言。所有從QObject或其子類(如QWidget)派生的類都能夠包含信號(hào)和槽。當(dāng)對(duì)象改變狀態(tài)時(shí),信號(hào)就由該對(duì)象發(fā)射(Emit)出去了,它不知道另一端是是誰(shuí)在接收這個(gè)信號(hào)。槽函數(shù)用于接收信號(hào),它們是普通的對(duì)象成員函數(shù),一個(gè)槽函數(shù)并不知道是否有任何信號(hào)與自己相連接。
對(duì)象間信號(hào)與插槽的關(guān)系
用戶可以將多個(gè)信號(hào)與單個(gè)槽函數(shù)連接,也可以將單個(gè)信號(hào)與多個(gè)槽函數(shù)連接,甚至將一個(gè)信號(hào)與另外一個(gè)信號(hào)相連接。其間的關(guān)系如下圖所示。
對(duì)象2
信號(hào)1
槽1
槽2
對(duì)象1
信號(hào)1
信號(hào)2
對(duì)象3
槽1
槽2
2、信號(hào)與插槽實(shí)現(xiàn)
信號(hào)的定義:
signals:
void mySignal();
void mySignal(int x);
void mySignalParam(int x,int y);
槽函數(shù)的定義:
public slots:
void mySlot();
void mySlot(int x);
void mySlotParam(int x,int y);
信號(hào)與插槽關(guān)聯(lián)(通過(guò)QObject對(duì)象的connect()函數(shù)實(shí)現(xiàn))
QLabel *label=new QLabel;
QScrollBar *scroll=new QScrollBar;
QObject::connect(scroll,SIGNAL(valueChanged(int)),label,SLOT(setNum(int)));
5.2.4 Qt/Embedded網(wǎng)絡(luò)編程
QTcpSocket和QTcpServer類,具體查看Qt的幫助文檔。
第6章 聊天系統(tǒng)設(shè)計(jì)與實(shí)現(xiàn)
6.1 聊天系統(tǒng)需求分析
1、使用對(duì)象:09計(jì)嵌。
2、系統(tǒng)說(shuō)明:以宿舍為單位,主界面中的成員為全班同學(xué),聊天包括私聊、群聊(信息僅限于本宿成員)和廣播(全班同學(xué)都能看到);ID為各自的學(xué)號(hào),禁止非本班同學(xué)登錄。
3、功能分析:注冊(cè)、登錄、下線、加入群、退出群、添加和修改個(gè)人信息、聊天、提供對(duì)用戶信息和聊天信息的保存等。
6.2 界面設(shè)計(jì)
服務(wù)器端創(chuàng)建聊天室 客戶端登錄界面
6.3 網(wǎng)絡(luò)相關(guān)部分的實(shí)現(xiàn)
服務(wù)器端程序部分代碼:
TcpServer::TcpServer(QWidget *parent,Qt::WindowFlags f)
:QDialog(parent,f)
{
setWindowTitle(tr("TCP Server"));
QVBoxLayout *vbMain=new QVBoxLayout(this);
ListWidgetContent=new QListWidget(this);
vbMain->addWidget(ListWidgetContent);
QHBoxLayout *hb=new QHBoxLayout();
LabelPort=new QLabel(this);
LabelPort->setText(tr("Port"));
hb->addWidget(LabelPort);
LineEditPort=new QLineEdit(this);
hb->addWidget(LineEditPort);
vbMain->addLayout(hb);
PushButtonCreate=new QPushButton(this);
PushButtonCreate->setText(tr("create"));
vbMain->addWidget(PushButtonCreate);
connect(PushButtonCreate,SIGNAL(clicked()),this,SLOT(slotCreateServer()));
port=8010;
LineEditPort->setText(QString::number(port));
}
TcpServer::~TcpServer()
{
}
void TcpServer::slotCreateServer()
{
server=new Server(this,port);
connect(server,SIGNAL(updateServer(QString,int)),
this,SLOT(updateServer(QString,int)));
PushButtonCreate->setEnabled(false);
}
void TcpServer::updateServer(QString msg,int length)
{
ListWidgetContent->addItem(msg.left(length));
}
TcpClientSocket::TcpClientSocket(QObject *parent)
{
connect(this,SIGNAL(readyRead()),this,SLOT(dataReceived()));
connect(this,SIGNAL(disconnected()),this,SLOT(slotDisconnected()));
}
void TcpClientSocket::dataReceived()
{
while(bytesAvailable()>0)
{
char buf[1024];
int length=bytesAvailable();
read(buf,length);
QString msg=buf;
emit updateClients(msg,length);
}
}
TcpClientSocket::~TcpClientSocket()
{
}
void TcpClientSocket::slotDisconnected()
{
this->close();
emit disconnected(this->socketDescriptor());
}
Server::Server(QObject *parent,int port)
:QTcpServer(parent)
{
listen(QHostAddress::Any,port);
}
void Server::incomingConnection(int socketDescriptor)
{
TcpClientSocket *tcpClientSocket=new TcpClientSocket(this);
connect(tcpClientSocket,SIGNAL(updateClients(QString,int)),
this,SLOT(updateClients(QString,int)));
connect(tcpClientSocket,SIGNAL(disconnected(int)),
this,SLOT(slotDisconnected(int)));
tcpClientSocket->setSocketDescriptor(socketDescriptor);
tcpClientSocketList.append(tcpClientSocket);
}
void Server::updateClients(QString msg,int length)
{
emit updateServer(msg,length);
for(int i=0;i<tcpClientSocketList.count();i++)
{
QTcpSocket *item=tcpClientSocketList.at(i);
if(item->write(msg.toLatin1(),length)!=length)
continue;
}
}
void Server::slotDisconnected(int descriptor)
{
for(int i=0;i<tcpClientSocketList.count();i++)
{
QTcpSocket *item=tcpClientSocketList.at(i);
if(item->socketDescriptor()==descriptor)
{
tcpClientSocketList.removeAt(i);
return;
}
}
return;
}
客戶端程序部分代碼:
TcpClient::TcpClient(QDialog *parent,Qt::WindowFlags f)
:QDialog(parent,f),status(false),port(8010)
{
setWindowTitle(tr("TCP client"));
ListWidgetContent=new QListWidget;
LineEditMsg=new QLineEdit;
PushButtonSend=new QPushButton(tr("send"));
PushButtonSend->setEnabled(false);
QHBoxLayout *msgLayout=new QHBoxLayout;
msgLayout->addWidget(LineEditMsg);
msgLayout->addWidget(PushButtonSend);
QHBoxLayout *userLayout=new QHBoxLayout;
userNameLabel=new QLabel(tr("user name:"));
LineEditUser=new QLineEdit;
userLayout->addWidget(userNameLabel);
userLayout->addWidget(LineEditUser);
QHBoxLayout *serverIPLayout=new QHBoxLayout;
serverIPLabel=new QLabel(tr("server IP:"));
LineEditServerIP=new QLineEdit;
serverIPLayout->addWidget(serverIPLabel);
serverIPLayout->addWidget(LineEditServerIP);
QHBoxLayout *portLayout=new QHBoxLayout;
portLabel=new QLabel(tr("port Num:"));
LineEditPort=new QLineEdit;
LineEditPort->setText(QString::number(port));
portLayout->addWidget(portLabel);
portLayout->addWidget(LineEditPort);
PushButtonEnter=new QPushButton(tr("enter"));
QVBoxLayout *mainlayout=new QVBoxLayout;
mainlayout->addWidget(ListWidgetContent);
mainlayout->addLayo