linux GUI-QT6.5移植到Mini2440
Posted 大奥特曼打小怪兽
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了linux GUI-QT6.5移植到Mini2440相关的知识,希望对你有一定的参考价值。
----------------------------------------------------------------------------------------------------------------------------
内核版本:linux 5.2.8
根文件系统:busybox 1.25.0
u-boot:2016.05
开发板:Mini2440
----------------------------------------------------------------------------------------------------------------------------
为实现目标嵌入式平台能够正常运行Qt程序,则需要在目标平台上部署QT运行环境。
一、QT编译和安装
1.1 QT版本介绍
QT的版本比较多,容易搞混。现分别介绍:
- Qt/X11 :指用于Linux/Unix的版本。如:我们常用的qt-x11-opensource-src-4.5.3.tar.gz,它是用于PC机linux平台的QT源码;
- Qt Windows:指用于Windows的版本;
- qt-everywhere:指(在配置时加上不同的参数)既可用于x86,也可用于ARM,如qt-everywhere-opensource-src-4.7.0.tar.gz、qt-everywhere-opensource-src-4.6.1.tar.gz;从Qt4.6开始提供这种源码包;
- Qt/Embedded:指用于ARM平台的版本。如qt-embedded-linux-opensource-src-4.5.3.tar.gzz是用于嵌入式ARM的qt源码包;从Qt4.1开始,Qt/Embedded改名为Qtopia Core,又从Qt4.4.1开始,Qtopia Core又改名为Qt for Embedded Linux,一般发行的源码包的名字叫做:qt-embeded-linux-xxxxxx,但是自动Qt4.6开始就不再提供这种源码包了,而是开始提供qt-everywhere源码包;
1.2 qt-everywhere下载
这里我们下载qt-everywhere,这里我们不去选择较新版本,主要由于新版本已经不支持ARMv4t架构了。我们下载5.0版本即可。
国内镜像站点下载地址:
- https://download.qt.io/archive(官方)
- Tsinghua University (不推荐,旧版本不全,刚才看有同步失败的情况)(TUNA)
- University of Science and Technology of China (推荐,旧版本较全)
在ubuntu服务器上下载程序包:
root@zhengyang:/work/sambashare# cd tools root@zhengyang:/work/sambashare/tools# wget https://download.qt.io/archive/qt/5.0/5.0.0/single/qt-everywhere-opensource-src-5.0.0.tar.xz
下载完后,解压程序包:
root@zhengyang:/work/sambashare/tools# tar -xvf qt-everywhere-opensource-src-5.0.0.tar.xz
1.3 修改qmake.conf
进入 qt-everywhere-opensource-src-5.0.0文件夹,针对Mini2440开发板,修改qmake.conf文件:
root@zhengyang:/work/sambashare/tools# cd qt-everywhere-opensource-src-5.0.0/ root@zhengyang:/work/sambashare/tools/qt-everywhere-src-6.0.0/# vim qtbase/mkspecs/linux-arm-gnueabi-g++/qmake.conf
源文件内容如下:
# # qmake configuration for building with arm-linux-gnueabi-g++ # MAKEFILE_GENERATOR = UNIX CONFIG += incremental QMAKE_INCREMENTAL_STYLE = sublib include(../common/linux.conf) include(../common/gcc-base-unix.conf) include(../common/g++-unix.conf) # 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 load(qt_config)
我们需要根据我们安装得交叉编译工具去修改,由于我之前安装的是arm-linux-gcc 4.8.3,
所以这里我们需要按照我们安装的交叉编译工具来修改QMAKE_CC、QMAKE_CXX等配置项:需要指定全路径。
# # 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 = /usr/local/arm/4.8.3/bin/arm-none-linux-gnueabi-gcc QMAKE_CXX = /usr/local/arm/4.8.3/bin/arm-none-linux-gnueabi-g++ QMAKE_LINK = /usr/local/arm/4.8.3/bin/arm-none-linux-gnueabi-g++ QMAKE_LINK_SHLIB = /usr/local/arm/4.8.3/bin/arm-none-linux-gnueabi-g++ # modifications to linux.conf QMAKE_AR = /usr/local/arm/4.8.3/bin/arm-none-linux-gnueabi-ar cqs QMAKE_OBJCOPY = /usr/local/arm/4.8.3/bin/arm-none-linux-gnueabi-objcopy QMAKE_NM = /usr/local/arm/4.8.3/bin/arm-none-linux-gnueabi-nm -P QMAKE_STRIP = /usr/local/arm/4.8.3/bin/arm-none-linux-gnueabi-strip load(qt_config)
1.4 配置安装
1.4.1 CMake安装
CMake是一个跨平台的构建工具,其支持程度要好于qmake。CMake的配置更加灵活、强大,也更容易维护。如果是Qt6.0+需要安装CMake,否则忽略即可。
注:是一个比make更高级的编译配置工具,它可以根据不同平台、不同的编译器,生成相应的Makefile或者vcproj项目。
接着回到安装目录,安装CMake:
root@zhengyang:/work/sambashare# cd /work/sambashare/tools root@zhengyang:/work/sambashare/tools# wget https://github.com/Kitware/CMake/releases/download/v3.21.2/cmake-3.21.2.tar.gz root@zhengyang:/work/sambashare/tools# tar xf cmake-3.21.2.tar.gz root@zhengyang:/work/sambashare/tools# cd cmake-3.21.2 root@zhengyang:/work/sambashare/tools/cmake-3.21.2# ./configure root@zhengyang:/work/sambashare/tools/cmake-3.21.2# make && make install root@zhengyang:/work/sambashare/tools/cmake-3.21.2# cd .. root@zhengyang:/work/sambashare/tools# rm -rf cmake-3.21.2
这里我们没有指定安装路径,默认是安装到了 /usr/local/bin路径。
root@zhengyang:/work/sambashare/tools# ll /usr/local/bin 总用量 47556 drwxr-xr-x 2 root root 4096 5月 7 13:45 ./ drwxr-xr-x 19 root root 4096 5月 7 13:48 ../ -rwxr-xr-x 1 root root 11319992 5月 7 13:45 ccmake* -rwxr-xr-x 1 root root 11589232 5月 7 13:45 cmake* -rwxr-xr-x 1 root root 12030672 5月 7 13:45 cpack* -rwxr-xr-x 1 root root 13098200 5月 7 13:45 ctest* -rwxr-xr-x 1 root root 230408 8月 27 2022 ffmpeg* -rwxr-xr-x 1 root root 123424 8月 27 2022 ffplay* -rwxr-xr-x 1 root root 139168 8月 27 2022 ffprobe* -rwxr-xr-x 1 root root 136720 8月 27 2022 ffserver* -rwxr-xr-x 1 root root 1568 8月 27 2022 sdl2-config*
1.4.2 tslib安装
要想Qt 支持触摸需要编译tslib ,以生成触摸相关插件。 tslib 多用于嵌入式系统中,是基本的触摸插件。在上一节linux设备树-LCD触摸屏设备驱动已经介绍了tslib的安装,这里不重复介绍了,当时我们将tslib安装到了ls /work/sambashare/drivers/tslib/tmp/路径下。
我们将其拷贝到/usr/local/tslib路径下:
root@zhengyang:/work/sambashare# ls drivers/tslib/tmp/ bin/ etc/ include/ lib/ share/ root@zhengyang:/work/sambashare# cp drivers/tslib/tmp/* /usr/local/tslib/ -rfd
1.4.3 Qt安装
接着回到qt安装目录:
root@zhengyang:/work/sambashare# cd tools/ qt-everywhere-opensource-src-5.0.0 root@zhengyang:/work/sambashare/tools/ qt-everywhere-opensource-src-5.0.0# sudo mkdir -p /usr/local/Qt5.12
接下来配置Qt, 在Qt的源码目录下有一个可执行程序 configure, 运行./configure --help 可以看到详细的配置选项。
为了操作方便,可以写一个脚本文件autoconfigure.sh,文容如下:
sudo ./configure -prefix /usr/local/Qt5.12 \\ -opensource \\ -confirm-license \\ -release \\ -strip \\ -shared \\ -xplatform linux-arm-gnueabi-g++ \\ -optimized-qmake \\ -c++std c++11 \\ --rpath=no \\ -pch \\ -skip qt3d \\ -skip qtactiveqt \\ -skip qtandroidextras \\ -skip qtcanvas3d \\ -skip qtconnectivity \\ -skip qtdatavis3d \\ -skip qtdoc \\ -skip qtgamepad \\ -skip qtlocation \\ -skip qtmacextras \\ -skip qtnetworkauth \\ -skip qtpurchasing \\ -skip qtremoteobjects \\ -skip qtscript \\ -skip qtscxml \\ -skip qtsensors \\ -skip qtspeech \\ -skip qtsvg \\ -skip qttools \\ -skip qttranslations \\ -skip qtwayland \\ -skip qtwebengine \\ -skip qtwebview \\ -skip qtwinextras \\ -skip qtx11extras \\ -skip qtxmlpatterns \\ -make libs \\ -make examples \\ -nomake tools -nomake tests \\ -gui \\ -widgets \\ -dbus-runtime \\ --glib=no \\ --pcre=qt \\ --zlib=qt \\ -no-openssl \\ --freetype=qt \\ --harfbuzz=qt \\ -no-opengl \\ -linuxfb \\ --xcb=no \\ -tslib \\ --libpng=qt \\ --libjpeg=qt \\ --sqlite=qt \\ -plugin-sql-sqlite \\ -I /usr/local/tslib/include \\ -L /usr/local/tslib/lib
-I和-L分别指定头文件目录和库目录,在安装tslib生成的目录tmp中,这里提前将tmp目录复制到/usr/local/tslib中。
赋予配置脚本autoconfigure.sh 可执行权限,然后执行
root@zhengyang:/work/sambashare/tools/ qt-everywhere-opensource-src-5.0.0# sudo apt-get install g++ #配置前请先安装g++,如已安装可忽略 root@zhengyang:/work/sambashare/tools/ qt-everywhere-opensource-src-5.0.0# chmod +x autoconfigure.sh root@zhengyang:/work/sambashare/tools/ qt-everywhere-opensource-src-5.0.0# ./autoconfigure.sh
配置脚本运行完成之后,就可以进行编译和安装了,大约需要十几到几十分钟:
root@zhengyang:/work/sambashare/tools/ qt-everywhere-opensource-src-5.0.0# make -j4 root@zhengyang:/work/sambashare/tools/ qt-everywhere-opensource-src-5.0.0# make install
二、根文件系统制作
三、QT应用程序测试
参考文章
正点原子I.MX6U-MINI移植篇kernel移植过程详解
一、下载Linux内核
这里使用NXP官方提供的Linux源码,将其移植到正点原子I.MX6U-MINI开发板上。NXP官方原版Liux源码路径为:1、例程源码->4、NXP官方原版Uboot和Linux->linux-imx-rel_imx4.1.15_2.1.0_ga.tar.bz2。
在ubunut中的/home/zhiguoxin/linux/IMX6ULL/目录下创建一个nxp_kernel文件夹用于存放NXP的内核。使用FileZilla将其发送到Ubuntu中并解压,得到名为linux-imx-rel_imx4.1.15_2.1.0_ga的目录。
cd /home/zhiguoxin/linux/IMX6ULL/
mkdir nxp_kernel
cd nxp_kernel
tar -vxjf linux-imx-rel_imx_4.1.15_2.1.0_ga.tar.bz2
二、NXP官方开发板Linux内核编译
NXP提供的Linux源码肯定是可以在自己的I.MX6ULL EVK开发板上运行下去的,所以我们肯定是以I.MX6 ULL EVK开发板为参考,然后将Linux内核移植到I.MX6U-ALPHA开发板上的。
2.1 修改顶层Makefile
修改顶层Makefile,直接在顶层Makefile文件里面定义ARCH和CROSS COMPILE这两个的变量值为arm
和arm-linux-gnueabihf-
,结果如图所示:
2.2 配置并编译Linux内核
在编译 Linux 内核之前要先配置 Linux 内核。每个板子都有其对应的默认配置文件,这 些默认配置文件保存 在 arch/arm/configs 目录中。
imx_v7_defconfig 和imx_v7_mfg_defconfig 都可作为 I.MX6ULL EVK 开发板所使用的默认配置文件。但是这里建议使用 imx_v7_mfg_defconfig 这个默认配置文件,首先此配置文件默认支持 I.MX6UL 这款芯片,而且重要的一点就是此文件编译出来的 zImage 可以通过 NXP 官方提供的 MfgTool 工具烧写!!imx_v7_mfg_defconfig 中的“mfg”的意思就是 MfgTool。
进入到 Ubuntu 中的 Linux 源码根目录下,执行如下命令配置 Linux 内核:
make clean //第一次编译 Linux 内核之前先清理一下
make imx_v7_mfg_defconfig //配置 Linux 内核
配置完成以后就可以编译了,使用如下命令编译 Linux 内核:
make -j16 //编译 Linux 内核
等待编译完成,结果如图所示:
Linux 内核编译完成以后会在arch/arm/boot 目录下生成zImage镜像文件,如果使用设备树的话还会在 arch/arm/boot/dts 目录下开发板对应的.dtb(设备树)文件,比如imx6ull-14x14-evk.dtb就是 NXP 官方的I.MX6ULL EVK开发板对应的设备树文件。至此我们得到两个文件:
- ①、Linux内核镜像文件:zImage。
- ②、NXP官方 I.MX6ULL EVK开发板对应的设备树文件:imx6ull-14x14-evk.dtb。
2.3 Linux内核启动测试
在上面已经得到了 NXP 官方I.MX6ULL EVK 开发板对应的 zImage和imx6ull-14x14-evk.dtb 这两个文件。这两个文件能不能在正点原子的 I.MX6U-ALPHA EMMC 版开发板上启动呢?测试一下不就知道了。
在测试之前确保 uboot 中的环境变量bootargs内容如下:
console=ttymxc0,115200 root=/dev/mmcblk1p2 rootwait rw
使用命令
setenv bootargs 'console=ttymxc0,115200 root=/dev/mmcblk1p2 rootwait rw'
saveenv
将上一小节编译出来的zImage和imx6ull-14x14-evk.dtb复制到Ubuntu 中的tftp目录下,因为我们要在 uboot 中使用 tftp 命令将其下载到开发板中,拷贝命令如下:
cp arch/arm/boot/zImage /home/zhiguoxin/linux/tftp -f
cp arch/arm/boot/dts/imx6ull-14x14-evk.dtb /home/zhiguoxin/linux/tftp -f
拷贝完成以后就可以测试了,启动开发板,进入uboot 命令行模式,然后输入如下命令将zImage 和 imx6ull-14x14-evk.dtb 下载到开发板中并启动:
tftp 80800000 zImage
tftp 83000000 imx6ull-14x14-evk.dtb
bootz 80800000 - 83000000
可以看出,此时Linux内核已经启动了。
三、在Linux中添加自己的开发板
通过编译NXP官方I.MX6ULL EVK 开发板对应的Linux内核,发现其可以在正点原子的EMMC版本开发板启动,所以我们就参考I.MX6ULL EVK开发板的设置,在Linux内核中添加正点原子的I.MX6U-ALPHA开发板。
3.1 添加开发板默认配置文件 件
将 arch/arm/configs目录下的imx_v7_mfg_defconfig重新复制一份 , 命名 为imx_alientek_emmc_defconfig,命令如下:
cd arch/arm/configs
cp imx_v7_mfg_defconfig imx_alientek_emmc_defconfig
以后imx_alientek_emmc_defconfig就是正点原子的EMMC版开发板默认配置文件了。完成以后如图所示:
以后就可以使用如下命令来配置正点原子EMMC版开发板对应的Linux内核了:
make imx_alientek_emmc_defconfig
3.2 添加开发板对应的设备树文件
添加适合正点原子 EMMC 版开发板的设备树文件,进入目录 arch/arm/boot/dts 中,复制一份 imx6ull-14x14-evk.dts,然后将其重命名为 imx6ull-alientek-emmc.dts,命令如下:
cd arch/arm/boot/dts
cp imx6ull-14x14-evk.dts imx6ull-alientek-emmc.dts
.dts是设备树源码文件,编译Linux的时候会将其编译为.dtb文件。imx6ull-alientek-emmc.dts创建好以后我们还需要修改文件arch/arm/boot/dts/Makefile, 找 到 “dtb-$(CONFIG_SOC_IMX6ULL)”配置项,在此配置项中加入“imx6ull-alientek-emmc.dtb” ,如下所示:
第422行为“imx6ull-alientek-emmc.dtb”,这样编译Linux 的时候就可以从 imx6ull-alientek-emmc.dts编译出 imx6ull-alientek-emmc.dtb文件了。
3.3 编译测试
创建一个编译脚本,imx6ull_alientek_emmc.sh,脚本内容如下:
touch imx6ull_alientek_emmc.sh
#!/bin/sh
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- distclean
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- imx_alientek_emmc_defconfig
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- menuconfig
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- all -j16
- 第2行,清理工程。
- 第3行,使用默认配置文件imx_alientek_emmc_defconfig来配置Linux内核。
- 第4行,打开Linux的图形配置界面,如果不需要每次都打开图形配置界面可以删除此行。
- 第5行,编译Linux。
执行shell脚本 imx6ull_alientek_emmc.sh编译Linux内核,命令如下:
chmod 777 imx6ull_alientek_emmc.sh //给予可执行权限
./imx6ull_alientek_emmc.sh //执行 shell 脚本编译内核
编译完成以后就会在目录arch/arm/boot下生成zImage镜像文件。在arch/arm/boot/dts目录下生成 imx6ull-alientek-emmc.dtb文件。将这两个文件拷贝到tftp目录下,
cp arch/arm/boot/zImage /home/zhiguoxin/linux/tftp -f
cp arch/arm/boot/dts/imx6ull-14x14-evk.dtb /home/zhiguoxin/linux/tftp -f
然后重启开发板,在uboot命令模式中使用tftp命令下载这两个文件并启动,命令如下:
tftp 80800000 zImage
tftp 83000000 imx6ull-alientek-emmc.dtb
bootz 80800000 – 83000000
只要出现如图 所示内容就表示 Linux 内核启动成功:
Linux内核启动成功,说明我们已经在NXP提供的 Linux内核源码中添加了正点原子I.MX6UL-MINI开发板。
四、CPU主频和网络驱动修改
4.1 CPU主频修改
正点原子I.MX6U-MINI开发板所使用的 I.MX6ULL 芯片主频都是792MHz 的,也就是NXP官方宣传的800MHz版本。
1 、设置 I.MX6U-MINI开发板工作在792MHz
确保EMMC中的根文件系统可用!然后重新启动开发板,进入终端(可以输入命令),输入如下命令查看cpu信息:
cat /proc/cpuinfo
结果如图所示:
在图中有BogoMIPS这一条,此时 BogoMIIS 为 3.00,BogoMIPS是Linux 系统中衡量处理器运行速度的一个“尺子”,处理器性能越强,主频越高,BogoMIPS 值就越大。
BogoMIPS只是粗略的计算CPU性能,并不十分准确。但是我们可以通过 BogoMIPS 值来大致的判断当前处理器的性能。在图中并没有看到当前 CPU 的工作频率,那我们就转变另一种方法查看当前CPU的工作频率。
进入到目录/sys/bus/cpu/devices/cpu0/cpufreq中,此目录下会有很多文件,使用如下命令查看当前CPU频率:
cd /sys/bus/cpu/devices/cpu0/cpufreq
cat cpuinfo_cur_freq
4.2 使能8线EMMC驱动
正点原子EMMC版本核心板上的EMMC 采用的8位数据线,原理图如图所示:
Linux内核驱动里面 EMMC默是4线模式的,4线模式肯定没有8线模式的速度快,所以本节我们将EMMC的驱动修改为8线模式。
修改方法很简单,直接修改设备树即可,打开文件 imx6ull-alientek-emmc.dts,找到如下所示内容:
cd arch/arm/boot/dts
vi imx6ull-alientek-emmc.dts
&usdhc2
pinctrl-names = "default", "state_100mhz", "state_200mhz";
pinctrl-0 = <&pinctrl_usdhc2_8bit>;
pinctrl-1 = <&pinctrl_usdhc2_8bit_100mhz>;
pinctrl-2 = <&pinctrl_usdhc2_8bit_200mhz>;
bus-width = <8>;
non-removable;
status = "okay";
;
修改完成以后保存一下 imx6ull-alientek-emmc.dts,然后使用命令make dtbs
重新编译一下设备树,编译完成以后使用新的设备树重启Linux 系统即可。
4.3 修改网络驱动
因为在后面学习Linux驱动开发的时候要用到网络调试驱动,所以必须要把网络驱动调试好。在讲解uboot移植的时候就已经说过了,正点原子开发板的网络和NXP官方的网络硬件上不同,网络PHY芯片由KSZ8081换为了 LAN8720A,两个网络 PHY芯片的复位IO也不同。所以Linux内核自带的网络驱动是驱动不起来I.MX6U-MINI开发板上的网络的,需要做修改。
4.3.1 修改LAN8720的复位以及网络时钟引脚驱动
ENET1复位引脚ENET1_RST连接在 I.M6ULL的SNVS_TAMPER7这个引脚上。ENET2的复位引脚 ENET2_RST 连接在I.MX6ULL 的SNVS_TAMPER8上。打开设备树文件imx6ull-alientek-emmc.dts,找到如下代码:
将 588 和 589 这两行删除掉!
删除掉以后继续在 imx6ull-alientek-emmc.dts 中找到如下所示代码,将示例代码中的第 129 行和第 133 行处的代码删除掉!!否则会干扰到网络复位引脚!
在 imx6ull-alientek-emmc.dts 里面找到名为“iomuxc_snvs”的节点(就是直接搜索),然后在此节点下添加网络复位引脚信息,添加完成以后的“iomuxc_snvs”的节点内容如下:
/*enet1 reset zhiguoxin*/
pinctrl_enet1_reset: enet1resetgrp
fsl,pins = <
/* used for enet1 reset */
MX6ULL_PAD_SNVS_TAMPER7__GPIO5_IO07 0x10B0
>;
;
/*enet2 reset zhiguoxin*/
pinctrl_enet2_reset: enet2resetgrp
fsl,pins = <
/* used for enet2 reset */
MX6ULL_PAD_SNVS_TAMPER8__GPIO5_IO08 0x10B0
>;
;
第 1 行,imx6ull-alientek-emmc.dts 文件中 iomuxc_snvs 节点。
第 559~600 行,ENET1 网络复位引脚配置信息。
第 603~608 行,ENET2 网络复位引脚配置信息。
最后还需要修改一下 ENET1 和 ENET2 的网络时钟引脚配置,继续在 imx6ull-alientek-emmc.dts 中找到如下所示代码
第 316和 331行,分别为 ENET1 和 ENET2 的网络时钟引脚配置信息,将这两个引脚的电气属性值改为0x4001b009,原来默认值为 0x4001b031。
修改完成以后记得保存一下 imx6ull-alientek-emmc.dts,网络复位以及时钟引脚驱动就修改好了。
4.3.2 修改fec1和fec2节点的pinctrl-0属性
在 imx6ull-alientek-emmc.dts 文件中找到名为“fec1”和“fec2”的这两个节点,修改其中的“pinctrl-0”属性值,修改以后如下所示:
4.3.3 修改LAN8720A的PHY地址
我们说过ENET1的LAN8720A地址为0x0,ENET2的LAN8720A地址为0x1。在 imx6ull-alientek-emmc.dts中找到如下代码:
- 第 171 和 172 行,添加了 ENET1 网络复位引脚所使用的IO为GPIO5_IO07,低电平有效。复位低电平信号持续时间为 200ms。
- 第 180 和 181 行,ENET2 网络复位引脚所使用的 IO 为 GPIO5_IO08,同样低电平有效,持续时间同样为 200ms。
- 第 191 和 197 行,“smsc,disable-energy-detect”表明 PHY 芯片是 SMSC 公司的,这样 Linux内核就会找到 SMSC 公司的 PHY 芯片驱动来驱动 LAN8720A。
- 第 190 行,注意“ethernet-phy@”后面的数字是 PHY 的地址,ENET1 的 PHY 地址为 0,所以“@”后面是 0(默认为 2)。
- 第 193 行,reg 的值也表示 PHY 地址,ENET1 的 PHY 地址为 0,所以 reg=0。
- 第 196 行,ENET2 的 PHY 地址为 1,因此“@”后面为 1。
- 第 199 行,因为 ENET2 的 PHY 地址为 1,所以 reg=1。
至此,LAN8720A 的 PHY 地址就改好了,保存一下 imx6ull-alientek-emmc.dts 文件。然后使用“make dtbs”命令重新编译一下设备树。
4.3.4 修改fec_main.c文件
要在I.MX6ULL上使用LAN8720A, 需要修改一下Linux内核源码 ,打开
drivers/net/ethernet/freescale/fec_main.c,找到函数fec_probe,在 fec_probe中加入如下代码:
cd drivers/net/ethernet/freescale
vi fec_main.c
/* 设置 MX6UL_PAD_ENET1_TX_CLK 和 MX6UL_PAD_ENET2_TX_CLK
* 这两个 IO 的复用寄存器的 SION 位为 1。
*/
void __iomem *IMX6U_ENET1_TX_CLK;
void __iomem *IMX6U_ENET2_TX_CLK;
IMX6U_ENET1_TX_CLK = ioremap(0X020E00DC, 4);
writel(0X14, IMX6U_ENET1_TX_CLK);
IMX6U_ENET2_TX_CLK = ioremap(0X020E00FC, 4);
writel(0X14, IMX6U_ENET2_TX_CLK);
第 3455~3462 就是新加入的代码,如果要在 I.MX6ULL 上使用 LAN8720A 就需要设置ENET1 和 ENET2 的 TX_CLK 引脚复位寄存器的 SION 位为1。
4.4.5 配置Linux内核,使能LAN8720驱动
输入命令“make menuconfig”,打开图形化配置界面,选择使能 LAN8720A 的驱动,路径如下:
-> Device Drivers
-> Network device support
-> PHY Device support and infrastructure
-> Drivers for SMSC PHYs
选择将Drivers for SMSC PHYs
编译到Linux内核中,因此<>
里面变为了*
。LAN8720A是SMSC公司出品的,因此勾选这个以后就会编译LAN8720驱动,配置好以后退出配置界面,然后重新编译一下Linux内核。
4.4.6 修改 smsc.c文件
在修改 smsc.c 文件之前先说点题外话,那就是我是怎么确定要修改 smsc.c 这个文件的。在写本书之前我并没有修改过 smsc.c 这个文件,都是使能 LAN8720A 驱动以后就直接使用。
但是我在测试 NFS 挂载文件系统的时候发现文件系统挂载成功率很低!老是提示NFS服务器找不到,三四次就有一次挂载失败!很折磨人。NFS 挂载就是通过网络来挂载文件系统,这样做的好处就是方便我们后续调试 Linux驱动。既然老是挂载失败那么可以肯定的是网络驱动有问题,网络驱动分两部分:内部MAC+外部 PHY,内部MAC驱动是由NXP提供的,一般不会出问题,否则的话用户早就给NXP反馈了。而且我用NXP官方的开发板测试网络是一直正常的,但是NXP官方的开发板所使用的PHY芯片为 KSZ8081。所以只有可能是外部PHY,也就是LAN8720A 的驱动可能出问题了。
鉴于LAN8720A 有“前车之鉴”,那就是在 uboot 中需要对LAN8720A 进行一次软复位,要设置 LAN8720A 的 BMCR(寄存器地址为 0)寄存器 bit15 为 1。所以我猜测,在 Linux 中也需要对 LAN8720A 进行一次软复位。
首先需要找到 LAN8720A 的驱动文件,LAN8720A 的驱动文件是 drivers/net/phy/smsc.c,在此文件中有个叫做 smsc_phy_reset 的函数,看名字都知道这是 SMSC PHY 的复位函数,因此,LAN8720A 肯定也会使用到这个复位函数,修改此函数的内容,修改以后的 smsc_phy_reset函数内容如下所示:
cd drivers/net/phy
vi smsc.c
static int smsc_phy_reset(struct phy_device *phydev)
int err, phy_reset;
int msec = 1;
struct device_node *np;
int timeout = 50000;
if(phydev->addr == 0) /* FEC1 */
np = of_find_node_by_path("/soc/aips-bus@02100000/ethernet@188000");
if(np == NULL)
return -EINVAL;
if(phydev->addr == 1) /* FEC2 */
np = of_find_node_by_path("/soc/aips-bus@02000000/ethernet@0b4000");
if(np == NULL)
return -EINVAL;
err = of_property_read_u32(np, "phy-reset-duration", &msec);
/* A sane reset duration should not be longer than 1s */
if (!err && msec > 1000)
msec = 1;
phy_reset = of_get_named_gpio(np, "phy-reset-gpios", 0);
if (!gpio_is_valid(phy_reset))
return;
gpio_direction_output(phy_reset, 0);
gpio_set_value(phy_reset, 0);
msleep(msec);
gpio_set_value(phy_reset, 1);
int rc = phy_read(phydev, MII_LAN83C185_SPECIAL_MODES);
if (rc < 0)
return rc;
/* If the SMSC PHY is in power down mode, then set it
* in all capable mode before using it.
*/
if ((rc & MII_LAN83C185_MODE_MASK) ==
MII_LAN83C185_MODE_POWERDOWN)
/* set "all capable" mode and reset the phy */
rc |= MII_LAN83C185_MODE_ALL;
phy_write(phydev, MII_LAN83C185_SPECIAL_MODES, rc);
phy_write(phydev, MII_BMCR, BMCR_RESET);
/* wait end of reset (max 500 ms) */
do
udelay(10);
if (timeout-- == 0)
return -1;
rc = phy_read(phydev, MII_BMCR);
while (rc & BMCR_RESET);
return 0;
最后我们还需要在 drivers/net/phy/smsc.c 文件中添加两个头文件,因为修改后的smsc_phy_reset 函数用到了 gpio_direction_output 和gpio_set_value这两个函数,需要添加的头文件如下所示:
#include <linux/of_gpio.h>
#include <linux/io.h>
以上是关于linux GUI-QT6.5移植到Mini2440的主要内容,如果未能解决你的问题,请参考以下文章
正点原子I.MX6U-MINI移植篇kernel移植过程详解
DM9000驱动移植在mini2440(linux2.6.29)和FS4412(linux3.14.78)上的实现(deep dive)篇一