1. 程式人生 > >移植QT5.6到嵌入式開發板(史上最詳細的QT移植教程)

移植QT5.6到嵌入式開發板(史上最詳細的QT移植教程)

文件傳輸 嵌入式環境 ubun 導致 字庫 etc -a led fill

目前網上的大多數 QT 移植教程還都停留在 qt4.8 版本,或者還有更老的 Qtopia ,但是目前 Qt 已經發展到最新的 5.7 版本了,我個人也已經使用了很長一段時間的 qt5.6 for windows ,本文就來介紹一下QT在嵌入式環境的搭建。
移植以到 JZ2440 為例,使用韋老大提供的 ubuntu9.10 虛擬機作為移植環境。當然,其它虛擬機也是可以的,我同樣在 ubuntu14.04 移植成功,只不過需要額外裝一些庫,後面我會簡單提及。
此外,我嘗試使用 4.3.2 版本的交叉編譯工具編譯 Qt5.6 ,編譯過成功很多錯誤,編譯成功之後使用 qt 編譯應用程序時也存在問題,因此我是用的是友善提供的 4.4.3 版本的交叉編譯工具。建議新手使用與我相同的編譯環境。
因為我們更換了編譯工具,因此,我們有接下來的4個工作。
1、重新編譯內核
2、制作文件系統
3、移植tslib

4、移植qt

教程涉及的資料:
1、交叉編譯器
arm-linux-gcc-4.4.3.tar.gz .鏈接:http://pan.baidu.com/s/1nvJF8ud 密碼:oi57
2、針對於 JZ2440 的內核補丁以及源碼
linux-2.6.22.6.tar.bz2 .鏈接:http://pan.baidu.com/s/1gf0oZn1 密碼:jrp6
linux-2.6.22.6_jz2440.patch 鏈接:http://pan.baidu.com/s/1c1CWgTE 密碼:uwuu
4.3寸LCD_mach-smdk2440.c 鏈接:http://pan.baidu.com/s/1boZsKwf 密碼:1xml
3、busybox
busybox-1.22.1.tar.bz2 .鏈接:http://pan.baidu.com/s/1cee6CI .密碼:lv81
4、tslib .
tslib-1.4.tar.gz
5、qt5.6 源碼 鏈接:http://pan.baidu.com/s/1jINj3IQ 密碼:6kkc
qt-everywhere-opensource-src-5.6.0.tar.gz 鏈接:http://pan.baidu.com/s/1kVnV9oN 密碼:r7cm


一、更換交叉編譯器

首先,將下載好的文件全部放在 /work 目錄下
1、解壓交叉編譯器
sudo tar zxvf arm-linux-gcc-4.4.3.tar.gz -C / #展開在根目錄
ls /opt/FriendlyARM/toolschain/4.4.3/bin #檢查是否生成了編譯目錄
2、設置環境變量
sudo vi /etc/environment
將現在原有的交叉編譯器路徑替換為我們新解壓的交叉編譯器,舉例:

[cpp] view plain copy
  1. #PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/work/tools/gcc-3.4.5-glibc-2.3.6/bin"//註釋
  2. PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/opt/FriendlyARM/toolschain/4.4.3/bin" //增加

後期測試時我發現這裏是有問題的,由於我的安裝目錄都指定的是 usr 目錄,需要 root 權限,然而在 environment 中設置的環境變量導致使用 root 權限 make install 過程中出現了個別的 command not found ,於是我將環境變量放到了 /etc/profile 中,這個文件是對所有用戶生效的。至於environment 百度了一下是系統環境變量按說應該沒問題,但是的確出現了問題。索性還是大家還是直接搞到 profile 中吧。

3、重啟虛擬機

4、檢查是否更換成功

arm-linux-gcc -v

技術分享

如圖,更換完畢,我們的編譯器就變為 4.4.3 版本了。


二、重新編譯內核

如果你不是jz2440也沒關系,使用你曾經移植好的內核,重新編譯即可,註意內核需要開啟EABI的支持,如果你是jz2440,按照下面的步驟操作即可。

1、解壓
tar jxvf linux-2.6.22.6.tar.bz2
2、打補丁
cd linux-2.6.22.6
patch -p1 < ../linux-2.6.22.6_jz2440.patch
如果你是 4.3 寸的 JZ2440 ,替換 LCD 驅動,3.5寸跳過此步
mv ../4.3寸LCD_mach-smdk2440.c arch/arm/mach-s3c2440/mach-smdk2440.c
3、配置內核支持 EABI
make menuconfig
kernel features->
<*>use the arm eabi to .... //選中這一項
4、修改 makefile ,不改的話 4.4.3 編譯器編譯時會報錯
vi Makefile

