100ASK-IMX6ULL开发板_QT移植全过程
环境及开发包介绍:
主机:ubuntu18.04(百问网提供)
交叉编译器:gcc-linaro-6.2.1-2016.11-x86_64_arm-linux-gnueabihf(百问网提供的bsp包)
QT5.6.0:qt-everywhere-opensource-src-5.6.0(链接:https://pan.baidu.com/s/1hiDQEDYWCq8FQYirw9yedg 密码:gvd7)
tslib:tslib-1.6(git clone https://github.com/kergoth/tslib.git)
Busybox:Busybox_1.30.0(百问网提供的bsp包)
Linux:Linux-4.9.88(百问网提供的bsp包)
注意:本文章的所有命令涉及到的 路径 需根据自身实际所创建的改变
一. Ubuntu安装QT软件
详细QT软件安装编译环境配置可参考链接:
使用QT执行编译时,应选择QT软件Tools/Options选项新增QT编译器选项,导入对应版本qmake(qt-everywhere-opensource-src-5.6.0配置编译安装目录的bin目录中),配置ARM板QT编译器,编译时选中新生成的配置选项
注意:选用新增的QT编译器选项生成的可执行文件(文件位于工程目录下build-xxx-xxx_toolchain-Debug文件中)不能在QT软件中Debug,需移植ARM进行功能测试。可用file命令查看文件运行环境:
二. 使用busybox构建根文件系统
参考链接:
- 解压busybox-1.30.0.tar.bz2:
tar -vxjf busybox-1.30.0.tar.bz2
- 修改Makefile(如果已设置全局交叉编译环境可忽略以下两条),添加编译器,打开busybox的根目录中的Makefile,将164行修改为:
CROSS_COMPILE ?= /home/book/share/100ask_imx6ull-sdk/ToolChain/gcc-linaro-6.2.1-2016.11-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf-
将路径修改为自己的交叉编译工具的绝对路径,将190行修改为:
ARCH ?= arm
- 配置busybox,busybox有三种配置选项:
- defconfig,默认配置
- allyesconfig,全选配置,使能busybox中的所有功能
- allnoconfig,最小配置
使用默认配置,执行:
make defconfig
然后打开图形配置界面,执行:
make menuconfig
分别配置下面的路径:
Location:
-> Settings
-> Build static binary (no shared libs) //取消选中,动态编译,不然编译出来的根文件系统很大
Location:
-> Settings
-> vi-style line editing commands //选中
Location:
-> Linux Module Utilities
-> Simplified modutils //取消选中
Location:
-> Linux System Utilities
-> mdev (16 kb) //确保下面的全部选中,默认都是选中的
- 配置完busybox就可以编译了,执行:
make install CONFIG_PREFIX=/home/book/nfs_rootfs/blogrootfs
CONFIG_PREFIX指定输出路径,指向nfs服务器的路径即可。编译完成后可以查看rootfs路径下的文件:
- 向根文件系统添加lib库
在rootfs下创建lib文件夹,在usr下创建lib文件夹。
- 进入交叉编译器存放的目录,将arm-linuxgnueabihf/libc/lib下的so和***.a拷贝到rootfs/lib下:
cp *so* *.a ~/nfs_rootfs/blogrootfs/lib/ -d
后面的“-d”表示拷贝符号链接。在rootfs中lib执行ls ld-linux-armhf.so.3 -l,可以看到ld-linux-armhf.so.3是一个软链接,所以需要重新复制一下。先删除rootfs/lib下的ld-linux-armhf.so.3,然后进入arm-linuxgnueabihf/libc/lib执行:
cp ld-linux-armhf.so.3 ~/nfs_rootfs/blogrootfs/lib/
再次查看rootfs/lib下的ld-linux-armhf.so.3,已经不是软链接了。
- 进入交叉编译器存放的目录,将arm-linuxgnueabihf/lib下的so和***.a拷贝到rootfs/lib下:
cp *so* *.a ~/nfs_rootfs/blogrootfs/lib/ -d
- 进入交叉编译器存放的目录,将arm-linuxgnueabihf/libc/usr/lib下的so和***.a拷贝到rootfs/usr/lib下:
cp *so* *.a ~/nfs_rootfs/blogrootfs/usr/lib/ -d
可能会有警告,不用管。
- 创建其它文件夹
在rootfs根目录下创建文件夹:dev、 proc、 mnt、 sys、 tmp、root,创建完后如下图示: - 测试根文件系统
测试根文件系统一般都使用NFS,在内核启动时指定使用的nfs服务器以及路径,设置好后保存环境变量,然后使用tftp加载内核和设备树并启动: - 配置TFTP环境
3.1. Ubuntu 安装 TFTP 服务
注意:使用 VMware NAT 网络或 Docker 时,不需要在 Ubuntu 中安装 TFTP 服务,而是在 Windows 运行
tftpd64 程序。
在 Ubuntu 中执行以下命令安装 TFTP 服务:
book@100ask:~$ sudo apt-get install tftp-hpa tftpd-hpa
然后,创建 TFTP 服务器工作目录,并打开 TFTP 服务配置文件,如下:
book@100ask:~$ mkdir -p /home/book/tftpboot
book@100ask:~$ sudo chmod 777 /home/book/tftpboot
book@100ask:~$ sudo vim /etc/default/tftpd-hpa
在配置文件/etc/default/tftpd-hpa 中,添加以下字段:
TFTP_DIRECTORY="/home/book/tftpboot"
TFTP_OPTIONS="-l -c -s"
最后,重启 TFTP 服务:
book@100ask:~$ sudo service tftpd-hpa restart
查看 tftp 服务是否在运行,运行如下命令,即可查看是否在后台运行。
book@100ask:~$ ps –aux | grep “tftp”
3.2. 准备工作
使用NFS根文件系统时,涉及3个文件:zImage 、 设备树(比如100ask_imx6ull-14x14.dtb)、
rootfs.tar.bz2(解压到Ubuntu某个目录,比如/home/book/nfs_rootfs)。 这里我们使用之前所构建根文件的对应目录
在U-Boot中通过tftpboot命令从Ubuntu/Windows中下载内核文件zImagen、100ask_imx6ull-14x14.dtb,
设置Uboot启动参数使用Ubuntu的某个目录(比如/home/book/nfs_rootfs)作为根文件系统。
1) 拷贝内核和设备树文件到 tftp 目录:
如果使用 VMware 桥接网络,将出厂镜像或者自行编译的 zImage 和设备树文件 100ask_imx6ull-
14x14.dtb,拷贝到 Ubuntu 的 /home/book/tftpboot 目录。
2) 把制作好的最小根文件系统压缩包拷贝到 NFS 目录:
3) 确认客户机与服务端互通:
先在 u-boot 中设置开发板 IP 为 192.168.1.112,然后在 u-boot 中使用 ping 命令测试开发板与 Ubuntu
系统是否连通(出现“alive”就表示联通):命令如下:
=> setenv ipaddr 192.168.1.112
=> ping 192.168.1.224
3.3. 配置选项,网络启动内核
先在 Ubuntu 的 TFTP 目录中放入 zImage 和设备树文件,再在/home/book/nfs_rootfs 目录下拷贝配置好的根文件系统。
然后在 U-Boot 控制台执行以下命令启动单板,假设 Ubuntu IP 是 192.168.1.224:
=> setenv serverip 192.168.***.*** //设置服务器的 IP 地址,这里指的是 Ubuntu 主机 IP
=> setenv ipaddr 192.168.***.*** //设置开发板的 IP 地址。
=> setenv nfsroot /home/book/nfs_rootfs/*** //设置文件系统所在目录。
=> run netboot //设置完成后,运行网络启动系统命令
3.4. 启动流程
U-boot通过tftp从服务端tftp指定目录下下载到内核设备树加载入内存,从而启动内核,最终挂载根文件系统
启动完成后如下图:
可以执行基本的命令了,但是提示没有/etc/init.d/rcS文件,所以需要完善一下文件系统。
3. 完善根文件系统
3.1 创建/etc/init.d/rcS文件
linux启动后需要运行一些服务,而 /etc/init.d/rcS文件就是规定启动哪些服务,创建该文件并添加如下内容:
#!/bin/sh
PATH=/sbin:/bin:/usr/sbin:/usr/bin:$PATH
#往PATH里面新增一个~/bin的路径,如果不加:$PATH的话,就表示直接把PATH赋值为~/bin,这样你其他的老路径就丢失了。
LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/lib:/usr/lib
export PATH LD_LIBRARY_PATH
mount -a
mkdir /dev/pts
mount -t devpts devpts /dev/pts
echo /sbin/mdev > /proc/sys/kernel/hotplug #通过这两行,linux内核就可以在/dev目录下自动创建设备节点
mdev -s
mount -a
exec /etc/rc.local
将rcS添加可执行权限chmod 777 rcS。
创建/etc/rc.local,创建该文件并添加如下内容:
\#!/bin/sh
. /etc/profile #注意.后边有个空格!
创建/etc/profile,暂且不添加内容.
3.2 创建/etc/fstab文件
fstab 在 Linux 开机以后自动配置哪些需要自动挂载的分区,创建该文件并添加如下内容:
#<file system> <mount point> <type> <options> <dump> <pass>
proc /proc proc defaults 0 0
tmpfs /tmp tmpfs defaults 0 0
tmpfs /dev tmpfs defaults 0 0
sysfs /sys sysfs defaults 0 0
3.3 创建/etc/inittab文件
init 程序会读取/etc/inittab这个文件, inittab 由若干条指令组成,创建该文件并添加如下内容:
::sysinit:/etc/init.d/rcS
console::askfirst:-/bin/sh
::restart:/sbin/init
::ctrlaltdel:/sbin/reboot
::shutdown:/sbin/umount -a -r
::shutdown:/sbin/swapoff -a
3.4 创建/etc/resolv.conf文件
/etc/resolv.conf文件用于配置域名服务器,没有域名服务器就不能将网址转换成ip地址,创建该文件并添加如下内容:
nameserver 114.114.114.114
nameserver 192.168.101.1
创建完以上三个文件后,重启linux,发现没有错误提示了。ping一下百度也可以ping通,网络也可以使用了,此时可以通过交叉编译器来编译可以在100ASK开发板上运行的linux程序了。
3.5 构建 /dev 目录
mkdir -p ~/nfs_rootfs/blogrootfs/dev
cd ~/nfs_rootfs/blogrootfs/dev
sudo mknod console c 5 1
sudo mknod null c 1 3
三.编译QT_arm源码与tslib
一. 安装tslib
tar xzf tslib-1.4.tar.gz
cd tslib
mkdir -p generated_tslib_ok/tslib
echo "ac_cv_func_malloc_0_nonnull=yes" >arm-linux.cache
./configure --host=arm-linux ac_cv_func_malloc_0_nonnull=yes CC=arm-linux-gnueabihf-gcc \
-prefix=$(pwd)/generated_tslib_ok/tslib
make&sudo make install
tslib安装在/generated_tslib_ok/tslib目录下:
二. 安装qt-everywhere-opensource-src-5.6.0
tar -xf qt-everywhere-opensource-src-5.6.0.tar.gz
cd qt-everywhere-opensource-src-5.6.0
vi qtbase/mkspecs/linux-arm-gnueabi-g++/qmake.conf
原配置文件:
修改配置文件:(注意以下选项:QMAKE_INCDIR QMAKE_LIBDIR对应tslib安装目录)
#
# qmake configuration for building with arm-linux-gnueabi-g++
#
MAKEFILE_GENERATOR = UNIX
CONFIG += incremental
QMAKE_INCREMENTAL_STYLE = sublib
QT_QPA_DEFAULT_PLATFORM = linuxfb
QMAKE_CFLAGS_RELEASE += -O2 -march=armv7-a
QMAKE_CXXFLAGS_RELEASE += -O2 -march=armv7-a
QMAKE_INCDIR +=/home/book/QT_imx6ull/tslib/generated_tslib_ok/tslib/include
QMAKE_LIBDIR +=/home/book/QT_imx6ull/tslib/generated_tslib_ok/tslib/lib
include(../common/linux.conf)
include(../common/gcc-base-unix.conf)
include(../common/g++-unix.conf)
# modifications to g++.conf
QMAKE_CC = arm-linux-gnueabihf-gcc
QMAKE_CXX = arm-linux-gnueabihf-g++
QMAKE_LINK = arm-linux-gnueabihf-g++
QMAKE_LINK_SHLIB = arm-linux-gnueabihf-g++
# modifications to linux.conf
QMAKE_AR = arm-linux-gnueabihf-ar cqs
QMAKE_OBJCOPY = arm-linux-gnueabihf-objcopy
QMAKE_NM = arm-linux-gnueabihf-nm -P
QMAKE_STRIP = arm-linux-gnueabihf-strip
load(qt_config)
配置选项:
./configure -v -prefix /opt/qt-5.6.0 -release \
-opensource -no-accessibility \
-make libs -xplatform linux-arm-gnueabi-g++ -optimized-qmake \
-pch \
-qt-sql-sqlite \
-qt-zlib \
-tslib \
-no-opengl \
-no-sse2 \
-no-openssl \
-no-nis \
-no-cups \
-no-glib \
-no-pkg-config \
-no-separate-debug-info \
-I /home/book/QT_imx6ull/tslib/generated_tslib_ok/tslib/include \
-L /home/book/QT_imx6ull/tslib/generated_tslib_ok/tslib/lib
执行安装:
make
sudo make install
最终生成文件:
四. QT与tslib移植
cp /opt/qt-5.6.0 /home/book/nfs_rootfs/blogrootfs/
cp /home/book/QT_imx6ull/tslib/generated_tslib_ok/tslib/ /home/book/nfs_rootfs/blogrootfs/
修改最小根文件系统配置文件,增加以下内容 /etc/profile
export T_ROOT=/tslib
export LD_LIBRARY_PATH=/tslib/lib:$LD_LIBRARY_PATH
export TSLIB_CONSOLEDEVICE=none
export TSLIB_FBDEVICE=/dev/fb0
export TSLIB_TSDEVICE=/dev/input/event1 #注意:该设备为板子触摸屏文件
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
export QTEDIR=/qt-5.6.0
export LD_LIBRARY_PATH=lib:$LD_LIBRARY_PATH
export QT_QPA_GENERIC_PLUGINS=tslib
export QT_QPA_FONTDIR=/lib/fonts
export QT_QPA_PLATFORM_PLUGIN_PATH=plugins
export QT_QPA_PLATFORM=linuxfb:fb=/dev/fb0:size=480x640:mmSize=1280x720:offset=0x0:tty=/dev/ttymxc0
export TSLIB_TSDEVICE=/dev/input/event1 #注意:该设备为板子触摸屏文件
移植后执行QT应用文件,可能会出现以下问题:
QIconvCodec::convertToUnicode: using Latin-1 for conversion, iconv_open failed
QIconvCodec::convertFromUnicode: using Latin-1 for conversion, iconv_open failed
下载 http://ftp.gnu.org/gnu/libiconv/libiconv-1.14.tar.gz 解压后,执行以下命令:
./configure -prefix=$PWD/_install -host=arm-linux-gnueabihf
wget -c http://www.itkb.ro/userfiles/file/libiconv-glibc-2.16.patch.gz
gzip -d libiconv-glibc-2.16.patch.gz
cp libiconv-glibc-2.16.patch libiconv-1.14/srclib #将补丁考到 libiconv-1.14/srclib 目录
cd libiconv-1.14/srclib
patch -p1 <libiconv-glibc-2.16.patch
cd libiconv-1.14 #返回
make
make install
#把_install/lib 下的preloadable_libiconv.so 拷到最小根文件系统的/lib 下,
#/etc/profile添加
export LD_PRELOAD=/lib/preloadable_libiconv.so
不打补丁会出现以下问题:
make[2]: [progname.o] Error 1
make[2]: Waiting for unfinished jobs…
make[2]: Leaving directory /opt/sources/libiconv-1.14/srclib
make[1]: [all] Error 2
make[1]: Leaving directory /opt/sources/libiconv-1.14/srclib
make: *** [all] Error 2
参考链接:
此刻,兼容QT5.6.0的最小根文件制作完成
四.使用genimage制作可烧录运行镜像
在制作完最小根文件系统后,需配置系统内核模块以及固件:
重新挂载rootfs.ext4,在根文件系统下创建/boot目录,
拷贝编译好的内核镜像和设备树文件到 arm 架构 ubuntu 根文件系统的 boot 目录下。
安装内核模块到arm架构的ubuntu文件系统内,如下命令所示,
book@100ask:~/100ask_imx6ull-sdk/Linux-4.9.88$ sudo make ARCH=arm INSTALL_MOD_PATH=/home/book/nfs_rootfs/roofs_ext4_touch/rootfs_mount modules_install
INSTALL_MOD_PATH后面的目录地址为 arm 架构 ubuntu 文件系统所在绝对路径(模块安装前需要先编译模块make moudle)。
安装完内上述文件后,即可进行镜像生成操作如下命令所示,需要先生成一个大小为 2GB 的 rootfs.ext4 镜像文件,让后格式化镜像为 ext4 格式,之后通过挂载镜像方式把制作好的镜像文件拷贝到文件系统内。
book@100ask:~$ dd if=/dev/zero of=rootfs.ext4 bs=1M count=512
book@100ask:~$ sudo mkfs.ext4 -F rootfs.ext4
如下命令所示,创建一个 rootfs-mount 目录,并挂载 rootfs.ext4 镜像到该目录下,之后拷贝制作好的文件系统内所有文件到此挂载目录,紧接着使用 sync 命令同步数据缓存保证拷贝完成,完成后可以使用 sudo umount rootfs-mount/卸载当前挂载的镜像。
book@100ask:~$ mkdir rootfs-mount
book@100ask:~$ sudo mount rootfs.ext4 rootfs_mount/
book@100ask:~$ sudo cp -rvfp min_blogrootfs/* rootfs_mount/
book@100ask:~$ sync
book@100ask:~$ sudo umount rootfs_mount/
只制作好 ext4 格式的文件系统并不能直接烧录到开发板启动,此时我们需要使用一个 buildroot 下的一个镜像生成工具 genimage 来制作。首先把编译好生成的 genimage 可执行程序拷贝到家目录下,同时把编译好的 uboot 镜像文件 u-boot-dtb.imx 文件也拷贝到当前目录下。
此时需要在家目录下新建一个名为 root-genimage.cfg 的分区配置文件,里面写入如下信息。
image 100ask_imx6ull.img {
hdimage {
}
partition u-boot {
in-partition-table = "no"
image = "u-boot-dtb.imx"
offset = 1024
}
partition arduino {
partition-type = 0xC
size = 50M
offset = 10M
}
partition rootfs {
partition-type = 0x83
image = "rootfs.ext4"
size = 512M
}
此时目录下有如下 4 个文件,分别是 rootfs-genimage.cfg rootfs.ext4 u-boot-dtb.imx genimage
此时我们可以执行如下命令来生成 ubuntu-16.04-armhf_100ask_imx6ull.img 系统镜像文件。
book@100ask:~$ mkdir root
book@100ask:~$ sudo ./genimage --inputpath ./ --outputpath ./ --config ./rootfs-genimage.cfg
执行命令完成在当前路径下生成空白文件目录与镜像文件100ask_imx6ull.img。
使用FileZilla软件将镜像文件拷贝到PC机修改正确的文件目录名称,使用100ask_imx6ull_flashing_tool即可烧录运行测试
五. 功能演示
- 测试tslib,并校准屏幕:
- 自己编写的QT测试程序,编译执行:
PS:根文件系统没有一次制作完成得多次挂载移植文件有点繁琐,不过当作练习命令敲写:!,过程还有很多地方得学习改进…