参考文章:https://blog.csdn.net/lizuobin2/article/details/52673494
中间遇到了很多问题,最终还是成功了,这里记录以下。
- 环境:Ubuntu 16.04_x64 LTS
- 内核:linux-2.6.22.6.tar.bz2
- busybox:busybox-1.22.1.tar.bz2
- 交叉编译器:arm-linux-gcc-4.4.3.tar.gz
- tslib:tslib-1.4.tar.gz
交叉编译器
tar zxvf arm-linux-gcc-4.4.3.tar.gz
cd ./opt/FriendlyARM/toolschain/
cp -rfd 4.4.3 /work/tools
#添加环境变量(在/etc/profile中export也行)
vi /etc/environment #内容如下
PATH="最后添加:/work/tools/4.4.3/bin"
source /etc/environment
内核
tar xjf linux-2.6.22.6.tar.bz2
patch -p1 < ../linux-2.6.22.6_jz2440_v2v3.patch
cp config_ok .config
make menuconfig
Kernel Features ->
<*>Use the ARM EABI to compile the kernel
vi Makefile
SUBLEVEL = 22改为SUBLEVEL = 32
#注释下面四行,上面的交叉编译工具不支持-gdwarf2调试功能
ifdef CONFIG_DEBUG_INFO
CFLAGS += -g
AFLAGS += -gdwarf2
endif
make uImage -j4 #-j4:4线程
- 之前装的交叉编译工具规定内核最低版本为2.6.32,这里为了方便直接在Makefile改内核版本,否则启动内核时会提示
kernel too old
- 交叉编译器里面的
EV_VERSION
数值需要和内核include/linux/input.h
中的EV_VERSION
所使用的一致(这里一致,如果用linux 3.4.2会不一致)
文件系统
tar jxvf busybox-1.22.1.tar.bz2
make menuconfig
Busybox Settings ->
general configuration ->
[*] don't use /usr #选中它,否则会破坏虚拟机
build options->
cross comliler prefix = arm-linux- #交叉编译工具
installtion options->
busybox installation prefix = /work/rootfs #安装路径
mkdir -p /work/rootfs
make
make install
接着还要配置一些文件,进入刚刚的安装目录
(1)创建etc
文件夹,建立如下内容
①fstab
文件
执行mount -a
会挂载fstab
文件中定义的文件系统
# device mount-point type options dump fsck order
proc /proc proc defaults 0 0
tmpfs /tmp tmpfs defaults 0 0
sysfs /sys sysfs defaults 0 0
tmpfs /dev tmpfs defaults 0 0
②inittab
文件
init
进程会调用parse_inittab()
解析inittab
文件,内容如下
# /etc/inittab
::sysinit:/etc/init.d/rcS
::askfirst:-/bin/sh
::ctrlaltdel:/sbin/reboot
::shutdown:/bin/umount -a -r
简单分析一下:
- 第一项为console,用作stdin、stdout和stderr输出,留空则默认输出到
/dev/console
- 第二项为runlevel,一般忽略不填
- 第四项为process,应用程序或可执行脚本
- 第三项为action,即执行时机,有八种。这里仅介绍上面出现的:
1.SYSINIT
:执行后面跟的应用程序或脚本一次,然后就退出
2.ASKFIRST
:后面的程序一直运行,运行前向用户“ask first”,对于上面的::askfirst:-/bin/sh
,即启动Linux后需要用户按下回车键,才运行bash
3.CTRLALTDEL
:按下Ctrl+Alt+Del键执行
4.SHUTDOWN
:关机时执行
③建立init.d
文件夹,在下面创建rcS
脚本文件
刚刚分析了,inittab
中的::sysinit:/etc/init.d/rcS
会在系统启动时,执行rcS
脚本文件。
#!/bin/sh
ifconfig eth0 192.168.1.17
mount -a #挂载fstab
mkdir /dev/pts #用于虚拟终端telnet/ssh等
mount -t devpts devpts /dev/pts #挂载
echo /sbin/mdev > /proc/sys/kernel/hotplug #支持热插拔
mdev -s #根据/sys目录下的相关信息,自动创建节点(mknod)
(2)创建dev
文件夹并进入
在init
进程中会打开console
字符设备节点,如果用户指定的设备节点打开失败,会打开null
字符设备节点,这里创建这两个节点:
mkdir dev && cd dev
sudo mknod console c 5 1
sudo mknod null c 1 3
(3)创建其它目录
mkdir proc mnt tmp sys root usr
(4)复制交叉编译库
cd /work/tools/4.4.3/arm-none-linux-gnueabi/lib
cp *.so* /work/rootfs/lib -rfd
cd /work/tools/4.4.3/lib
cp *.so* /work/rootfs/lib -rfd
TSLIB
#确保安装下面三个软件已安装
sudo apt-get install autoconf automake libtool
cd tslib
./autogen.sh
mkdir tslib #等会安装到目录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-none-linux-gnueabi-gcc CXX=arm-none-linux-gnueabi-g++ -prefix=$(pwd)/tslib
make
make install
vi ./tmp/etc/ts.conf
取消第二行module_raw input的注释
#将tmp里面的bin,etc,include,lib 4个目录下的文件拷贝到开发板的对应目录下
cp ./tslib/bin /work/rootfs/bin -rfd
cp ./tslib/etc /work/rootfs/etc -rfd
cp ./tslib/include /work/rootfs/include -rfd
cp ./tslib/lib /work/rootfs/lib -rfd
然后添加tslib环境变量
vi /work/rootfs/etc/profile
添加如下内容:
export TSLIB_TSDEVICE=/dev/event0
export TSLIB_CALIBFILE=/etc/pointercal
export TSLIB_CONFFILE=/etc/ts.conf
export TSLIB_PLUGINDIR=/lib/ts
export TSLIB_CONSOLEDEVICE=none
export TSLIB_FBDEVICE=/dev/fb0
烧写测试
由于内核版本太老,busybox1.22.1不支持启动内核后用mount
挂载服务器上的文件夹,不过开发板和Ubuntu之间可以ping通,所以可以通过tftp下载文件
tftp -g -l 1.txt 192.168.1.12 #从Ubuntu下载tftp文件夹里的1.txt
当然也可以设置NFS启动(需要交换机或路由器)。其中Ubuntu18.04需要在bootargs的nfsroot后面加上v3才能以NFS启动。
noinitrd root=/dev/nfs nfsroot=192.168.1.12:/work/rootfs,v3 ip=192.168.1.17:192.168.1.12::255.255.255.0::eth0:off init=/linuxrc console=ttySAC0,115200
以下为制作yaffs2映像文件的步骤
(1)yaffs2制作工具
tar xjf yaffs_source_util_larger_small_page_nand.tar.bz2
cd Development_util_ok/yaffs2/utils/
make
sudo cp mkyaffs2image /usr/local/bin #拷贝到环境变量目录
sudo chmod +x /usr/local/bin/mkyaffs2image #添加执行权限
(2)制作yaffs2文件系统镜像
mkyaffs2image /work/rootfs test.yaffs2
现在通过U-Boot烧写内核和文件系统,其中bootargs
设置如下
bootargs=noinitrd root=/dev/mtdblock3 init=/linuxrc console=ttySAC0,115200
启动内核,运行tslib测试
ts_calibrate #校准屏幕坐标
vi /etc/pointercal #cat和vi这个文件最后显示不同,所以这里用vi
复制里面的内容,然后回到Ubuntu创建相同文件
vi /work/rootfs/etc/pointercal
粘贴刚刚的内容,我的校准内容如下
34441 142 -1903264 -254 23036 -2835128 65536^@
这样以后就不需要每次都校准屏幕了。
安装QT的库和插件到开发板
tar zxvf qt-everywhere-opensource-src-5.6.0.tar.gz
cd qt-everywhere-opensource-src-5.6.0/qtbase/mkspecs/linux-arm-gnueabi-g++
vi qmake.conf
修改qmake.conf
文件如下(对于JZ2440):
#
# 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 += -msoft-float -D__GCC_FLOAT_NOT_NEEDED -march=armv4t -mtune=arm920t
QMAKE_CXXFLAGS += -msoft-float -D__GCC_FLOAT_NOT_NEEDED -march=armv4t -mtune=arm920t
include(../common/linux.conf)
include(../common/gcc-base-unix.conf)
include(../common/g++-unix.conf)
# modifications to g++.conf
QMAKE_CC = /work/tools/4.4.3/bin/arm-none-linux-gnueabi-gcc -lts
QMAKE_CXX = /work/tools/4.4.3/bin/arm-none-linux-gnueabi-g++ -lts
QMAKE_LINK = /work/tools/4.4.3/bin/arm-none-linux-gnueabi-g++ -lts
QMAKE_LINK_SHLIB = /work/tools/4.4.3/bin/arm-none-linux-gnueabi-g++ -lts
# modifications to linux.conf
QMAKE_AR = /work/tools/4.4.3/bin/arm-none-linux-gnueabi-ar cqs
QMAKE_OBJCOPY = /work/tools/4.4.3/bin/arm-none-linux-gnueabi-objcopy
QMAKE_NM = /work/tools/4.4.3/bin/arm-none-linux-gnueabi-nm -P
QMAKE_STRIP = /work/tools/4.4.3/bin/arm-none-linux-gnueabi-strip
load(qt_config)
接着回到安装目录,配置参数
cd ../../..
sudo mkdir -p /usr/local/Qt5.6
#执行.configure
sudo ./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 -j4
sudo make install
注意事项:
-I
和-L
分别指定头文件目录和库目录,在刚刚安装tslib生成的目录tslib
中,这里提前将tslib目录复制到/usr/local
中。./configure
遇到问题:
编译时不用配置的arm-none-linux-gnueabi-gcc
,而是用g++,然后说g++找不到,随便装个g++或者将交叉编译工具里的g++建立一个软连接放在环境变量目录都会有不同错误。
结论:上述问题出现在Ubuntu18.04,后将系统换为Ubuntu16.04 LTS得以解决,但上述的内核、文件系统、tslib在18.04编译没有问题。make -j4
遇到问题:
整个过程半小时,然后最后突然冒出某个错误,又得花半小时,还不知道改的对不对,实在是磨人。以下库是我最终总结出来的,可能其中一两个库没什么用,但是一make就是半小时,实在没那个精力去试哪个没用,建议全部安装。
sudo apt-get install lib32z1
sudo apt-get install lib32ncurses5
sudo apt-get install libncurses5-dev libncursesw5-dev
sudo apt-get install lib32stdc++6
sudo apt-get install libc6-dev
sudo apt-get install libqt5serialport5-dev libudev-dev
sudo apt-get install dbus
sudo apt-get install libjpeg-dev
- 可以在最前面加上
#!/bin/bash
,保存为一个sh文件运行,这样就不用一个个复制安装了
接着压缩刚刚生成的文件夹
cd /usr/local
#开发板环境只需要lib和plugins目录,而等会用QT Creator写程序需要其它目录
cp -rfd Qt5.6 Qt5.6-1 #建立一个副本
cd Qt5.6
rm -rf doc include bin mkspecs qml translations
cd ..
sudo tar zcvf Qt5.6.tar.gz Qt5.6
rm -rf Qt5.6 && mv Qt5.6-1 Qt5.6 #删除库目录并将副本名字改回来
cp Qt5.6.tar.gz /work/rootfs/usr/local/ #拷贝到根文件下
- 压缩的原因:不能直接将
lib
和plugins
目录复制到根文件系统中,这样制作出根文件系统后文件太大,一般会超过了SDRAM的大小64M,U-Boot烧写文件系统的程序是一次将程序完整读到内存再烧写的,所以无法烧写到NAND Flash。如果用NFS启动当然就没有这些问题。
最后添加QT的环境变量
vi /work/rootfs/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=95x53:offset=0x0:tty=/dev/tty1
export QT_QPA_FB_TSLIB=1
export LD_PRELOAD=/lib/preloadable_libiconv.so
- 最后一行的preloadable_libiconv.so:稍后执行程序时会有如下两条错误信息
QIconvCodec::convertFromUnicode: using Latin-1 for conversion, iconv_open failed
QIconvCodec::convertToUnicode: using Latin-1 for conversion, iconv_open failed
需要安装libiconv-1.14.tar.gz
mkdir -p /usr/local/libiconv #安装到这个目录
tar xzvf libiconv-1.14.tar.gz
cd libiconv-1.14
./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
cd /usr/local/libiconv/lib
cp preloadable_libiconv.so /work/rootfs/lib #拷贝到文件系统
安装QT Creator编写程序
下载QT Creator 5.6到Ubuntu中安装
sudo chmod 777 qt-opensource-linux-x64-5.6.0.run
./qt-opensource-linux-x64-5.6.0.run
安装完运行,打开Tools - Options,然后选择Build & Run
进行配置:
(1)Compilers
点击Add添加编译器
- Name:
arm-linux-gcc 4.4.3
- Compiler path:
/work/tools/4.4.3/bin/arm-none-linux-gnueabi-c++
(2)Qt Versions
点击Add添加qmake
- qmake location:
/usr/local/Qt5.6/bin/qmake
(3)Kits
点击Add添加套件
- Name:
JZ2440 Qt 5.6.0 GCC 32bit
- Compiler:
arm-linux-gcc 4.4.3
以后创建项目时Kit选择JZ2440 Qt 5.6.0 GCC 32bit
就可以了。
程序编译和运行
编写完程序后,点击菜单栏的Build
,前后分别点击Run qmake
和Build Project "xxx"
,可执行程序默认生成在工程目录文件夹所在目录下的build-xxx-JZ2440_Qt_5_6_0_GCC_32bit-Release
文件夹中,复制相应程序到根文件目录中。
- 假设程序名为test
chmod +x test
cp test /work/rootfs
mkyaffs2image /work/rootfs qt.yaffs2 #qt.yaffs2大概40M
启动开发板,解压QT库,运行程序
cd /usr/local && tar xzvf Qt5.6.tar.gz
cd ..
./test
中文显示
QT5.6没有中文字库,可以在C:\Windows\Fonts
中复制一个字库,我复制了宋体字库STSONG.TTF
。
1.pro工程文件中添加:
QT += gui
2.在主窗口构造函数中添加:
int id = QFontDatabase::addApplicationFont("/STSONG.TTF");
QString msyh = QFontDatabase::applicationFontFamilies (id).at(0);
QFont font(msyh,10);
font.setPointSize(10);
this->setFont(font);
一个汉字对应的Unicode(UTF-8)即该汉字在字库中的索引,且QT Creator编辑器的默认编码为UTF-8,所以进行上面的字体设置后,直接在代码中写汉字即可正常显示。
最终制作好的根文件系统和内核下载:https://pan.baidu.com/s/1hywVYpEterofKlLYLPLZeg 1234
- 根文件系统的根目录有一个
init.sh
是解压/usr/local/qt.tar.gz
的脚本,每次启动后运行解压QT库,解压完运行根目录下的test程序即可。