由於友善在制作這款交叉編譯工具時指定了最低內核版本(2.6.32.2)的限制,所以我們如果不加修改直接編譯啟動內核時會出現 kernel too old 的錯誤信息,無法啟動。這裏使用一個投機取巧的辦法,強制對 2.6.22.6 內核的版本進行修改,更改內核版本號對內核編譯是有影響的,真正移植的時候還是建議選擇高版本內核。

Makefile 最開始的地方就是版本號:
VERSION = 2
PATCHLEVEL = 6
SUBLEVEL = 22
EXTRAVERSION = .6
中的 SUBLEVEL = 22 改為 SUBLEVEL = 32
//找到一下幾行 ,這裏是因為 4.4.3 的編譯器不支持 gdwarf2 這個選項
ifdef CONFIG_DEBUG_INFO
CFLAGS += -g
AFLAGS += -gdwarf2
endif
//註釋掉 AFLAGS += -gdwarf2
5、編譯
make uImage -j4
編譯完的uImage 在 /arch/arm/boot 目錄下


三、制作文件系統

1、解壓
tar jxvf busybox-1.22.1.tar.bz2
2、配置
make menuconfig
Busybox Settings ->
general configuration ->
[*] don‘t use /usr //選中它 否則會破壞虛擬機
build options->
cross comliler prefix = arm-linux- //選擇交叉編譯工具
installtion options->
busybox installation prefix = /work/my_rootfs //指定安裝路徑
3、編譯&安裝
mkdir -p /work/my_rootfs //安裝路徑
make
make install
cd /work/my_rootfs
ls //查看是否安裝成功
編譯安裝完畢之後,我們的文件系統就生成在 /work/my_roofs 目錄下了
4、創建 /etc/inittab
mkdir -p /work/my_rootfs/etc
vi /work/my_rootfs/etc/inittab
# /etc/inittab
# 啟動腳本/etc/init.d/rcS
::sysinit:/etc/init.d/rcS
# 啟動 shell
::askfirst:-/bin/sh
# 重啟關機前 卸載文件系統
::ctrlaltdel:/sbin/reboot
::shutdown:/bin/umount -a -r
5、創建 /etc/init.d/rcS
mkdir -p /work/my_rootfs/etc/init.d
vi /work/my_rootfs/etc/init.d/rcS
# 這是一個腳本文件,用/bin/sh解析
#!/bin/sh
# 掛載文件系統
mount -a
# 使用內存文件系統
mkdir /dev/pts
mount -t devpts devpts /dev/pts
echo /sbin/mdev > /proc/sys/kernel/hotplug
mdev -s
# 設置IP
#/sbin/ifconfig eth0 192.168.1.17 #nfs不需要
# 掛載 /etc/fstab 中的文件系統
mount -a
exec /etc/rc.local
6、創建rc.local
vi /work/my_rootfs/etc/rc.local
#!/bin/sh
. /etc/profile //註意.後邊有個空格!
7、創建/etc/fstab
vi /work/my_rootfs/etc/fstab
# device mount-point type options dump fsck order
proc /proc proc defaults 0 0
sysfs /sys sysfs defaults 0 0
tmpfs /tmp tmpfs defaults 0 0
tmpfs /dev tmpfs defaults 0 0
8、構建 /dev 目錄
mkdir -p /work/my_rootfs/dev
cd /work/my_rootfs/dev
sudo mknod console c 5 1
sudo mknod null c 1 3
9、創建其它目錄
mkdir proc mnt tmp sys root usr
10、拷貝Lib
cd /opt/FriendlyARM/toolschain/4.4.3/arm-none-linux-gnueabi/lib
cp *.so* /work/my_rootfs/lib -d
cd /opt/FriendlyARM/toolschain/4.4.3/lib
cp *.so* /work/my_rootfs/lib -d


四、移植 tslib

1、解壓&配置&編譯
如果不是使用的韋老大的虛擬機可能還需要安裝一下幾個包 autoconf automake libtool
#sudo apt-get install autoconf automake libtool
tar zxvf tslib-1.4.tar.gz
sudo mkdir -p /usr/local/tslib
cd tslib
./autogen.sh
./configure --host=arm-linux ac_cv_func_malloc_0_nonnull=yes CC=arm-none-linux-gnueabi-gcc CXX=arm-none-linux-gnueabi-g++ -prefix=/usr/local/tslib
make
sudo make install

