跳到主要內容

[Qt][Embedded][PXA270]
Porting Qt 4.8.6 for Creator XScale PXA270

這篇文章介紹這學期我在嵌入式作業系統課程,使用Creator XScale PXA270板子的一些學習筆記與製作final project的一些過程,歡迎各位多多指教~

背景介紹

Creator XScale PXA270開發版是一塊由新華電腦(microtime)公司出品的模組化XScale/ARM/SoC/FPGA/DSP嵌入式行動通訊發展平台,在此課程與final project主要使用的是"Create XScale‐PXA270 子板"與"MTLCD‐0708048 LCD Module",在Create XScale‐PXA270子板上的為Intel(現在已出售給Marvell)的Xscale系列PXA270處理器,基於ARMv5TE架構指令集,在旁附有SDRAM Memory 64MB、Flash Memory 32MB、SD Card Connectors、RJ45 10/100 Base‐T Ethernet Interface、USB 1.1 Device/Host Port各一、AC97 Audio Codec(Line_in、Mic_in、Headphone)、ADC Interface*4、PWM Interface、CMOS Camera Interface、TFT-LCD Interface、GPIO Interface...等;在軟體功能部分,由新華科技提供了GNU GCC cross compiler toolchain(arm-unknown-linux-gnu-gcc 4.0.2)、Uboot 1.1.5、Linux Kernel 2.6.15.3與patch(提供支援子板上的Ethernet、USB Host、TFT‐LCD(Frame buffer、Touch Screen)、AC97‐Codec...等與母板LED、7‐Seg LED、Key Pad...等的device driver)、rootfs,相關的實驗環境設定可以參考User Guide
看到以上這麼多的軟硬體介面,別以為這板子有多強,其實這是2006ASUS P535手機使用的規格了,不禁讓人感嘆科技進步之快阿~
在此附上開發版本尊
Qt是自由且開放原始碼的跨平台C++應用程式開發框架。廣泛用於開發GUI程式,也可用於開發非GUI程式,比如控制台工具和伺服器。Qt使用於OPIE、Skype、VLC media player、Adobe Photoshop Elements、VirtualBox 與 Mathematica以及被Autodesk、歐洲太空總署、夢工廠、Google、HP、KDE、盧卡斯影業、西門子公司、富豪集團、華特迪士尼動畫製作公司、三星集團、飛利浦、Panasonic所使用。
*為什麼這篇選用Qt 4.8.6,而不使用最新的Qt 5.5?
原因很簡單,因為我在cross compile Qt 5.5時,一直遇到編譯error問題,且網路上大部分還是Qt 4的code且我也比較熟Qt 4的code,所以就使用Qt 4.8.6啦~

環境準備

以下開發環境在VirtualBox上執行Ubuntu 14.04LTS作業系統進行(ubuntu-14.04.2-desktop-amd64.iso),灌好系統後插入Guest Additions CD映像與安裝,使虛擬機畫面可以全螢幕並支援與Host OS交換檔案、剪貼簿等功能,設定vboxsf群組加入使用者權限、更新系統到最新、一些基本環境設定(安裝gcc, g++)、執行32bit GCC cross compiler toolchain的zlib等支援(lib32z1...等)指令如下:
sudo usermod -aG vboxsf $(whoami)
sudo apt-get update
sudo apt-get upgrade
sudo apt-get install build-essential g++ lib32z1 lib32ncurses5 lib32bz2-1.0
sudo apt-get install 
首先到Qt官網下載Qt 4.8.6 source code(qt-everywhere-opensource-src-4.8.6.tar.gz)
附上網址: http://download.qt.io/archive/qt/4.8/4.8.6/,下載完成後解壓縮:
wget http://download.qt.io/archive/qt/4.8/4.8.6/
tar zxvf qt-everywhere-opensource-src-4.8.6.tar.gz
由於我們會先在桌面開發完成Qt應用程式後再porting到板子上,所以首先我們先build出桌面版本的Qt,經測試發現Qt內部的Makefile可能沒寫好,因此我們必須把桌面版本的Qt source與porting版的分開來(或是使用git來還原),故桌面版這次先重命名為 qt-desktop-opensource-src-4.8.6,根據Qt for X11 Requirements安裝相關套件,然後開始build~(-j8是開八條thread歐,請自行斟酌CPU能力與memory大小)
mv qt-everywhere-opensource-src-4.8.6 qt-desktop-opensource-src-4.8.6
cd qt-desktop-opensource-src-4.8.6
sudo apt-get install libfontconfig1-dev libfreetype6-dev libx11-dev libxcursor-dev libxext-dev libxfixes-dev libxft-dev libxi-dev libxrandr-dev libxrender-dev
./configure -release -opensource -confirm-license -prefix build-ubuntu64
make -j8
make install
在完成漫長的編譯後,即可在build-ubuntu64下看到編譯完成的Qt framework,將Qt framework動態函式庫加到LD_LIBRARY_PATH,可執行example內的範例測試:
export LD_LIBRARY_PATH=$(pwd)/build-ubuntu64/lib:$LD_LIBRARY_PATH
./build-ubuntu64/examples/mainwindows/application/application
成功執行application的範例

