1、tslib编译和安装
其他不多说,jz2440出厂移植的是Qtopia-free-2.2.0,在Qtopia 4.*版本中,默认的Tslib版本为Tslib 1.4。在Qtopia 2.*版本中,默认的Tslib版本为Tslib 1.3
tslib-1.4.tar.gz下载链接http://vdisk.weibo.com/s/AcUHxOERV2k0
1.1编译tslib库
下载完成后,在命令行输入
tar -xzf tslib-1.4.tar.gz
cd进入该目录
首先安装以下依赖
sudo apt-get install autoconf
sudo apt-get install automake
sudo apt-get install libtool
如果不安装依赖执行.autogen.sh则会出现找不到文件中的libtoolize,aclocal,autoheader,automake
echo -n "Libtoolize..."
libtoolize --force --copy
echo "Done."
echo -n "Aclocal..."
aclocal
echo "Done."
echo -n "Autoheader..."
autoheader
echo "Done."
echo -n "Automake..."
automake --add-missing --copy
echo "Done."
echo -n "Autoconf..."
autoconf
安装完成后,接着执行
./autoge.sh
配置tslib
./configure --host=arm-linux --prefix=/usr/local/tslib ac_cv_func_malloc_0_nonnull=yes 这边我直接安装到/usr/local/tslib
编译tslib
make (确保是交叉编译器,因为i我们要给ARM平台用的 这边用的arm-linux-gcc)
make过程中没出现什么问题(如果有 自行谷歌,百度)
安装tslib
执行make installz则会把tslib库安装到配置时的目录下
安装完成可以看到bin etc include lib目录
测试tslib 等等在测试
2 移植Qt
思路先理清楚,首先下载qt-everywhere-opensource-src-4.8.6.tar.gz,接着配置源码,编译源码,安装源码
下载qt-everywhere-opensource-src-4.8.6.tar.gz
链接地址:http://mirrors.ustc.edu.cn/qtproject/archive/qt/4.8/4.8.6/
下载完成后,
解压:tar -xzf qt-everywhere-opensource-src-4.8.6.tar.gz
cd到目录
编写autogen.sh脚本文件
#!/bin/sh
./configure \
-opensource \
-confirm-license \
-release -shared \
-embedded arm \
-xplatform qws/linux-arm-g++ \
-depths 16,18,24,32 \
-fast \
-optimized-qmake \
-pch \
-qt-sql-sqlite \
-qt-libjpeg \
-qt-zlib \
-qt-libpng \
-qt-freetype \
-system-libjpeg \
-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-opengl \
-no-cups \
-no-glib \
-no-xcursor -no-xfixes -no-xrandr -no-xrender \
-no-separate-debug-info \
-nomake examples -nomake tools -nomake docs \
-qt-mouse-tslib \
-I/usr/local/tslib/include \
-L/usr/local/tslib/lib \
-D__ARM_ARCH_5TEJ__
exit
这边着重说说 qt-libjpeg 和system-jpeg,待会要用到这个小知识点
qt-libjpeg是指使用qt自己编译的库文件,比如qt资源文件中的jpeg格式的文件
system-jpeg是指使用本地jpeg格式的图片文件
配置会出现
The tslib functionality test failed!
You might need to modify the include and library search paths by editing
QMAKE_INCDIR and QMAKE_LIBDIR in
/home/zdw/qt-everywhere-opensource-src-4.8.6/mkspecs/qws/linux-arm-g++.
解决方法:
cd到该目录/home/zdw/qt-everywhere-opensource-src-4.8.6/mkspecs/qws/linux-arm-g++.
打开qmake.conf文件
修改成
#
# qmake configuration for building with arm-linux-g++
#
include(../../common/linux.conf)
include(../../common/gcc-base-unix.conf)
include(../../common/g++-unix.conf)
include(../../common/qws.conf)
QMAKE_INCDIR=/usr/local/tslib/include
QMAKE_LIBDIR=/usr/local/tslib/lib
# modifications to g++.conf
QMAKE_CC = /opt/gcc-3.4.5-glibc-2.3.6/bin/arm-linux-gcc
QMAKE_CXX = /opt/gcc-3.4.5-glibc-2.3.6/bin/arm-linux-g++
QMAKE_LINK = /opt/gcc-3.4.5-glibc-2.3.6/bin/arm-linux-g++
QMAKE_LINK_SHLIB = /opt/gcc-3.4.5-glibc-2.3.6/bin/arm-linux-g++
# modifications to linux.conf
QMAKE_AR = /opt/gcc-3.4.5-glibc-2.3.6/bin/arm-linux-ar cqs
QMAKE_OBJCOPY = /opt/gcc-3.4.5-glibc-2.3.6/bin/arm-linux-objcopy
QMAKE_STRIP = /opt/gcc-3.4.5-glibc-2.3.6/bin/arm-linux-strip
load(qt_config)
意思就是修改成交叉编译器的绝对路径
重新sudo ./autogen.sh
接着 往下看, 就是传说中的make了
这是我在编译时遇到的问题
/qthread_unix.o thread/qthread_unix.cpp 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
{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 */
../3rdparty/javascriptcore/JavaScriptCore/wtf/Platform.h:328:6: #error "Not supported ARM architecture"
解决方法:
在configure 时在后面加上 -D__ARM_ARCH_5TEJ__
../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); }
如果有其他错误自行谷歌百度(加油,相信你可以的)
至此编译成功。
接着安装
sudo make install
默认安装到ubuntu的根文件系统下的/usr/local/Trolltech/QtEmbedded-4.8.6-arm(建议不要修改安装路径,意思就是修改了也是安装到这边,不是耍你,我自己也被Qt/E耍了)
安装以后,出现以下目录
至此,Qt和tslib-1.4都编译安装好了
但是如何才能让2440用起来?当然就是制作文件系统,如何制作最小根文件系统,请看韦东山老师的一期视频,这里假设有最小根文件系统
首先,我们挂接nfs网络根文件系统,用作调试,(要注意的点是,ubuntu防火墙要关,如果是虚拟机的话要设置成桥接模式)
1、ubuntu下安装 nfs服务
sudo apt-get nfs-kernel-server
然后 打开/etc/目录下的exports文件
gedit /etc/exports
添加
/home/zdw/fs_qt4.8.5 *(rw,sync,no_root_squash,no_subtree_check) //路径填自己的
重启ubuntu或者 /etc/init.d/nfs-kernel-server restart
2、在开发板上进入uboot命令行 设置bootargs参数
set bootargs noinitrd root=/dev/nfs/ nfsroot=192.168.1.127:/home/zdw/fs_qt4.8.6 ip=192.168.1.126:192.168.1.127:192.168.1.1:255.255.255.0::eth0:off init=/linuxrc console=ttySAC0
(其中:192.168.1.126为开发板的IP,192.168.1.127为ubuntu的IP,192.168.1.1为网关)
重启开发板,即可挂接最小根文件系统
以下都是对最小根文件系统进行操作
工作目录为最小根文件系统中
3、上面不是安装了tslib1.4,这边就要用起来了
将/usr/local/tslib/bin/目录下的文件ts_calibrate和ts_test拷贝到根文件系统的bin目录下
将/usr/local/tslib/lib文件下除去pkgconfig目录外其他所有文件拷贝到最小根文件系统/lib目录下
将/usr/local/tslib/etc下的ts.conf拷贝到最小根文件系统的/etc下,修改ts.conf文件。
下面是ts.conf文件的第一行与第二行
# Uncomment if you wish to use the linux input layer event interface
# module_raw input
去掉# module_raw input前面的注释,一定要注意中间的空格也去掉,module顶格。
然后在etc目录下创建profile脚本文件添加以下内容(注意JZ2440的触摸屏设备结点为event0,LCD设备节点为fb0)
#!/bin/sh
export TSLIB_TSDEVICE=/dev/event0
export TSLIB_CONFFILE=/etc/ts.conf
export TSLIB_PLUGINDIR=/lib/ts
export TSLIB_CALIBFILE=/etc/pointercal
export TSLIB_CONSOLEDEVICE=none
export TSLIB_FBDEVICE=/dev/fb0
保存
设置可执行权限
chmod +x etc/profile
然后打开etc/init.d/rcSgedit etc/init.d/rcS
添加/etc/profile
重启开发板
执行ts_calibrate
开发板就会出现校准屏幕,同时串口输出坐标信息。
etc目录下就会出现pointeral校准文件
至此tslib移植成功
5、移植QtEmbedded-4.8.6-arm
将ubuntu的文件系统/usr/local/Trolltech目录下QtEmbedded-4.8.6-arm拷贝到根文件系统下usr/local目录下
接着设置环境变量
cd到最小根文件系统目录下
在最小根文件系统下打开/etc/profile脚本文件
gedit etc/profile
添加以下内容
export QWS_SIZE=480x272
export set QTDIR=/usr/local/QtEmbedded-4.8.6-arm #目录名要与拷贝的Qt文件名一致
export set LD_LIBRARY_PATH=$QTDIR/lib:$LD_LIBRARY_PATH
export set PATH=$QTDIR/bin:$PATH
export set MANPATH=$QTDIR/man:$MANPATH
export set QT_QWS_FONTDIR=/usr/local/QtEmbedded-4.8.6-arm/lib/fonts
export set QWS_MOUSE_PROTO=tslib:/dev/event0
由于开发Qt程序需要用图片库所以继续添加以下内容
#使用Qt自带的编译的图片库
export LD_LIBRARY_PATH=/usr/local/QtEmbedded-4.8.6-arm/plugins/imageformats:$LD_LIBRARY_PATH
export QT_PLUGIN_PATH=/usr/local/QtEmbedded-4.8.6-arm/plugins
这些内容根据Qt程序要用到什么东西就添加库路径就好了
重启开发板
至此算是Qt移植成功了
在开发板上cd到/usr/local/QtEmbedded-4.8.6-arm/demos目录下
执行示例代码
cd textedit
./textedit -qws
必须加-qws
下面介绍制作移植Qt后根文件系统映像
目标板是JZ2440 DRAM为64M
用dnw或者tftp下载超过64M的东西都会失败
我们编译的Qt都要80几M制成映像那就要变成90几M所以肯定下载不成功
所以想到的就是裁剪,毕竟是linux裁剪是经常事
这边采用的不是配置上还减少,因为现在剩下的可以用Qt开发的功能也是少得可怜(这边提一下 不能开发QWidget,没有配置-qwidget)
首先编译好的Qt目录下的bin对运行在ARM板子上是没有意义的,所以删除(21.9M呢)
demos目录也没用,删除
最后剩下imports include lib mkspecs plugins 目录就可以了
mkspecs目录下也是一些文件没用,没猜错的话就用得上qws目录下的linux-arm-g++目录下的文件
其他也可以删(没试过 只是删除把win的删了)
根据要运行的Qt程序删除一些没有用到的库(这个要求你要懂一些Qt基本东西)(就是程序用到哪些类 你在lib目录下别删和类相同的库文件)
include目录也是一样(删除一些没用的头文件)
现在制成文件系统映像大概小于64M了接近62M左右
就可以下载到2440板子上这边用的是tftp下的
我也是遇到这样的问题
Warning: unable to open an initial console. Failed to execute /linuxrc. Attempting defaults... Kernel panic - not syncing: No init found. Try passing init= option to kernel.
原因是我从内存中拷贝到文件系统地址方式的问题
tftp 30000000 fs_qt4.8.6.yaffs2
nand erase root 擦除root分区
nand write.yaffs 30000000 260000 $(filesize)
这样就可以了
然后
重启开发板 遇到不能执行Qt程序和触摸屏测试程序
遇到段错误
,一开始觉得不可能啊 怎么会这样 我又重新挂接nfs根文件系统又没问题,我重新看了配置问题,感觉应该是校准问题,我删了重启开发板执行ts_calibrate程序,就解决问题
为防止日后出现相同问题
在etc目录下的profile脚本文件添加 -e针对单个文件()
if [ ! -e /etc/pointercal ] //如果etc目录下没有pointercal执行文件
then
/bin/ts_calibrate
fi
如果想要开机执行Qt程序也是在脚本中添加
/video/video -qws &
接下去安装嵌入式Qt开发环境
下载qtcreator 资源qt-creator-linux-x86-opensource-2.6.0.bin
下载链接:http://pan.baidu.com/s/1pKOfzbP 或者到官网下,百度谷歌
安装qtcreator
sudo qt-creator-linux-x86-opensource-2.6.0.bin
自己选择安装目录
跟window系统软件安装一样,后面可用设置ubuntu桌面快捷方式具体实现方式参考如下
gedit Qt4.8.6.desktop
[Desktop Entry]
Categories=Development;
Comment[zh_CN]=
Comment=
Exec=/home/zdw/Qt/Qt5.5/Tools/QtCreator/bin/qtcreator 解释:这里放的是qtcreator的具体文件路径
GenericName[zh_CN]=IDE
GenericName=IDE
Icon=/home/zdw/Qt/Qtlcon.png 解释:这里放的是桌面快捷方式的图标路径
MimeType=
Name[zh_CN]=Qt5.5 解释:这里放的是桌面快捷方式的名称
Name=Qt5.5
Path=
StartupNotify=true
Terminal=false
Type=Application
X-DBUS-ServiceName=
X-DBUS-StartupType=
X-KDE-SubstituteUID=false
X-KDE-Username=warsllon
或者直接添加环境变量
export PATH=/usr/local/qtcreator-2.6.0/bin:$PATH
这样就可以在终端直接输入qtcreator打开Qt的IDE了
配置交叉编译器
打开IDE在菜单栏下点击工具 接着点击选项
分到构建和运行
在Qt版本这里选择 我们之前编译安装的路径下的bin目录下的qmake,这个用来管理Qt工程文件的
这里换到Compilers 选择编译器路径,就是ARM平台的编译器,不过这是Qt框架是由C++写的所以C++的编译器是g++
这边这么设置吧
接下来就可以开开心心玩转Qt跨ARM平台即2440了
编译Qt程序 点击IDE中的主界面的锄头
至此环境搭建好了
关于视频监控 我是采用定时器刷新视频服务器的图像信息
mainWindow.cpp文件内容
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "QPixmap"
#include "QLabel"
#include "QDir"
#include "QFile"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
img=new QImage;
scaledimg=new QImage;
showTime=new QTimer;
showTime->setInterval(50);//毫秒级
Mkdirfile();
QObject::connect(showTime,SIGNAL(timeout()),this,SLOT(flushPic()));
manager = new QNetworkAccessManager(this);
QObject::connect(manager,SIGNAL(finished(QNetworkReply*)),this,SLOT(slot_replyFinished(QNetworkReply*)));
button_movieIsClicked = false;
}
MainWindow::~MainWindow()
{
delete ui;
QFile::remove("/root/mjpg-streamer/temp1.jpg");
}
void MainWindow::Mkdirfile()
{
if(!QDir("/root/mjpg-streamer").exists())
{
QDir dir;
dir.mkpath("/root/mjpg-streamer");
}
}
void MainWindow::flushPic()
{
request.setUrl(QUrl(PU));
manager->get(request);
}
void MainWindow::slot_replyFinished(QNetworkReply *reply)
{
if(button_movieIsClicked==true)
{
QPixmap pix;
QByteArray data = reply->readAll();
pix.loadFromData(data,"JPG");
pix.save("/root/mjpg-streamer/tmp1.jpg","JPG",100);//文件名 图像格式 压缩率图片质量
if(!(img->load("/root/mjpg-streamer/tmp1.jpg")))
{
showTime->stop();
QMessageBox::information(this,tr("failed"),tr("open failed"));
button_movieIsClicked=false;
return;
}
*scaledimg=img->scaled(640,480,Qt::KeepAspectRatio);
ui->PicLabel->setPixmap(QPixmap::fromImage(*scaledimg));
}
else
{
QPixmap pixmap(":/new/prefix1/背景.jpg");
ui->PicLabel->setPixmap(pixmap);
}
}
void MainWindow::on_ButtonMovie_clicked()
{
Address=ui->AddressLineEdit->text();
Port=ui->PortlineEdit->text();
PU="http://"+Address+":"+Port+"/?action=snapshot";
if(button_movieIsClicked==false)
{
button_movieIsClicked=true;
ui->ButtonMovie->setText("finished");
showTime->start();
}
else
{
button_movieIsClicked=false;
ui->ButtonMovie->setText("video");
showTime->stop();
}
}
mainWindow.h文件内容
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include "QtNetwork/QNetworkAccessManager"
#include "QtNetwork/QNetworkReply"
#include "QtNetwork/QNetworkRequest"
#include "QMessageBox"
#include "QTimer"
#include "QImage"
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
QImage *img;
QImage *scaledimg;
QTimer *showTime;
QNetworkAccessManager *manager;
QNetworkRequest request;
QString PU,Address,Port;
bool button_movieIsClicked; //控制显示“视频”或者“结束”
void Mkdirfile();
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
public slots:
void slot_replyFinished(QNetworkReply*reply);
void flushPic();
private slots:
void on_ButtonMovie_clicked();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
至于Qt可执行程序如何弄到2440上 比如挂载nfs服务