如果編譯過程中遇到 undefined reference to ‘rpl_malloc‘,前面配置完成之後修改 config.h.in 文件,註釋掉文件最後的 #undef malloc ,重新 make 即可。
安裝完成之後,tslib 就安裝在虛擬機 /usr/local/tslib 目錄下
2、更改 tslib 配置文件
cd /usr/local/tslib/etc/
sudo vi ts.conf
去掉# module_raw input 前面的 “#” 和空格
3、將制作好的 tslib 移動到我們制作的文件系統
cd /usr/local
sudo tar zcvf tslib.tar.gz tslib
mkdir -p /work/my_rootfs/usr/local
cp tslib.tar.gz /work/my_rootfs/usr/local
tar zxvf tslib.tar.gz
rm tslib.tar.gz
4、添加 tslib 環境變量
vi /work/my_rootfs/etc/profile

#!/bin/sh
export T_ROOT=/usr/local/tslib
export LD_LIBRARY_PATH=/usr/local/tslib/lib:$LD_LIBRARY_PATH
export TSLIB_CONSOLEDEVICE=none
export TSLIB_FBDEVICE=/dev/fb0
export TSLIB_TSDEVICE=/dev/input/event0
export TSLIB_PLUGINDIR=$T_ROOT/lib/ts
export TSLIB_CONFFILE=$T_ROOT/etc/ts.conf
export POINTERCAL_FILE=/etc/pointercal
export TSLIB_CALIBFILE=/etc/pointercal
此時,tslib 就已經移植好了,你可以掛載 nfs 文件系統啟動,cd /usr/local/tslib/bin

./ts_test 來測試
按照教程制作應該沒有問題,我在使用高版本內核的時候遇到“selected device is not a touchscreen I understand”錯誤,百度了一下,是由於內核和編譯器的一個宏定義不一致導致的,vi include/Linux/input.h EV_VERSION 為 0x0100000 ,從新編譯內核特別是觸摸驅動。


五、移植 qt5.6

1、解壓
tar zxvf qt-everywhere-opensource-src-5.6.0.tar
2、修改編譯配置
cd /work/qt-everywhere-opensource-src-5.6.0/qtbase/mkspecs/linux-arm-gnueabi-g++
vi qmake.conf
針對於 2440 增加:
QT_QPA_DEFAULT_PLATFORM = linuxfb
QMAKE_CFLAGS += -msoft-float -D__GCC_FLOAT_NOT_NEEDED -march=armv4t -mtune=arm920t
QMAKE_CXXFLAGS += -msoft-float -D__GCC_FLOAT_NOT_NEEDED -march=armv4t -mtune=arm920t
march 指的 cpu 架構,針對 2440 來說是 armv4t
mtune 指的 cpu 名字,針對 2440 來說是 arm920t
如果你是 A8 的板子 ,可以參考下邊的配置
QT_QPA_DEFAULT_PLATFORM = linuxfb
QMAKE_CFLAGS += -msoft-float -D__GCC_FLOAT_NOT_NEEDED -march=armv7-a -mtune=cortex-a8
QMAKE_CXXFLAGS += -msoft-float -D__GCC_FLOAT_NOT_NEEDED -march=armv7-a -mtune=cortex-a8
如果你是 A9 的板子 ,可以參考下邊的配置
QT_QPA_DEFAULT_PLATFORM = linuxfb
QMAKE_CFLAGS += -msoft-float -D__GCC_FLOAT_NOT_NEEDED -march=armv7-a -mtune=cortex-a9
QMAKE_CXXFLAGS += -msoft-float -D__GCC_FLOAT_NOT_NEEDED -march=armv7-a -mtune=cortex-a9
將以下部分
# modifications to g++.conf
QMAKE_CC = arm-linux-gnueabi-gcc
QMAKE_CXX = arm-linux-gnueabi-g++
QMAKE_LINK = arm-linux-gnueabi-g++
QMAKE_LINK_SHLIB = arm-linux-gnueabi-g++