開始Porting

在以上步驟我們完成了於Desktop上的Qt編譯,沒有任何修改code的行為就可在ubuntu上編譯成功,但是到了embedded上就不一樣了,另外在以上編譯桌面板的source下make distclean,仍會殘留大量Makefile、pri修改與config.tests...等檔案,因此必須再重tar開另一份source(或是使用git還原回去),故以下步驟開始:
tar zxvf qt-everywhere-opensource-src-4.8.6.tar.gz
cd qt-everywhere-opensource-src-4.8.6
接著要開始創建Embedded Linux Target組態,官方提供了詳細的文件說明如:

  1. Cross-Compiling Qt for Embedded Linux Applications
  2. Qt for Embedded Linux
  3. Installing Qt for Embedded Linux

基本上與參考一的步驟一樣
第一步,加入cross-compiler toolchain的執行檔位置到PATH(可以直接改在~/.bashrc再source比較方便)
export PATH=path/to/cross/compiler:$LD_LIBRARY_PATH
第二步,建立target的QMake規格檔案,以下是我的作法
export QT_ROOT=$(pwd)
mkdir mkspecs/qws/linux-arm-pxa270-g++
cd mkspecs/qws/linux-arm-pxa270-g++
touch qmake.conf
cp ../linux-arm-gnueabi-g++/qplatformdefs.h .
gedit qmake.conf
在qmake.conf輸入以下內容指定使用的toolchain並存檔,在這裡是使由新華提供的toolchain其prefix為arm-unknown-linux-gnu-,在flag部分針對armv5te架構、xscale系列來tune:
#
# qmake configuration for building with arm-none-linux-gnueabi-g++
#

include(../../common/linux.conf)
include(../../common/gcc-base-unix.conf)
include(../../common/g++-unix.conf)
include(../../common/qws.conf)

# modifications to g++.conf
QMAKE_CC                = arm-unknown-linux-gnu-gcc
QMAKE_CXX               = arm-unknown-linux-gnu-g++
QMAKE_LINK              = arm-unknown-linux-gnu-g++
QMAKE_LINK_SHLIB        = arm-unknown-linux-gnu-g++

# modifications to linux.conf
QMAKE_AR                = arm-unknown-linux-gnu-ar cqs
QMAKE_OBJCOPY           = arm-unknown-linux-gnu-objcopy
QMAKE_STRIP             = arm-unknown-linux-gnu-strip

QMAKE_CFLAGS           += -O3 -march=armv5te -mtune=xscale -Wa,-mcpu=xscale -Uarm -mapcs -mno-sched-prolog -mabi=apcs-gnu -mno-thumb-interwork -fno-omit-frame-pointer
QMAKE_CXXFLAGS         += $$QMAKE_CFLAGS

