历时一个五一假期,终于把这个移植给搞定了,流程如下。坑有很多,祝你好运....
我先慢慢把框架搭起来,尽量精简,让文章简单易懂,一点点填充...
参考文章:
[1] 移植QT5.6到嵌入式开发板
[2] JZ2440(V3)移植QT5.6
具体制作u-boot,参考下篇博客:【u-boot移植】编译u-boot
使用oflash工具烧写u-boot到Nor Flash,这个步骤和裸板开发的时候是一样的。
启动后u-boot的界面应该是:
具体制作kernel,参考下下篇博客:【内核移植】编译内核文件uImage
此处注意:
1. 网卡驱动支持。如果不修改网卡配置文件,将uImage烧到开发板后,是ping不通服务器的(具体如何使用nfs和tftp,请参考之前博客:Linux配置tftp和nfs),这样也就没法挂载文件了,这还开发个啥,难道每次重写文件系统吗,哈哈哈
2. LCD驱动移植
3. 触摸屏驱动移植
(2) 下载内核到开发板上SDRAM中(推荐)
nfs 0x30000000 192.168.0.3:/home/ztaotao/work/my_rootfs/uImage
如果想直接烧写内核,要确保内核大小 < 分区的大小,不然的话使用擦出命令或者烧写文件系统的时候,几乎肯定会破坏到kernel分区的内容,当然如果你计算准确,也是没有影响的,比如,我就这么干过....,诚不推荐。
那么,内核过大怎么办呢?答:【内核移植】内核裁剪
(3)从内存启动内核
① 抹掉kernel分区(测试成功后再烧写,节省时间)
nand erase.part kernel
或者
nand erase 0x60000 0x00260000 //这个分区地址使用mtdparts查看
② 从30000000启动内核(推荐)
bootm 0x30000000
(4)设置网卡eth0的ip,注意这里的ip和u-boot的没关系,kernel启动以后,u-boot已经挂了,所以理论上,这个ip可以和u-boot的ip一样,不过我测试,哈哈哈
ifconfig eth0 192.168.0.100 //ip网段要和服务器一样,不然的话ping不通
此处在记录一个坑:可能是由于使用的是最新的Dm9000的网卡,有一些bug:
准备设置网卡ip时候,报错:
ifconfig: 192.168.0.100: error fetching interface information: Device not found
/ # ifconfig
/ # ifconfig eth0 192.168.0.100
ifconfig: SIOCSIFADDR: No such device
/ # ifconfig
/ #
/ # ifconfig -a
lo Link encap:Local Loopback
LOOPBACK MTU:16436 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
可以看到,没有网卡
解决方法:
修改/etc/init.d/rcS
ifconfig eth0 up
mount -a
mkdir /dev/pts
mount -t devpts devpts /dev/pts
echo /sbin/mdev > /proc/sys/kernel/hotplug
mdev -s
mount -a
ifconfig eth0 192.168.0.100
exec /etc/rc.local
对于脚本文件,要设置可执行属性:chmod +x rcS
vi /etc/rc.local
#!/bin/sh
. /etc/profile
对于脚本文件,要设置可执行属性:chmod +x rc.local
感觉可能是移植网卡搞得不是特别好,另外如果高频率重启机器的话,网卡可能没法处于就绪状态,这个时候断电重启一下就可以啦。
此外,这两句话:ifconfig eth0 192.168.0.100和ifconfig eth0 up不能挨在一起,网卡反应不过来的。
具体制作busybox文件系统,参考下下篇博客:【文件系统制作】制作jffs文件系统
随后进行烧写:
启动:boot
注意以下坑:
(1)如果直接下载jffs2文件,可能写不进去,因为对于linux3.4版本的内核是不支持jffs2文件的烧写的【内核移植】添加yaffs文件系统到内核
(2)使用sudo命令安装busybox到根目录下目录可能发生以下错误,因为安装busybox要使用交叉编译工具,这个在环境变量中配置好了,只对特定用户有效,对更目录无效,所以,在安装时候,最好使用这样的命令:make CROSS_COMPILE=/usr/local/arm/gcc-4.4.3/bin/arm-linux- ARCH=arm install CONFIG_PREFIX=/usr/local/busybox
(1)制作Qt交叉编译工具
首先,qt源码下载: qt-everywhere-opensource-src-5.6.0.tar.gz
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
(1)
/* 针对于 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
/************************************************************************************/
/************************************************************************************/
(2)
//将以下部分
# 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 库,arm-none-linux-*确保已经添加到环境变量,不然的话要指明其路径
# 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 ../../../
写一个脚本问价:在当前目录写一个脚本文件build-qt.sh,内容如下,对这个脚本添加可执行属性:chmod +x build-qt.sh,随后执行./build-qt
./configure -prefix /usr/local/Qt5.6 \
-v\
-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
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/root/usr/local/
tar zxvf Qt5.6.tar.gz
rm Qt5.6.tar.gz
5、设置qt相关的环境变量
此部分可以参考qt官方问文档:http://doc.qt.io/qt-5/embedded-linux.html ,这我这仅仅是设置支持了触摸屏,你可以参考官方设置支持键盘,鼠标等等。 在文件系统 /etc/profile 里添加
//注意这里面的路径是你制作的文件系统的路径,对于文件系统来说,root文件里面就是arm板子的根文件系统
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
//size指定屏幕分辨率,mmsize指定屏幕物理尺寸,offset指定偏移
export QT_QPA_PLATFORM=linuxfb:fb=/dev/fb0:size=480x272:mmsize=480x272:offset=0x0:tty=/dev/tty1
export QT_QPA_FB_TSLIB=1
size=480x272:mmsize=480x272请根据自己的开发板进行修改,我手头的开发板是 3.5 寸 320*240 的 LCD,JZ2440 V3 用上面的参数即可。
(2)随后进行以下步骤:
Ubuntu安装qt方法参考之前的博客:Ubuntu安装QT,不过我这里安装的是Qt5.0,因为新的版本太大了...,注意卸载的时候也要将相应添加的环境变量和配置文件删除。
测试界面:
以下是坑,请注意:
(1)我们安装Qt5.6交叉编译工具,是为了将编译好的程序放到arm上使用,所以,
另外,qt不需要任何配置,不要瞎捣鼓(计算你把Qt5.6的qmake添加到Qt的tool下面,其实最后也会编译报错:出现path或no permitted属于正常,因为在Linux qt中无法运行arm qt中的程序;)
(2)在qt界面设计的时候,可能会遇到如下的错误:
In file included from main.cpp:1:
mainwindow.h:4:21: error: QtWidgets: No such file or directory
main.cpp:2:24: error: QApplication: No such file or directory
In file included from main.cpp:1:
mainwindow.h:11: error: expected class-name before '{' token
mainwindow.h:12: error: ISO C++ forbids declaration of 'Q_OBJECT' with no type
mainwindow.h:14: error: expected ';' before 'public'
main.cpp: In function 'int main(int, char**)':
main.cpp:6: error: 'QApplication' was not declared in this scope
main.cpp:6: error: expected ';' before 'a'
mainwindow.h:16: error: 'MainWindow::~MainWindow()' is private
main.cpp:7: error: within this context
main.cpp:8: error: 'class MainWindow' has no member named 'show'
main.cpp:10: error: 'a' was not declared in this scope
main.cpp: At global scope:
main.cpp:4: warning: unused parameter 'argc'
main.cpp:4: warning: unused parameter 'argv'
Makefile:379: recipe for target 'main.o' failed
make: *** [main.o] Error 1
解决方案:参考错误:QMainWindow: No such file or directory 解决方法(不要瞎修改编译好的交叉编译工具Qt5.6)
armbtn.pro文件:
mainwindow.h文件:
修改后保存,注意不要删除.pro文件,也不要使用命令:qmake -project(你才修改好,乱动它是干嘛呀)
之后,成功编译,绿色的armbtn就是我们的测试程序。cp到nfs的共享文件夹。
(1)挂载文件夹:
这里说一下,挂载不是下载,断电后,这个文件就没了,要想掉电后还可以有,显然要把文件送到arm开发板家里,方法有:
(2)测试:(armbtn是可执行文件名)
./armbtn
最后一个bug:Failed to open tty (No such file or directory),不过这个对我们的使用没有丝毫影响,说不定你碰不到呢....
在文件系统中查找关键字,最终发现在环境变量里面调用了这个设备
直接在/dev目录下面创建tty1的节点:
mknod tty1 c 4 1
source /etcprofile
随后测量,bug修复
关于如何使用QTE来调用驱动程序且带下篇博客细细道来.................