# modifications to linux.conf
QMAKE_AR = arm-linux-gnueabi-ar cqs
QMAKE_OBJCOPY = arm-linux-gnueabi-objcopy
QMAKE_NM = arm-linux-gnueabi-nm -P
QMAKE_STRIP = arm-linux-gnueabi-strip
修改為:-lts 是指在鏈接時鏈接 tslib 庫
# modifications to g++.conf
QMAKE_CC = arm-none-linux-gnueabi-gcc -lts
QMAKE_CXX = arm-none-linux-gnueabi-g++ -lts
QMAKE_LINK = arm-none-linux-gnueabi-g++ -lts
QMAKE_LINK_SHLIB = arm-none-linux-gnueabi-g++ -lts

# modifications to linux.conf
QMAKE_AR = arm-none-linux-gnueabi-ar cqs
QMAKE_OBJCOPY = arm-none-linux-gnueabi-objcopy
QMAKE_NM = arm-none-linux-gnueabi-nm -P
QMAKE_STRIP = arm-none-linux-gnueabi-strip
3、配置編譯
sudo mkdir -p /usr/local/Qt5.6
cd ../../../

./configure -prefix /usr/local/Qt5.6 \
-opensource \
-release \
-confirm-license \
-xplatform linux-arm-gnueabi-g++ \
-shared \
-qt-zlib \
-no-gif \
-qt-libjpeg \
-no-nis \
-no-opengl \
-no-cups \
-no-glib \
-no-dbus \
-no-rpath \
-no-sse2 -no-sse3 -no-ssse3 -no-sse4.1 -no-sse4.2 \
-no-avx \
-no-openssl \
-nomake tools \
-qreal float \
-qt-libpng \
-tslib \
-nomake examples \
-I /usr/local/tslib/include \
-L /usr/local/tslib/lib


make -j4
sudo make install

如果使用的不是韋老大的虛擬機編譯過程中可能報關於libxcb的錯誤,查看 qtbase/src/plugins/platforms/xcb 底下的 readme 安裝相應的庫就可以了。
4、將移植好的 qt 打包到開發板
cd /usr/local
sudo tar zcvf Qt5.6.tar.gz Qt5.6
cp Qt5.6.tar.gz /work/my_rootfs/usr/local/
tar zxvf Qt5.6.tar.gz
rm Qt5.6.tar.gz
rm -r doc include bin mkspecs qml translations
5、設置qt相關的環境變量
此部分可以參考qt官方問文檔:http://doc.qt.io/qt-5/embedded-linux.html ,這我這僅僅是設置支持了觸摸屏,你可以參考官方設置支持鍵盤,鼠標等等。

在文件系統 /etc/profile 裏添加
export QTEDIR=/usr/local/Qt5.6
export LD_LIBRARY_PATH=/usr/local/Qt5.6/lib:$LD_LIBRARY_PATH
export QT_QPA_GENERIC_PLUGINS=tslib
export QT_QPA_FONTDIR=$QTEDIR/lib/fonts
export QT_QPA_PLATFORM_PLUGIN_PATH=$QTEDIR/plugins
export QT_QPA_PLATFORM=linuxfb:fb=/dev/fb0:size=480x272:mmSize=480x272:offset=0x0:tty=/dev/tty1

export QT_QPA_FB_TSLIB=1

紅色部分請根據自己的開發板進行修改,我手頭的開發板是 3.5 寸 320*240 的 LCD,JZ2440 V3 用上面的參數即可。

此時,qt 已經移植完畢,你可以打包放入你的 nfs 目錄啟動進行測試了,至於制作 yaffs2 jffs2 等文件系統請參考:http://blog.csdn.net/lizuobin2/article/details/52589215 ,qt庫比較大,燒錄的時候可能比較困難,可以先將QT去除,打包成文件系統大約之後20M不到,燒錄到開發板之後,啟動內核,通過nfs tftp等工具,再將打包好的Qt傳到板子上展開即可。

六、測試Qt應用程序

我個人習慣先用 windows 版本的 qt 寫好程序,調試沒問題之後直接拿到虛擬機上編譯,windows 版本的 qt 安裝非常簡單,就跟安裝個QQ一樣毫不費力,這裏就不再贅述了。

將windows下編輯好的源碼拷貝到虛擬機上,切換到源碼目錄

/usr/local/Qt5.6/bin/qmake

make

即可生成可執行文件,拿到開發板測試即可。

嫌費事的話,將 qmake 添加到環境變量裏。

在測試過程中我發現程序跑起來沒問題,但是有以下兩條錯誤信息:

QIconvCodec::convertFromUnicode: using Latin-1 for conversion, iconv_open failed
QIconvCodec::convertToUnicode: using Latin-1 for conversion, iconv_open failed