load(qt_config)
接著就可以開始編譯了,指定使用arm架構、platform使用剛剛定義的pxa270規格檔案並且關閉x window support:
cd $QT_ROOT
./configure -embedded arm -xplatform qws/linux-arm-pxa270-g++ -prefix build-pxa270 -release -no-opengl -opensource -verbose -no-glib -no-xrender -no-xrandr -no-xfixes -no-xcursor -no-xinerama -no-xsync -no-xvideo -no-xshape -little-endian -confirm-license -no-rpath
make -j8
make install
在以上的編譯過程你一定會遇到error而停下來,畢竟是cross compile有些是組合語言的關係、有些是define的問題,這邊列出我編譯時遇到的問題:
若遇到非以下問題請嘗試將錯誤訊息複製去google有許多大陸的論壇都會教你如何修改,修改後在繼續make、make install動作 。(ps: gedit跳到某行數的short-cut是ctrl+i)
問題1
錯誤訊息:
thread/qthread_unix.cpp:125: error: thread-local storage not supported for this target
解決方式: 開啟qthread_unix.cpp,在122行後undefine HAVE_TLS,使原本124行的#ifdef HAVE_TLS不成立 gedit src/corelib/thread/qthread_unix.cpp
加入內容:
#ifdef HAVE_TLS
#undef HAVE_TLS
#endif
問題2
錯誤訊息: {standard input}: Assembler messages:
{standard input}:311: Error: register or shift expression expected -- `orr r2,r1,lsl#16'
{standard input}:321: Error: register or shift expression expected -- `orr r3,r1,lsl#16'
{standard input}:329: Error: register or shift expression expected -- `orr r2,ip,lsl#16'
{standard input}:467: Error: register or shift expression expected -- `orr r2,r1,lsl#16'
{standard input}:475: Error: register or shift expression expected -- `orr r3,r0,lsl#16'
make[1]: *** [.obj/release-shared-emb-arm/ftbbox.o] Error 1
解決方式: 開啟ftconfig.h,修改第330行的內容
gedit src/3rdparty/freetype/include/freetype/config/ftconfig.h
修改內容:
(原本的為)  "orr %0, %2, lsl #16\n\t" /* %0 = %2 << 16 */
(修改後為)  "orr %0, %0, %2, lsl #16\n\t" /* %0 = %2 << 16 */
問題3
錯誤訊息: ../3rdparty/javascriptcore/JavaScriptCore/wtf/Threading.h: In function 'int QTWTF::atomicIncrement(volatile int*)':
../3rdparty/javascriptcore/JavaScriptCore/wtf/Threading.h:253: error: '__sync_add_and_fetch' was not declared in this scope
../3rdparty/javascriptcore/JavaScriptCore/wtf/Threading.h: In function 'int QTWTF::atomicDecrement(volatile int*)':
../3rdparty/javascriptcore/JavaScriptCore/wtf/Threading.h:254: error: '__sync_sub_and_fetch' was not declared in this scope
解決方式: 開啟Threading.h,將第251、253、254行變成註解
gedit src/3rdparty/javascriptcore/JavaScriptCore/wtf/Threading.h
修改後內容:
//#define WTF_USE_LOCKFREE_THREADSAFESHARED 1
//
//inline int atomicIncrement(int volatile* addend) { return __sync_add_and_fetch(addend, 1); }
//inline int atomicDecrement(int volatile* addend) { return __sync_sub_and_fetch(addend, 1); }
問題4
錯誤訊息: ./wtf/Atomics.h: In function 'int WTF::atomicIncrement(volatile int*)':
./wtf/Atomics.h:112: error: '__sync_add_and_fetch' was not declared in this scope
./wtf/Atomics.h: In function 'int WTF::atomicDecrement(volatile int*)':
./wtf/Atomics.h:113: error: '__sync_sub_and_fetch' was not declared in this scope
解決方式: 開啟Atomics.h,將第110、112、113行變成註解
gedit src/3rdparty/webkit/Source/JavaScriptCore/wtf/Atomics.h
修改後內容:
//#define WTF_USE_LOCKFREE_THREADSAFESHARED 1
//#define WTF_USE_LOCKFREE_THREADSAFEREFCOUNTED 1
//
//inline int atomicIncrement(int volatile* addend) { return __sync_add_and_fetch(addend, 1); }
//inline int atomicDecrement(int volatile* addend) { return __sync_sub_and_fetch(addend, 1); }
終於在完成以上編譯與修改動作後,建出了可以於PXA270執行的Qt framework
此時的Qt還無法支援觸控輸入,僅能顯示並且透過Linux的支援可以插上鍵盤滑鼠操作
(PS1:在Linux的kernel driver那邊必須開啟TFT LCD的support)
(PS2:在PXA270執行時,一樣要記得設定LD_LIBRARY_PATH,而在執行時若沒特別啟動過Qt server,必須在執行檔名稱後加上-qws的option,忘記時Qt也會提醒你^.<)

Linux kernel的設定

在Linux kernel部分,必須開啟LCD的支援,在PXA270上的詳細步驟如下:
make mrproper
make menuconfig
  1.在"Load an Alternate Configuration File"
  arch/arm/configs/creator_pxa270_defconfig
  2.在"Device Drivers"->"Character devices"選擇include
  Creator-pxa270 LCD、Creator-pxa270 Codec
  3.在"Device Drivers"->"Graphics support"選擇include"PXA LCD framebuffer support"後才會出現LCD type選項,選擇"MTLCD-0708048 7.0 inches"
make clean
make -j4

What's NEXT?

留言

  1. 您好,謝謝您的教學,請問將我將Qt framework動態函式庫加到LD_LIBRARY_PATH後,build-ubuntu64底下並沒有examples,examples和build-ubuntu64是屬於同一個資料夾,而examples/mainwindows/application/application application/目錄底下並沒有可執行的application,請問我是哪裡出錯了呢? 謝謝您,謝謝。

    回覆刪除
    回覆
    1. 嗨你好,你的configure是否有build example?

      刪除
    2. 您好,我的qt-desktop-oprnsource底下並沒有configure這個資料夾,只有/config.profiles,/config.tests 這兩個資料夾,和一個名叫configure的shell script,/build-ubuntu64底下也沒有configure。我是用VMware Workstation 12 player,和Ubuntu 64-bit,其他都是照您的步驟進行。

      刪除
    3. 非常謝謝您的幫忙,我也正在做交大的期末project。

      刪除
    4. 我上一個回覆的意思是你下./configure的時候,要確定是否有設定成要編譯example
      ./configure --help可以看有哪些option可以下

      刪除
    5. 作者已經移除這則留言。

      刪除
    6. 您好,請問 ./configure -release -opensource -confirm-license -prefix build-ubuntu64 是把qt-desktop底下有關/build-ubuntu64的file 都編譯產生makefile,您是指說 和build-ubuntu64同一層的examples並沒有被configure到嗎?怎麼會這樣呢,請問我該如何調整。非常謝謝您,謝謝。

      刪除
  2. 作者已經移除這則留言。

    回覆刪除
  3. 作者已經移除這則留言。

    回覆刪除

張貼留言

這個網誌中的熱門文章

Run Android VTS with Android R emulator through WSL

Background Android VTS The Android Vendor Test Suite (VTS) provides extensive new functionality for Android testing and promotes a test-driven development process. Android R emulator Run the latest Android R image from Google CI build artifacts WSL WSL is a collection of components that enables native Linux ELF64 binaries to run on Windows . It contains both user mode and kernel mode components. It is primarily comprised of: User mode session manager service that handles the Linux instance life cycle Pico provider drivers (lxss.sys, lxcore.sys) that emulate a Linux kernel by translating Linux syscalls Pico processes that host the unmodified user mode Linux (e.g. /bin/bash) It is the space between the user mode Linux binaries and the Windows kernel components where the magic happens. By placing unmodified Linux binaries in Pico processes we enable Linux system calls to be directed into the Windows kernel. The lxss.sys and lxcore.sys drivers translate the Linux s...

[Android][AOSP][ddmlib][Intelij IDEA][Gradle]搭建Android ddmlib編譯環境

Android ddmlib在AOSP的platform/tools/base的repo內 可以使用以下指令將整個repo的master branch抓回: git clone https://android.googlesource.com/platform/tools/base 取其中的annotations、common、ddmlib 建立Intelij IDEA專案 使用Intelij IDEA開一新的Java Project,GroupId、ArtifictedId、Version隨便,並使用graddle wrapper方式建立專案: GroupId 'com.android.tools.ddms' ArtifictedId = 'ddmlib' Version '1.0-SNAPSHOT' 刪除IDE建立的src資料夾,建立base資料夾,將annotations、common、ddmlib複製進來 參考Android Studio建立的專案,修改build.gradle為: // Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { repositories { mavenCentral() } } allprojects { repositories { mavenCentral() } } task clean(type: Delete) { delete rootProject.buildDir } 修改settings.gradle,加入annotations、common、ddmlib為include rootProject.name = 'ddmlib' include ':base:annotations' include ':base:common' include ':base:ddmlib' 修改annotations、common、ddmlib內的b...