www.directfb.com.cn
kendych@sina.com.cn
著作權申明: 本文檔一切權利歸本人(kendych@sina.com.cn)所有,用於商業用途徐徵得本人同意,如無法連絡到本人,須徵得www.directfb.com.cn所有者同意;用於非商業用途的,無需任何許可,但請尊重本人的署名權,並註明出處www.directfb.com.cn及附加本申明。
關鍵詞: 嵌入式 GUI arm linux DirectFB GTK tslib
1 前言
數年前,曾經開發過一個嵌入式的產品,如今市場依然存在,但由於電子產品的升級換代很快,許多元器件都採購不到了,為了延續產品的生命週期,計劃在linux平台上開發新的版本。而在linux上的GUI上成了大問題,最開始有用Minigui的打算,也同飛漫公司聯絡過,但費用我這裡無法承受。(Minigui作為國產優秀的嵌入式GUI,如果不是費用的問題,應該是最優的選擇。) QT我也看了下,也是收費的,沒有仔細研究。最開始我打算用MicroWindow的,但後來發現這個東西好久沒有更新了,bug一大堆。最後的目光停留在GTK上,最開始無從下手,不知道到底適合不適合做嵌入式GUI,最後不知道在哪裡看到一個介紹說諾基亞有產品是用GTK的,覺得既然別人能做得,我也能做得。最開始做這個,相關資料太少,一點底都沒有,但經過兩個月(長了點)的努力,終於解決了所有問題,才一顆石頭落地。個人認為,在本文的協助下,如果你擁有初中級的嵌入式linux的知識,也許一天就能解決問題,最長也不會超過一個星期。
2 準備工作
硬體環境:linux主機一台,如果你喜歡用windows,可以在windows主機上用vmware虛擬一個linux系統。嵌入式開發套件,包括嵌入式開發板、帶觸屏的液晶屏及相關串連電纜。
軟體環境:x86 linux發行版,配置好framebuffer,並安裝好ftp server、telnet server、tftp server、nfs server、gcc及相關軟體、交叉編譯器、開發套件的kernel 2.6的源碼包。
本人用的是Ubuntu 7.10的發行版,嵌入式開發版採用三星的2440系列cpu,如何搭建開發環境不在本文討論範圍之類,請參考其他文檔。交叉編譯器用的是自己編譯的3.4.1,最開始採用的是開發套件帶的3.4.1,為什麼要用自己編譯的而不用開發套件內建的呢? 這裡說本文第一個秘笈:由於GTK採用的向量字型裡一些演算法使用了浮點運算,而24xx系列的cpu硬浮點不支援(我沒有相關知識,這是我的一個同事說得,是不是他本來意思,我都不敢確定,如果你的cpu不是這個系列的,請查看相關資料),只要在交叉編譯器裡加上軟浮點運算支援,就應該沒有問題了,所以在開始之前,先檢查交叉編譯器裡有沒有--with-float=soft這個選項。在我使用開發版內建的編譯完成編譯後,運行gtk的程式,總是有這個提示” shape engine failure, expect ugly output. the offending font is”,而螢幕上所有字元都顯示不出來,button由於字元無法顯示,被壓縮成一條線,這個問題困擾我好幾天,我開始以為是字型檔設定的問題,後來求助同事,他聽了我的描述後,猜測可能是浮點運算的問題,讓我用我們自己編譯的交叉編譯器重新編譯一下,看看能不能解決問題,結果真的解決了。
3 源碼包的選擇
選用GTK做嵌入式GUI是個痛苦的選擇,如果選用商業GUI如MiniGui,別人都給你整好了,你拿過來用就可以了,或者用Wince,還是與windows相容的。而選用GTK做GUI,不同組織(個人)編寫的15個軟體包,各個軟體包又有不同的版本,而網上又沒有權威的指南,如何選擇合適的版本以及如何整合確實是個非常複雜的問題。
我是先從在x86上搭建GTK環境開始的,首先我選用最新版本,然後,看到介紹說,GTK在framebuffer上運行有兩種模式: DirectFB 和linux-fb,而linux-fb的項目好像已經停止,主要方向是DirectFB,後來查的有個DirectFB + GTK的英文文檔,基本都選用最新的版本,而且很多包都可以使用系統內建的,編譯必須的源碼就可以了,最開始怎麼也編譯不成功,我快絕望的時候,發現釋放出一個最新的GTK源碼版本(大概是08年7月4日),我第一時間下載下來,很快就編譯出來了,並且在framebuffer模式下gtk-demo以及一些test運行一點問題都沒有。
熟悉了編譯過程後,我先嘗試用交叉編譯這個最新版本,編譯第一個包glib-2.16.4就失敗了。我在網上閱讀了很多關於交叉編譯DirectFB+GTK的的資料,有個用shell指令碼寫的好像不錯,但是看不懂呀,雖然我接觸unix都十多年了,還曾經在unix下做個一比較大型的項目,但後來,linux都是個人興趣,看了一些,玩了一些,沒做過東西,shell編程看過,好多東西一直半解,他那篇文檔看的我都傻了,這人真牛。但源碼包的選擇是可以借鑒的。
我的選擇:
1) tslib-1.0.tar.bz2
觸控螢幕本來我是最後弄的,但如果你需要觸屏支援,最好在一開始就搞定他。這個其實是tslib.14,為啥成了1.0的了,我也不知道,如何編譯不是很難,難在怎麼配置,相關文檔請閱讀本人的另外一篇文檔《arm-linux之tslib》,當然哪片文檔可能並不能幫你搞定,你需要動用你的聰明才智,你也許需要閱讀kernel裡觸屏驅動的源碼。我的開發套件觸屏控制器是用的cpu本身的AD轉換器,kernel裡的驅動是相容H3600的,所以我在ts.conf檔案裡module_raw模組設定為h3600。如果你用的三星的24XX系列的cpu,也許使用的方式跟我相同,使用同樣的配置也許可以,如果不行,可能要閱讀觸屏驅動的源碼及tslib的module_raw的源碼,找到匹配的模組就行了。
《arm-linux之tslib》的位置http://www.directfb.com.cn/viewthread.php?tid=388&extra=page%3D1
2) freetype-2.3.5.tar.bz2
3) glib-2.12.13.tar.bz2
4) libpng-1.2.19.tar.bz2
這個模組本來我是不需要的,我在編譯GTK的時候想disable這個模組,configure無法完成。
5) zlib-1.2.3.tar.bz2
6) jpegsrc.v6b.tar.gz
這個模組是我必須的,但編譯GTK的時候,configure說找不到這個模組的jpeglib.h,我也研究了好久,
7) tiff-3.7.4.tar.gz
這個模組我不需要,但編譯了,最終,我不會採用這個模組。
8) DirectFB-1.1.1.tar.gz
最開始我採用的是1.1.0,基本正常,最後弄觸屏的時候,運行程式DirectFB怎麼也載入不成功nputdrivers裡的模組libdirectfb_tslib.so,閱讀了相關代碼後,發現這個版本的DFB的這個模組載入後,不讀取tslib的相關環境變數,直接載入/dev/input/tslibn些裝置,而我的開發板起來後,根本沒有這些裝置,1.1.0之後的版本,相關代碼做過修正,我也嘗試了最新版本的DFB 1.2.1,但這個版本的DF B跟好核後面選用的GTK的版本配合有點問題,無法編譯後面的GTK,我閱讀DFB 1.1.1的相關代碼,發現已經修正,選用了這個版本,運行GTK程式,DFB開始載入tslib的相關模組,但只載入成功tslib的module_raw的模組,後面的模組載入失敗。什麼原因這裡不做解釋,後面再說。
9) atk-1.19.3.tar.bz2
10) expat-2.0.1.tar.gz
11) libxml2-2.6.29.tar.gz
12) fontconfig-2.4.2.tar.gz
13) pango-1.16.4.tar.bz2
14) cairo-1.4.10.tar.gz
15) gtk+-2.10.14.tar.bz2
這個模組最後編譯,編譯完成意味著我們成功完成了編譯工作,我configure這個模組的時候碰到了兩個問題:第一找不到pango,最後看到好多,才知道在configure前需要設定這個環境變數export LDFLAGS="-L$PREFIX/lib -Wl,-rpath,$PREFIX/lib" 這個啥意思,我不知道,為什麼這樣設我也不知道。第二找不到jpeglib.h,我分析了log,發現是在測試g++編譯的時候,找不到jpeglib.h,而測試gcc編譯是沒有問題的,我在configure前設定了這個export CPPFLAGS="-I$PREFIX/include"環境變數,告訴g++編譯器到哪裡找jpeglib.h。
4 交叉編譯
在宿主系統上交叉編譯後的所有包的安裝目錄為/usr/gtkdfb,當然,你可以使用其他的目錄,但絕不能跟主機環境相衝突,將交叉編譯後東西安裝到宿主系統的預設位置,可能會導致你的宿主系統某些不可預知的後果。下面開始編譯
1) Tslib
export PREFIX=/usr/gtkdfb
echo "ac_cv_func_malloc_0_nonnull=yes" >arm-linux.cache
./configure --host=arm-linux --prefix=$PREFIX --cache-file=arm-linux.cache --enable-inputapi=no
make
make install
編譯前只需要指定PREFIX一個環境變數,這個模組編譯下面的編譯基本都需要以下三個
export LDFLAGS=-L$PREFIX/lib
export CFLAGS="-g -I$PREFIX/include"
export PKG_CONFIG_PATH=$PREFIX/lib/pkgconfig
2) glib
echo ac_cv_type_long_long=yes>arm-linux.cache
echo glib_cv_stack_grows=no>>arm-linux.cache
echo glib_cv_uscore=no>>arm-linux.cache
echo ac_cv_func_posix_getpwuid_r=yes>>arm-linux.cache
CC=arm-linux-gcc ./configure --host=arm-linux --build=i686-pc-linux --prefix=$PREFIX --cache-file=arm-linux.cache
make
make install
3) atk
./configure --host=arm-linux --prefix=$PREFIX
make
make install
4) jpeg-6b
./configure --prefix=$PREFIX --enable-shared --enable-static
修改產生的Makefile檔案:
# The name of your C compiler:
CC= gcc 該成 CC=arm-linux-gcc (根據你自己交叉編譯器的位置修改)
# library (.a) file creation command
AR= ar rc 該成 AR= arm-linux-ar rc (同上)
# second step in .a creation (use "touch" if not needed)
AR2= ranlib 該成 AR2=arm-linux-ranlib (同上)
mkdir $PREFIX/man
mkdir $PREFIX/man/man1
make
make install-lib
5) zlib
CC=arm-linux-gcc ./configure --prefix=$PREFIX --shared
make
make install
6) libpng
./configure --host=arm-linux --prefix=$PREFIX
make
make install
7) expat
./configure --host=arm-linux --prefix=$PREFIX
make
make install
8) freetype
./configure --host=arm-linux --prefix=$PREFIX
make
make install
9) libxml
./configure --host=arm-linux --prefix=$PREFIX
make
make install
10) fontconfig
export LIBXML2_CFLAGS=-I$PREFIX/include/libxml2
export LIBXML2_LIBS="-L$PREFIX/lib -lxml2"
./configure --host=arm-linux --prefix=$PREFIX --with-freetype-config=$PREFIX/bin/freetype-config --with-arch=arm
make
make install
11) tiff
./configure --host=arm-linux --prefix=$PREFIX --enable-shared
make
make install
12) DirectFB
./configure --host=arm-linux --prefix=$PREFIX --with-gfxdrivers=none --with-inputdrivers=all --enable-png --enable-jpeg --disable-tiff --enable-zlib --enable-sdl=no --enable-gif=no --disable-x11
make
make install
13) cairo
./configure --host=arm-linux --prefix=$PREFIX --without-x --disable-xlib --disable-xlib-xrender --enable-directfb --enable-freetype --disable-win32 --enable-pdf --enable-ps --disable-svg --enable-png
make
make install
不知道為什麼,gtk非要有pdf和ps的支援,沒有就無法完成configure,沒辦法,我只好在這裡就開啟,其實也不能真正支援,因為pdf等東西根本沒有加進來。不知道後來的gtk版本有無改進。
14) Pango
修改configure檔案,將下面一些參數改成true
have_cairo=true
have_cairo_png=true
have_cairo_ps=true
have_cairo_pdf=true
have_cairo_freetype=true
./configure --host=arm-linux --prefix=$PREFIX --enable-cairo --without-x
make
make install
15) gtk
export LDFLAGS="-L$PREFIX/lib -Wl,-rpath,$PREFIX/lib"
export CPPFLAGS="-I$PREFIX/include"
./configure --host=arm-linux --prefix=$PREFIX --with-gdktarget=directfb --without-x --without-libtiff
make
make install
5 開發板運行環境
開發板的核心是2.6的,一切驅動都已完畢,檔案系統採用nfs載入,在宿主系統上位於/arm/root/root_nfs上,我是編譯好後,才弄板子的,但最好,在編譯之前,最好先熟悉熟悉開發板,我弄好好幾天才使開發板運行起來,因為2.6的kernel使用的uboot裡某些東西跟2.4 kernel使用的uboot不同。我以前根本沒有弄過,困擾了好幾天。
在宿主系統上,將/usr/gtkdfb目錄複寫到/arm/root/root_nfs/usr目錄下,開發板運行起來後,編譯好的東西都會在/usr/gktdfb目錄下。
1) Pangorc
mkdir /arm/root/root_nfs/usr/gtkdfb/etc/pango
建立檔案 /arm/root/root_nfs/usr/gtkdfb/etc/pango/pangorc檔案內容如下
# pangorc file for uninstalled operation.
# We set the path as ../modules, such that it works from any of
# top level build subdirs.
#
[Pango]
ModuleFiles = /usr/gtkdfb/etc/pango/pango.modules
ModulesPath = /usr/gtkdfb/lib/pango/1.6.0/modules
上面在宿主系統上運行
下面的命令在開發板上運行
/usr/gtkdfb/bin/pango-querymodules > /usr/gtkdfb/etc/pango/pango.modules
2) gfxdrivers
下面的命令本行在開發板上運行,只是消除一個警告
mkdir /usr/gtkdfb/lib/directfb-1.1-0/gfxdrivers
3) gdk-pixbuf.loaders
下面的命令本行在開發板上運行
mkdir /usr/gtkdfb/etc/gtk-2.0
/usr/gtkdfb/bin/gdk-pixbuf-query-loaders > /usr/gtkdfb/etc/gtk-2.0/gdk-pixbuf.loaders
4) gtk.immodules
下面的命令本行在開發板上運行
/usr/gtkdfb/bin/gtk-query-immodules-2.0 > /usr/gtkdfb/etc/gtk-2.0/gtk.immodules
5) fonts.conf
在/usr/gtkdfb/etc/fonts目錄下有fonts.conf這麼個檔案,在這個檔案配置了一些字型檔的資訊,在宿主系統中開啟檔案/arm/root/root_nfs/usr/gtkdfb/etc/fonts/fonts.conf,修改<!-- Font directory list -->這行以下的東西,設定正確的字型檔目錄。當然前提需要將字型檔複製到/arm/root/root_nfs的合適目錄下。比如ubuntu的設定如下
<!-- Font directory list -->
<dir>/usr/share/fonts</dir>
<dir>/usr/X11R6/lib/X11/fonts</dir>
<dir>~/.fonts</dir>
最簡單的方法就是將ubuntu的這些目錄裡的內容複寫到/arm/root/root_nfs相對目錄下,這樣,這個檔案都可以不修改。但最後你肯定不能這樣做,因為嵌入式是不需要這麼多字型檔的,我們只要需要的,不需要的統統砍掉,瞭解一下這個檔案也應該是必須的。
6) directfbrc
這個檔案我還沒用過,我曾經相弄它,因為當初碰到一個問題以為是他的問題,但不是它的問題,所以到現在為止,我還沒弄。論壇上VCVC0說,沒有這個檔案,程式載入很慢,有了,就快很多,這裡給個連結,我就不詳述
http://www.directfb.com.cn/viewthread.php?tid=373
下面是文章的內容。也現在也不臆想我的用法了
如何配置基於arm的directfbrc設定檔?
我在我的開發板裡跑了一下應用。如果/etc目錄下沒有directfbrc檔案的話,程式需要很久才能顯示出來。
我簡單設定了一下directfbrc內容如下:
system=fbdev
fbdev=/dev/fb/0
wm=default
mode=640x480
depth=32
pixelformat=RGB32
程式的啟動速度就快了很多,不知道是什麼原因。
還有問題就是direct的wm能否管理gtk的視窗。或者有沒有基於嵌入式開發的視窗管理器可以使用的。
6 最後的秘笈
現在你在板子上運行GTK源碼包裡的test,應該是沒有問題,如果有問題,就要回頭苦修了。最後的一個問題來了,usb滑鼠可以控制螢幕上的滑鼠指標,觸屏不反應,明明我的tslib測試程式運行一定問題也沒有,DFB編譯也正確失敗了tslib這個庫,怎麼回事呢? 這就是最後的秘笈,我只所以敢將本文檔稱為至尊秘笈,也就因為這個秘笈,我認為,解決這個問題需要相當的技術水平。
首先,要說明這個問題都是複雜的。先說DFB的初始化,DFB載入先讀directfbrc,讀取一些設定,然後載入輔助模組,模組的載入都是動態,採用dlopen方式載入的。tslib載入一些模組也是採用這種方式載入的。應用程式動態連結到DFB的庫,載入能載入的模組,同時載入了libdirectfb_tslib.so,這個模組動態連結到libts.so這個庫,動態載入libdirectfb_tslib.so同時做一些初始化tslib的工作,初始tslib又會動態載入tslib的一些模組,這四個模組pthres、variance、dejitter、linear會用到libts.so這個庫裡的一個函數tslib_parse_vars,由於libdirectfb_tslib.so是用dlopen載入的,載入tslib的上四個模組時,根本就不知道到何處去找函數tslib_parse_vars,而tslib的測試程式已經動態連結了libts.so,載入tslib的上速模組時能夠正確識別函數tslib_parse_vars。
原因知道了,解決問題就簡單了。連結應用程式時動態連結到庫libts.so就可以了,我修改gtk源碼tests目錄下的Makefile
LDFLAGS = -L/usr/gtkdfb/lib -lts -Wl,-rpath,/usr/gtkdfb/lib
重新編譯了這些測試程式,複製到開發板上,運行,一切都OK了
7 結語
回想起來,搭建一個嵌入式的DFB+GTK的GUI開發平台真的很困難,且不說如此多不同組織和個人編寫的包,就是每個人的環境也是千差萬別的,能夠給你提供協助的人幾乎沒有,碰到問題,你只能在浩瀚的網路裡找尋解決的方法。解決任何一個問題也許都要耗費巨大的精力。如果你的項目資金允許,還是請支援一下國產的優秀GUI軟體――MiniGUI,你碰到的問題,應該都很得到迅速,圓滿的解決,無疑會加快你的項目開發進度。當然,DFB+GTK也是很好的選擇,在你自己解決問題的時候,你會學到很多的東西,還會帶給你帶來巨大的成就感。
最後,要感謝這些開源軟體包的寫作者們,是他們無私的奉獻,才讓我們能夠有機會學習這些優秀的代碼。還要感謝哪些在網上共用了自己經驗的先驅們,是他們的點點星火,給了我靈感,為我指引瞭解決問題的方向。謹以本文獻給他們,再次感謝他們。同時,將本文獻給www.directfb.com.cn及壇主echo先生以及論壇的每一個現在的和將來的會員。我只不過在論壇上發表了兩篇很短小的陋文,echo先生竟邀請我當版主,使我倍感榮幸。
環境的搭建工作我基本完成了,項目的需要,我要做其他的事情了。如果你也在做類似的工作,碰到了一些問題,希望本文能給你協助。如果你在其他地方看到本文(本人希望有網站轉載本文),請訪問www.direcfb.com.cn,也許你能的得到更多的資訊。
免責聲明: 本人不保證本文檔完全正確,如果你看到有什麼不合適的地方,歡迎與本人交流。