大概是缺少 libiconv

下載 鏈接:http://pan.baidu.com/s/1c22xb4O 密碼:pbld

mkdir -p /usr/local/libiconv

./configure --host=arm-none-linux-gnueabi --prefix=/usr/local/libiconv CC=arm-none-linux-gnueabi-gcc LDFLAGS="-L/opt/FriendlyARM/toolschain/4.4.3/arm-none-linux-gnueabi/sys-root/lib" --enable-static

make

sudo make install

把安裝目錄/lib 下的 preloadable_libiconv.so 文件系統的 /lib 下, 在 /etc/profile 中添加
export LD_PRELOAD=/lib/preloadable_libiconv.so

7、使Qt支持中文

在測試過程中很悲劇的發現移植好的qt不支持中文,強大度娘給了我答案。

下載字庫 鏈接:http://pan.baidu.com/s/1bp9QFQv 密碼:2u81

DroidSansFallback.ttf 放到文件系統 /usr/local/Qt5.6/lib/fonts 目錄下,雖然Qt自帶了很多字庫了,但是都沒有中文的。

然後在使用qt creator 開發qt應用程序時,在項目中添加

QT += gui

包含頭文件 #include <QFontDatabase>

代碼中設置使用的字體。

    int id = QFontDatabase::addApplicationFont("/usr/local/Qt5.6/lib/fonts/DroidSansFallback.ttf");
    QString msyh = QFontDatabase::applicationFontFamilies (id).at(0);
    QFont font(msyh,10);
    font.setPointSize(20);
    this->setFont(font);
技術分享 8、制作好的文件系統&內核 8.1 簡單的qt例子,代碼中Ui尺寸寫死為 320*240 ,如果不適合你的板子請修改。 鏈接:http://pan.baidu.com/s/1qXV4C1Y 密碼:908q 8.2 jz2440 內核(包含3.5和4.3) 鏈接:http://pan.baidu.com/s/1qYMrxmc 密碼:qsk0 8.3 文件系統 鏈接:http://pan.baidu.com/s/1skLtj3J 密碼:lbo2 改文件系統沒有打包成鏡像,請使用nfs啟動,解壓之後在 dev 目錄創建 console null 設備節點。 此外,/etc/profile 環境變量中的參數請修改成符合自己開發板的參數,默認為3.5寸。 解壓縮之後80多M,制作成 yaffs 恐怕會過 100 M,qt的庫文件沒有進行剪裁,需要制作鏡像的同學可以進行剪裁(查看你的app依賴於哪些庫,其余的都可以去掉)。 8.4 編譯好的Qt 鏈接:http://pan.baidu.com/s/1pLCznr9 密碼:l6pz

9、最新的uboot、內核、文件系統 文章寫了很久了,感謝有眾多朋友的信任,參考本文進行了一系列的嘗試,在此過程中也發現了文章中的不足,以及網盤中文件系統中的一些不足,恰巧最近有機會,重新做了一份內核,文件系統,以及配套的 uboot,並將它們放在了github上持續更新。如有需要,請下載: 註意:編譯器版本:4.4.3 rootfs: https://github.com/lizuobin/rootfs_jz2440.git 註意:git 下來之後 /dev目錄沒有 console 和 null 節點,請參考前面創建這兩個設備節點 這個文件系統相對完善,開機會自動校準(第一次),然後運行一個簡單的Qt桌面程序,暫時沒有放其它應用程序。文件系統中已經帶有ftpserver工具,大家可以使用filezila進行文件傳輸,加密方式選擇(僅ftp...不安全),端口21,用戶root,沒有密碼。文件系統龐大,還是建議先將qt等一些東西拷貝出來再傳進去。 內核:https://github.com/lizuobin/linux-3.4.2-jz2440.git 記得:cp config_ok .config uboot:https://github.com/lizuobin/uboot-2012.04.01-jz2440.git

如果你想讓你的開發板支持 ssh 請參考:

http://blog.csdn.net/lizuobin2/article/details/52664339

如果你想讓你的開發板支持串口(rz)傳輸文件請參考:

http://blog.csdn.net/lizuobin2/article/details/52601617

如果你想讓你的開發板想虛擬機一樣在命令行顯示用戶名請參考:

http://blog.csdn.net/lizuobin2/article/details/52664657


嵌入式QT相關的設計開發需求,請聯系我QQ:271526143

移植QT5.6到嵌入式開發板(史上最詳細的QT移植教程)