这几天拿到米尔-全志T113-S3开发板,想研究了一下如何在全志t113上跑通qt程序,现将具体方法列出来。
先来介绍一下开发板,T113-S3入门级、低成本、极致双核A7国产处理器
基于T113-S3处理器,双核A7@1.2GHz,适用低成本网关产品和商业显示产品;丰富多媒体接口MIPI-DSI/RGB/LVDS/Parallel CSI,支持1080P@60FPS显示;支持千兆以太网接口、2个CAN接口、2个USB2.0接口、6个UART功能接口;内置128MB DDR3,支持256MB Nand Flash和4G eMMC存储;核心板采用邮票孔方式连接,尺寸为37mmx39mm,140PIN。
应用:电力、商业显示、智能家居、工业控制、医疗器械等场景。
SDK源码(以下为官方教程):
默认源码都存放在github仓库内,请使用如下命令获取
book@100ask:~$ git clone https://github.com/DongshanPI/buildroot-100ask_t113-pro
book@100ask:~$ cd buildroot-100ask_t113-pro/
book@100ask:~/buildroot-100ask_t113-pro$ git submodule update --init --recursive
book@100ask:~/buildroot-100ask_t113-pro$ git submodule update --recursive --remote
book@100ask:~/buildroot-100ask_t113-pro$ cd buildroot/
book@100ask:~/buildroot-100ask_t113-pro/buildroot$ git submodule update --init --recursive
对于国内无法访问github的同学,可以使用国内备用gitee站点, 如下命令。
book@100ask:~$ git clone https://gitee.com/weidongshan/buildroot-100ask_t113-pro
book@100ask:~$ cd buildroot-100ask_t113-pro/
book@100ask:~/buildroot-100ask_t113-pro$ git submodule update --init --recursive
book@100ask:~/buildroot-100ask_t113-pro$ git submodule update --recursive --remote
book@100ask:~/buildroot-100ask_t113-pro$ cd buildroot/
book@100ask:~/buildroot-100ask_t113-pro/buildroot$ git submodule update --init --recursive
这里提供两个该下载源码的命令
这个SDK的buildroot上也可以配置搭建Qt的根文件系统,但是我没用到。 参考网上的开发文档,大部分都是需要安装交叉编译工具,然后用虚拟机上安装好的qt软件去指定。但是我觉得直接把源码编译出来,然后得到编译得到qt的交叉编译工具qmake会更加方便,毕竟我们大部分人都不习惯在Linux虚拟机上去编写qt程序。利用qmake,我们可以把在window上编写好的qt程序传到虚拟机,然后在虚拟机的xxx.pro所在工程下执行qmake,就可以自动生成makefile,然后执行make就可以生成可执行文件了。
可以看到,在得到qmake工具后,我在qt代码的文件目录下执行一次qmake,就可以得到makefile。在执行make,就会得到可执行文件。这个可执行文件会基于你所指定的交叉编译链而在相对应的开发板上运行。
在得到qmake之前,我们还需要去加载一个触摸屏的相关库。照着下面的教程操作就好了!
先要得到tslib的源码,可以到
https://github.com/kergoth/tslib
下载完成后放到ubutun的相关目录下,解压,进入目录,编译,安装。
tar xf tslib-1.21.tar.bz2
cd tslib-1.21
sudo apt-get update
sudo apt-get install autoconf automake libtool
./configure --host=arm-linux-gnueabihf ac_cv_func_malloc_0_nonnull=yes --cache-file=armlinux.cache -prefix=/home/alientek/tslib-1.21/arm-tslib
注意 --host后面要接上你自己板子的交叉编译链,-prefix是指定生成目录的,要把家目录改成和自己的一致。
正常操作后,就可以直接执行:
make
make install
生成后我们先不管它,记住你的生成目录,后面还会用到。
如何得到qmake?
我们需要先得到qt的源码,在qt源码目录下做一些相关配置,例如指定qt平台,指定qt编译所需要的交叉编译链,指定编译生成目录等等。完成相关配置后进行编译,最终能够在相关目录下得到qmake。
先做第一步,去官网上下载qt源码。
大家可以自行去官网目录上找,为了方便,我这里提供两个版本的qt源码下载指令。按需直接下载就可以了!
Qt4.84源码下载:(注:两条指令分别对应不同的ubuntu版本)
wget https://download.qt.io/archive/qt/4.8/4.8.4/qt-everywhere-opensource-src-4.8.4.tar.gz // >=ubuntu1404
wget http://download.qt.io/archive/qt/4.8/4.8.4/qt-everywhere-opensource-src-4.8.4.tar.gz // ubuntu12.04
Qt5.12.9源码下载:
wget https://download.qt.io/archive/qt/5.12/5.12.9/single/qt-everywhere-src-5.12.9.tar.xz
由于全志t113的这个SDK的编译器在编译qt5.12.9源码的时候会提示编译链被破坏,不能正常编译。所以这里以qt4为例。如果想在t113上跑qt5可以去研究一下其它的SDK,但是本文介绍的SDK似乎不能跑Qt5?有大佬成功跑通可以评论区留言指导一下。
下载完源码后,解压,进入目录。
tar xf qt-everywhere-src-5.12.9.tar.xz
cd qt-everywhere-src-5.12.9/
我们需要先修改Qt相关平台下qmake.conf,大部分情况都是指定linux-arm-gnueabi-g++去修改的。
vi qtbase/mkspecs/linux-arm-gnueabi-g++/qmake.conf
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 = /home/book/wode/buildroot-100ask_t113-pro/buildroot/output/host/opt/ext-toolchain/bin/arm-linux-gnueabi-gcc -lts
QMAKE_CXX = /home/book/wode/buildroot-100ask_t113-pro/buildroot/output/host/opt/ext-toolchain/bin/arm-linux-gnueabi-g++ -lts
QMAKE_LINK = /home/book/wode/buildroot-100ask_t113-pro/buildroot/output/host/opt/ext-toolchain/bin/arm-linux-gnueabi-g++ -lts
QMAKE_LINK_SHLIB = /home/book/wode/buildroot-100ask_t113-pro/buildroot/output/host/opt/ext-toolchain/bin/arm-linux-gnueabi-g++ -lts
QMAKE_CXXFLAGS += -std=gnu++98 -march=armv7-a
# modifications to linux.conf
QMAKE_AR = /home/book/wode/buildroot-100ask_t113-pro/buildroot/output/host/opt/ext-toolchain/bin/arm-linux-gnueabi-ar cqs
QMAKE_OBJCOPY = /home/book/wode/buildroot-100ask_t113-pro/buildroot/output/host/opt/ext-toolchain/bin/arm-linux-gnueabi-objcopy
QMAKE_STRIP = /home/book/wode/buildroot-100ask_t113-pro/buildroot/output/host/opt/ext-toolchain/bin/arm-linux-gnueabi-strip
load(qt_config)
这里指定交叉编译链的时候我用的是绝对路径,防止报错。各位在编写时要修改成自己的路径。
如果在终端下打arm-linux-gnueabi-gcc -v能够正确获取编译链的相关版本信息,你也可以不指定绝对路径。
接着我们要在当前qt源码目录下写一个脚本文件:
./configure -prefix /home/alientek/qt-everywhere-opensource-src-4.8.4/arm-qt
-opensource
-confirm-license
-release -shared
-embedded arm
-xplatform qws/linux-arm-gnueabi-g++
-fast
-optimized-qmake
-no-pch
-qt-libjpeg
-qt-zlib
-qt-libpng
-qt-freetype
-little-endian
-host-little-endian
-no-qt3support
-no-libtiff
-no-libmng
-no-opengl
-no-mmx
-no-sse
-no-sse2
-no-3dnow
-no-openssl
-no-webkit
-no-qvfb
-no-phonon
-no-nis
-no-cups
-no-glib
-qt-mouse-tslib
-nomake tools
-nomake docs
-qt-sql-sqlite
-plugin-sql-sqlite
-I /home/alientek/tslib-1.21/arm-tslib/include
-L /home/alientek/tslib-1.21/arm-tslib/lib
这没什么好说的,需要注意的还是路径,注意改成自己qt源码的路径和tslib的路径就好了!
当然,第一个目录指定的是qt源码目录下的arm-qt目录,这个目录是你编译文件生成最终结果的目录,你可以尝试改变它。但是需要记住,因为最终会在这里生成qmake编译器。
接着运行脚本文件,运行后在末尾出现Just run ‘make’信息代表你可以开始编译qt源码了!
我的编译过程并不是一帆风顺。首先如果用的是官方SDK的交叉编译链去编译qt5的源码时,在执行脚本文件的时候会出现报错。报错内容是无法生成最小文件系统,你的交叉编译链可能已损坏。
这种情况下如果你的交叉编译工具的路径是指定正确的话,很大概率是因为你的交叉编译工具版本跟qt源码版本对不上导致的。但是我们没有办法改变官方的交叉编译工具,所以只能去换更低的qt版本了。
换好后,我发现交叉编译链可以成功指定,脚本文件无错误,但是编译的时候会出现一些报错。
这个原因是因为官方编译器对语法的一些要求会比较严格。我是跟着报错提示去修改了一些qt源码(例如把一些报错的数据类型改好),然后在qmake.conf那个配置文件上添加如下一行:
QMAKE_CXXFLAGS += -std=gnu++98 -march=armv7-a
稍作修改就能编译成功了!
编译好后,我们就能在响应目录下得到qmake(qt源码目录/arm-qt/bin),可以按上面操作生成可执行文件了!
但是仅仅只有可执行文件还不够,还需要在开发板上搭载qt环境。也就是需要在开发板上搭载qt文件系统,以及tsb触摸屏文件系统。
这两个东西,一个是刚刚生成的arm-qt,一个是之前生成好的arm-tslib,由于arm-qt比较大。不好通过tftp协议传输,所以我是把他们两个压缩放到u盘,通过u盘挂载到开发板上,解压生成的。
我们解压到开发板的usr/lib目录下。接着需要加载在/etc/profile上添加一些环境变量。
export TSLIB_ROOT=/usr/lib/arm-tslib
export TSLIB_CONSOLEDEVICE=none
export TSLIB_FBDEVICE=/dev/fb0
export TSLIB_TSDEVICE=/dev/input/event1
export TSLIB_CONFFILE=$TSLIB_ROOT/etc/ts.conf
export TSLIB_PLUGINDIR=$TSLIB_ROOT/lib/ts
export TSLIB_CALIBFILE=/etc/pointercal
QT_DIR=/usr/lib/arm-qt
export QT_QWS_FONTDIR=$QT_DIR/lib/fonts
export QWS_MOUSE_PROTO="tslib:/dev/input/event1 mouseman:/dev/input/mice"
export QT_QWS_DISPLAY="linuxFB:/dev/fb0"
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$QT_DIR/lib
然后重新加载一下环境变量:
source /etc/file
之后如果顺利,你就能把你ubutun上的qt程序传到开发板进行跑通了。
但是第一次跑Qt的时候,出现了爆栈的情况,因为我是用SD卡搭载Linux内核后启动的。
因为爆栈是内存不够的原因,所以还需要增加一下交换分区,教程如下:
linux中增加swap分区文件的步骤方法_linux 增加swap_
但是奇怪的是,第一次跑的时候爆栈了,后面按着上面扩容+设置交换分区操作下来,没有再次配置交换分区也能跑qt程序。
最后发现qt程序成功跑通,但是屏幕没有任何反应。
在相关函数上调用printf()也没有信息输出。程序像是阻塞卡死了一样。
原因是qt程序可能改变了printf指定的标准窗口,在创建qt类MainWindow的时候,printf便不会向标准控制台输出信息了,所以是看不到的。如果想看到调试信息可以用c++的cout函数,这样就肯定能看到输出信息了。
在这里卡了一晚上,发现是屏幕设备指定的问题,官方文档是这样指定屏幕的:
export QT_QWS_DISPLAY="linuxFB:/dev/fb0"
但是搜索网上的教程后发现另外一种指定
QWS_DISPLAY="LinuxFb:mmWidth100:mmHeight130:0" QWS_DISPLAY=EP93xx:/dev/fb0
将这个环境变量修改后,便能成功在屏幕上显示qt程序了!
更多回帖