【移植03】修改移植`FSL Yocto Project Community BSP`用到的Linux内核源码并增加触摸屏、蓝牙、wifi的驱动程序,使其能适配百问网(100ask)的开发板

目录

前言

本篇博文承接我的上一篇博文 https://blog.youkuaiyun.com/wenhao_ir/article/details/145662136

上一篇博文中已经实现u-boot的成功移植了,这篇博文就继续移植Linux内核。

获取FSL Yocto Project Community BSP使用的Linux内核源码

根据上一篇博文 https://blog.youkuaiyun.com/wenhao_ir/article/details/145662136 的经验,官方的git仓库已经不能用了,那就只用用百问网当时保存在那里的了。

百度网盘下载地址:
https://pan.baidu.com/s/1Y-Wz69K9tsWFxTTdhZWV_g?pwd=n79q
注意:文件有点大…4.04GB呢…

下载好后如下图所示:
在这里插入图片描述

##内核源码复制到Ubuntu中并解压
首先检查自己的交叉编译器是否配置好了,如果没有弄好,按照博文 https://blog.youkuaiyun.com/wenhao_ir/article/details/145649698去配置安装。

当然,因为我前面在编译构建u-boot时已经使用过了,所以肯定是没有问题的了。

把之前下载好的源码压缩包linux-imx.tar.gz复制到Ubuntu中。
在这里插入图片描述
然后解压,解压是需要点时间的,因为压缩文件有4.04GB嘛,解压出来后如下图所示:
在这里插入图片描述

配置内核

执行下面的命令来配置内核

make imx_v7_defconfig

因为IMX6ULL是Cortex-A7架构的处理器,所以上面的名字中是v7
在这里插入图片描述

运行结果如下:
在这里插入图片描述

编译构建生成内核镜像文件zImage

运行下面的命令进行构建编译内核镜像文件(zImage)

make zImage -j4

当然,如果处理器的资源够多,可以用8线程加快构建速度,即把-j4改为-j8
在这里插入图片描述
运行时间和结果如下:
起始时间: 2025-02-24 13:47:12
结束时间:2025-02-24 13:54:41
在这里插入图片描述
根据上图的运行结果,我们知道生成的zImage镜像文件位于目录/arch/arm/boot中,如下图所示:
在这里插入图片描述

编译生成设备树文件(dtb文件)

承接上一步,继续编译生成设备树文件。
执行下面的命令生成设备树文件:

make dtbs

在这里插入图片描述
运行结果如下(1分钟左右就完成了):
在这里插入图片描述
在目录/arch/arm/boot/dts下生成了所有设备树文件(dts文件)的二进制文件(dtb文件),我们需要的dts文件和对应生成的dtb文件如下面的截图如示:
在这里插入图片描述
注意:我们要的设备树文件的名字中是im6ull,而不是im6ul,它们的区别是前者的末尾是两个l,而后者的末尾是一个l,我们要的是名字中含两个l的。

即我们要的文件是imx6ull-14x14-evk.dts和文件imx6ull-14x14-evk.dtb

注意:下面这幅图中的两个文件不是我们要的文件:
在这里插入图片描述

这样,我们就测试了编译生成设备树文件(dtb文件)是没有问题的,接下来我们就可以修改dts设备树文件了,使其能适应我们的开发板。

修改设备树文件imx6ul-14x14-evk.dts

复制并重命名百问网提供的设备树文件

上一步中我们测试了编译生成设备树文件(dtb文件)是没有问题的,接下来我们就可以修改dts设备树文件了,使其能适应我们的开发板。

先把上一步末尾中提到的文件imx6ull-14x14-evk.dts和文件imx6ull-14x14-evk.dtb分别改名为:
imx6ull-14x14-evk.dts.bak0
imx6ull-14x14-evk.dtb.bak0
在这里插入图片描述

然后把百问网提供的位于目录/home/book/100ask_imx6ull-sdk/Linux-4.9.88/arch/arm/boot/dts中的设备树文件100ask_imx6ull-14x14.dts复制到目录/home/book/mybuild/Linux-BSP_raw/linux-imx/arch/arm/boot/dts中,并重命名为:imx6ull-14x14-evk.dts

在这里插入图片描述

然后我们尝试编译生成生dtb文件,肯定有错误,运行下面的命令进行编译:

make dtbs

运行结果如下:
在这里插入图片描述

book@100ask:~/mybuild/Linux-BSP_raw/linux-imx$ make dtbs
  DTC     arch/arm/boot/dts/imx6ull-14x14-evk.dtb
Error: arch/arm/boot/dts/imx6ull-14x14-evk.dts:234.1-10 Label or path flexcan1 not found
FATAL ERROR: Syntax error parsing input tree
scripts/Makefile.lib:285: recipe for target 'arch/arm/boot/dts/imx6ull-14x14-evk.dtb' failed
make[1]: *** [arch/arm/boot/dts/imx6ull-14x14-evk.dtb] Error 1
Makefile:1250: recipe for target 'dtbs' failed
make: *** [dtbs] Error 2

错误的原因提取如下:

Error: arch/arm/boot/dts/imx6ull-14x14-evk.dts:234.1-10 Label or path flexcan1 not found

这个错误提示表明设备树文件(imx6ull-14x14-evk.dts)中第234行出现了一个问题,具体是“flexcan1标签或路径未找到”。从错误信息看,可能是设备树的某个部分引用了flexcan1,但设备树中并没有定义或正确引用这个节点。

与标签flexcan1有关的错误修改

我们不妨去看下这个设备树文件imx6ull-14x14-evk.dts的234行:
这里先说明一下,这个设备树文件imx6ull-14x14-evk.dts其实就是100ask_imx6ull-14x14.dts,通过前面的操作,我们知道只是100ask_imx6ull-14x14.dts重命名为imx6ull-14x14-evk.dts而已。

不妨用Vscode来查看。

文件imx6ull-14x14-evk.dts的234行左右的内容如下:
在这里插入图片描述
可见这是一个对标签名为flexcan1的节点的引用,关于标签名和引用的详情,见我的另一篇博文 https://blog.youkuaiyun.com/wenhao_ir/article/details/145060032

这应该是与CAN设备节点有关,我们不妨去查看下公板提供的内核里的设备树文件里是怎么描述CAN设备节点的。

我们打开公板提供的内核里的设备树文件imx6ull-14x14-evk.dts.bak0【后面的bak0是我重命名的】,发现内容如下:

// SPDX-License-Identifier: (GPL-2.0 OR MIT)
//
// Copyright (C) 2016 Freescale Semiconductor, Inc.

/dts-v1/;

#include "imx6ull.dtsi"
#include "imx6ul-14x14-evk.dtsi"

/ {
	model = "Freescale i.MX6 ULL 14x14 EVK Board";
	compatible = "fsl,imx6ull-14x14-evk", "fsl,imx6ull";
};

&clks {
	assigned-clocks = <&clks IMX6UL_CLK_PLL3_PFD2>,
			  <&clks IMX6UL_CLK_PLL4_AUDIO_DIV>;
	assigned-clock-rates = <320000000>, <786432000>;
};

&csi {
	status = "okay";
};

&ov5640 {
	status = "okay";
};

/delete-node/ &sim2;

在这里插入图片描述
可见它包含了两个了设备树文件,名字分别为imx6ull.dtsiimx6ul-14x14-evk.dtsi

这里要说明下,我在博文 https://blog.youkuaiyun.com/wenhao_ir/article/details/145060032 中已经说明了:当设备树文件通过 #include 引入其他 dtsi 文件时,dtsi 文件中的内容会被嵌入到主文件中,但不会定义新的根节点,这些嵌入的内容通常作为子节点或并列节点加入现有的设备树结构。

所以我们不妨先去文件imx6ull.dtsi中搜索下关键词can1,看下有没有相关的设备节点:
搜索的结果为没有结果,也就是说在文件imx6ull.dtsi中没有搜索到关键词can1

然后再去文件imx6ul-14x14-evk.dtsi中搜索关键词can1,看下有没有相关的设备节点:
这就有了:
在这里插入图片描述
可见在公板提供的内核里的设备树文件中,对应的CAN设备的标签名为can1,我们不妨再去查看标签名can1的定义处,我们继续在文件imx6ul-14x14-evk.dtsi中搜索关键词can1:,看下在文件imx6ul-14x14-evk.dtsi中是否定义了标签can1,结果没有相关的结果。

那我们就只有去看文件imx6ul-14x14-evk.dtsi通过include包括的文件,很遗憾的是文件imx6ul-14x14-evk.dtsi并没有包含另外的设备树文件。
但是文件imx6ull.dtsi中有包含的另外的设备树文件啊:
在这里插入图片描述

#include "imx6ul.dtsi"
#include "imx6ull-pinfunc.h"
#include "imx6ull-pinfunc-snvs.h"

所以我们现在去文件imx6ul.dtsi中搜索关键词can1:,看有没有标签can1的定义,这就有了,如下图所示:
在这里插入图片描述
可见在公板提供的内核里的设备树文件中,对应的CAN1设备的标签名为can1,节点名为flexcan@2090000

总结一下:在公板提供的内核里的设备树文件中,对于设备CAN1的描述结构情况如下:

顶层设备设备树文件imx6ull-14x14-evk.dts.bak0【后面的bak0是我重命名的】中包含了两个设备树文件,分别如下:

#include "imx6ull.dtsi"
#include "imx6ul-14x14-evk.dtsi"

在文件imx6ull.dtsi中又包含了另一个设备树文件,如下:

#include "imx6ul.dtsi"

在设备树文件imx6ul.dtsi中定义了标签名为can1、节点名为flexcan@2090000的节点,用来描述设备CAN1,如下图所示:
在这里插入图片描述
而在设备树文件imx6ul-14x14-evk.dtsi中有对标签can1代表的节点的引用,截图如下:
在这里插入图片描述

百问网提供的内核的设备树文件与公板提供的内核的设备树文件的主要区别如下:
①百问网提供的设备树文件把公板提供的设备树文件imx6ul-14x14-evk.dtsi的内容直接写在了文件imx6ull-14x14-evk.dts中,所以百问网提供的设备树文件不需要文件imx6ull-14x14-evk.dts
②百问网提供的设备树文件对CAN1这个设备描述的节点的标签名为flexcan1,而公板提供的设备树文件对CAN1这个设备描述的节点的标签名为can1
③公板中的设备文件没有引用头文件 #include <dt-bindings/input/input.h>,而百问网引用了这个文件,相关截图如下:
在这里插入图片描述
在这里插入图片描述

对于上面第①点和第②点的区别,我们作如下修改:
imx6ull-14x14-evk.dts(其实是100ask_imx6ull-14x14.dts)作如下修改:

&flexcan1 {
    pinctrl-names = "default";
    pinctrl-0 = <&pinctrl_flexcan1>;
    xceiver-supply = <&reg_can_3v3>;
    status = "okay";
};

在这里插入图片描述
改为:

&can1 {
    pinctrl-names = "default";
    pinctrl-0 = <&pinctrl_flexcan1>;
    xceiver-supply = <&reg_can_3v3>;
    status = "okay";
};

在这里插入图片描述
对于第③点,我们首先要了解清楚头文件 #include <dt-bindings/input/input.h>的作用是什么,先查看下它的代码,如下:
在这里插入图片描述
在这里插入图片描述

/* SPDX-License-Identifier: GPL-2.0 */
/*
 * This header provides constants for most input bindings.
 *
 * Most input bindings include key code, matrix key code format.
 * In most cases, key code and matrix key code format uses
 * the standard values/macro defined in this header.
 */

#ifndef _DT_BINDINGS_INPUT_INPUT_H
#define _DT_BINDINGS_INPUT_INPUT_H

#include "linux-event-codes.h"

#define MATRIX_KEY(row, col, code)	\
	((((row) & 0xFF) << 24) | (((col) & 0xFF) << 16) | ((code) & 0xFFFF))

#define FT5416		0x54160002
#define FT5426		0x54260002

#endif /* _DT_BINDINGS_INPUT_INPUT_H */

这个文件 dt-bindings/input/input.h 是 Linux 内核中的设备树绑定文件,它定义了与输入设备相关的一些常量、宏和结构,主要用于设备树(Device Tree)配置中的输入设备部分。它提供了设备树节点中与输入设备相关的配置项,允许内核和设备驱动程序正确地理解和处理输入设备的配置。

具体来说,文件中包含了以下内容:

  1. 包含 linux-event-codes.h

    • linux-event-codes.h 是 Linux 内核中的一个头文件,它定义了事件代码(event codes),例如按键的扫描码、触摸屏的坐标等。这个文件通常与输入设备(如键盘、触摸屏)相关,用于描述不同的输入事件。
  2. MATRIX_KEY(row, col, code)

    • 这个宏用于定义矩阵键盘中的按键代码,参数包括 row(行)、col(列)和 code(按键的事件代码)。它通过按位运算将这些值组合成一个 32 位的整数,这个整数用于标识具体的按键。在设备树中,矩阵键盘通常会根据行列的组合来映射每个按键,因此这个宏可以方便地生成对应的按键值。

    例如:

    MATRIX_KEY(2, 3, KEY_A);
    

    这会生成一个唯一的键值,表示矩阵键盘第二行第三列的 “A” 键。

  3. 常量 FT5416FT5426

    • 这两个常量是触摸屏控制器的设备 ID。FT5416FT5426 都是 FocalTech 公司生产的触摸屏控制器型号,用于在设备树中指定特定的触摸屏设备。例如,设备树中的节点可能会使用这些 ID 来识别设备类型,进而加载相应的驱动。

文件 input.h 的作用总结:
dt-bindings/input/input.h 的主要作用是为设备树中与输入设备相关的配置提供常量和宏定义,确保内核和设备驱动可以正确解析设备树中的输入设备配置。例如,它为矩阵键盘、触摸屏等输入设备的配置提供了标准的编码方式,并定义了常见的输入设备标识符(如触摸屏控制器型号)。

由此可见,这个头文件保留就行,即使设备树文件没有用到它,也没什么要紧的。

所以总结一下,在这里我们只需把设备树文件imx6ull-14x14-evk.dts其实就是100ask_imx6ull-14x14.dts的第234行中的flexcan1改为can1即可,其它的不需要作任何修改。
在这里插入图片描述
改好之后我们再次运行下面的命令编译设备树文件:

make dtbs

在这里插入图片描述
运行情况如下:
在这里插入图片描述

book@100ask:~/mybuild/Linux-BSP_raw/linux-imx$ make dtbs
  DTC     arch/arm/boot/dts/imx6ull-14x14-evk-emmc.dtb
  DTC     arch/arm/boot/dts/imx6ull-14x14-evk-btwifi.dtb
Error: arch/arm/boot/dts/imx6ul-evk-btwifi.dtsi:40.1-14 Label or path reg_sd1_vmmc not found
FATAL ERROR: Syntax error parsing input tree
scripts/Makefile.lib:285: recipe for target 'arch/arm/boot/dts/imx6ull-14x14-evk-btwifi.dtb' failed
make[1]: *** [arch/arm/boot/dts/imx6ull-14x14-evk-btwifi.dtb] Error 1
Makefile:1250: recipe for target 'dtbs' failed
make: *** [dtbs] Error 2

错误原因提取如下:

Error: arch/arm/boot/dts/imx6ul-evk-btwifi.dtsi:40.1-14 Label or path reg_sd1_vmmc not found
FATAL ERROR: Syntax error parsing input tree

可见,发生错误的设备树文件imx6ul-evk-btwifi.dtsi,这说明设备树文件imx6ul-evk-btwifi.dtsi是用到了设备树文件imx6ull-14x14-evk.dts的,那是怎么个用到法的呢?

首先打开设备树文件imx6ul-evk-btwifi.dtsi发现它并没有包含文件imx6ull-14x14-evk.dts,如下图所示:
在这里插入图片描述
那我们不妨用全文搜索工具去搜索后缀名为dts的文件,找出那些含有下面这个关键词的dts文件:

"imx6ul-evk-btwifi.dtsi"

在这里插入图片描述
上面的搜索结果中最有可能与我们进行修改了的文件imx6ull-14x14-evk.dts有关的就是imx6ull-14x14-evk-btwifi.dts,我们打开imx6ull-14x14-evk-btwifi.dts看一下:
发现它果然引用了设备树文件imx6ull-14x14-evk.dts
在这里插入图片描述
但是,我们的目标并不是要生成imx6ull-14x14-evk-btwifi.dtb文件,所以这个错误其实我们可以不管。

如果觉得别扭的话可以修改Makefile文件把这个编译项去掉,具体是下面这个Makefile文件:

/home/book/mybuild/Linux-BSP_raw/linux-imx/arch/arm/boot/dts

在这里插入图片描述
打开之后搜索关键词imx6ull-14x14-evk-btwifi.dtb
在这里插入图片描述
找到之后注释掉它:
在这里插入图片描述
然后再试着编译:

make dtbs

在这里插入图片描述
这下就没有任何问题了,同也生成了我们想要的设备树二进制文件:imx6ull-14x14-evk.dtb,时间上也是吻合的:
在这里插入图片描述
在这里插入图片描述

设备树文件中关于以太网设备的描述的说明

在博文 https://blog.youkuaiyun.com/wenhao_ir/article/details/145662136 中我们花了很大的力气去让u-boot能驱动以太网2,其中最重要的修改之一就是对u-boot的设备树文件进行了修改,那我们不妨这里也看一看百问网提供的设备树文件100ask_imx6ull-14x14.dts中对以太网设备的描述是怎么样的,如下图所示:
在这里插入图片描述
可见基本与u-boot中对以太网的设备的描述是相同的,在u-boot中,我们只启用了以太网2,而没有启用以太网1,但是在Linux内核中,两个以太网设备都是启用的。并且从后面内核的运行情况来看,公板提供的Linux内核的以太网驱动是能驱动两个以太网设备的,不像u-boot那样还需要作额外修改。

结论:u-boot和Linux的设备树文件可以互相参考

这里需要注意一个结论:即“u-boot和Linux内核的设备树文件在书写时是可以相互参考的”,关于这个结论的详细得出过程请参看我的另一篇博文 https://blog.youkuaiyun.com/wenhao_ir/article/details/145883906

将内核镜像和设备树文件放到TFTP目录中

将我们上面编译的内核镜像和设备树文件放到TFTP目录中。

TFTP的安装和配置见博文 https://blog.youkuaiyun.com/wenhao_ir/article/details/145850749

TFTP在u-boot下的测试见博文 https://blog.youkuaiyun.com/wenhao_ir/article/details/145814363

内核镜像位于下面的位置:
在这里插入图片描述
设备树文件位于下面的位置:
在这里插入图片描述
复制完成后目录/home/book/tftpboot的情况截图如下:
在这里插入图片描述

将根文件系统放到Ubuntu系统中并解压

在这一步中,将在博文 https://blog.youkuaiyun.com/wenhao_ir/article/details/145547974 中通过官方提供的BSP(FSL Yocto Project Community BSP)构建编译生成的根文件系统的压缩包文件imx-image-full-imx6ull14x14evk-20201209093926.rootfs.tar.bz2下载并复制到Ubuntu系统中并解压,从而得到根文件系统。我们后面会设置u-boot从网络启动Linux系统,到时候我们解压得到的根文件系统就以NFS网络文件的形式挂载到内核上去。

根文件系统的压缩包文件的百度网盘下载载地址:
https://pan.baidu.com/s/1NUnuC9dzBFS9oOC0EhjarQ?pwd=qcyz
在这里插入图片描述
解压之后得到的文件夹的截图如下:
在这里插入图片描述
文件名有点长,我们不妨重命名为nfs_linux_rootfs在这里插入图片描述
我们看下里面有哪些目录:
在这里插入图片描述
可见,这就是标准文件系统嘛,这样我们就得到了根文件系统。我们后面会设置u-boot从网络启动Linux系统,到时候我们解压得到的这个根文件系统就以NFS网络文件的形式挂载到内核上去。

到时候我们用下面这条命令在u-boot中设置NFS网络文件目录就行了:

setenv nfsroot /home/book/mybuild/nfs_linux_rootfs

关于为什么设置环境变量nfsroot能实现指定NFS网络文件系统的挂载目录,请参见我的另三篇博文:
https://blog.youkuaiyun.com/wenhao_ir/article/details/145901614
https://blog.youkuaiyun.com/wenhao_ir/article/details/145902134
https://blog.youkuaiyun.com/wenhao_ir/article/details/145883835

权限设置:将根文件目录中的所有子目录和文件的权限都设为777

这一步非常重要,我之前就是因为只把顶层目录设为了777,而没有把其子目录也设为777,导致挂载根文件系统时某些需要写权限的目录无法挂载,出现下面的错误:

[FAILED] Failed to mount POSIX Message Queue File System.
[FAILED] Failed to mount Kernel Debug File System.
[FAILED] Failed to mount Temporary Directory (/tmp).
[FAILED] Failed to mount FUSE Control File System.
[FAILED] Failed to mount Kernel Configuration File System.
[FAILED] Failed to start Remount Root and Kernel File Systems.
[FAILED] Failed to mount /var/volatile.

详情见博文 https://blog.youkuaiyun.com/wenhao_ir/article/details/145883835

说回来,这里用下面的命令将根文件目录中的所有子目录和文件的权限都设为777

sudo chmod -R 777 /home/book/mybuild/nfs_linux_rootfs

注意:其中的-R参数非常重要
注意:其中的-R参数非常重要
注意:其中的-R参数非常重要

【启动系统】设置好u-boot的相关环境变量,然后从网络启动Linux系统

首先按照博文 https://blog.youkuaiyun.com/wenhao_ir/article/details/145899568 的方法设置好路由器。

然后网线的连接状态如下:
在这里插入图片描述
在这里插入图片描述
确认Ubuntu系统启动了,这是为了保证有TFTP服务器和NFS服务器。

启动开发板,按任意键停止u-boot的自动载入进程:
在这里插入图片描述

运行下面的命令请确保Ubuntu中要挂载的NFS目录的所有子目录和文件的权限都设置为777了,具体的设置方法请在本篇博文中搜索“将根文件目录中的所有子目录和文件的权限都设为777”。

环境变量设置

运行下面的命令设置u-boot的环境变量:

setenv fdt_file imx6ull-14x14-evk.dtb
setenv ip_dyn no
setenv serverip 192.168.5.11
setenv ipaddr 192.168.5.9
setenv nfsroot /home/book/mybuild/nfs_linux_rootfs
setenv netargs 'setenv bootargs console=${console},${baudrate} root=/dev/nfs rw ip=dhcp nfsroot=${serverip}:${nfsroot},v3,tcp'

在这里插入图片描述
要想彻底理解上面各个设置的原理和作用,请参看我的另一篇博文,链接:
https://blog.youkuaiyun.com/wenhao_ir/article/details/145902134

事实上,以后如果遇到u-boot启动不了Linux内核的情况,你首先就是要去研究它的u-boot的环境变量,通过对u-boot的环境变量的研究,你可以了解你所使用的u-boot它启动内核的原理。

我这里只是简单的介绍下这里进行了设备的各环境变量的作用:

  • fdt_file:用于指定设备树文件的名字。
  • ip_dyn:配置当u-boot以网络方式启动内核时,是用动态IP的方式去配置好网络然后去读取设备树文件和内核镜像,还是用TFTP的方式去读取设备树文件和内核镜像,当选no的时候,是用TFTP的方式去读取设备树文件和内核镜像。
  • serverip:这是TFTP的服务器地址,同时也是NFS网络服务器的地址,当然你可以修改NFS网络服务器的地址,比如把环境变量netargs中的serverip改为serverip_nfs,这样二者的地址就区分开来了。
  • ipaddr:这是u-boot的网络的IP地址,注意不是内核的IP地址,内核的IP地址奖在内核启动过程中由DHCP协议分配。
  • nfsroot:这是要挂载的NFS的目录路径。
  • netargs:用于设置环境变量bootargs的内容,环境变量bootargs是u-boot向内核传递的参数,详情见 https://blog.youkuaiyun.com/wenhao_ir/article/details/145901614
  • 注意:不需要设置内核镜像的名字,因为内核镜像的名字已经有存在的环境变量设置了,详情见博文 https://blog.youkuaiyun.com/wenhao_ir/article/details/145902134【搜索“image=zImage”】

从网络启动的命令

设置好各环境变量后,接下来,就可以运行下面的命令从网络启动Linux系统了:

run netboot

在这里插入图片描述
启动过程中会有下面两个错误:

[FAILED] Failed to start Network Time Synchronization.
[FAILED] Failed to start Login Service.

关于这两个错误的详细解释见:
https://blog.youkuaiyun.com/wenhao_ir/article/details/145883835 【搜索“第1个错误是因为我的路由器”】
备注:后来通过eMMC启动系统时这两个错误都没有了,原因分析如下:
①第一个错误没有的原因:因为eMMC设备不带授时功能,自然系统就不会去尝试获取网络时间了呀;
②第二个错误没有的原因: systemd-logind 在网络启动模式下是启动不了的,通过eMMC启动的方式可以。

下面的启动信息表示网络配置成功,并成功挂载由NFS网络文件系统提供的根文件系统:
在这里插入图片描述

启动之后的串口终端截图如下:
在这里插入图片描述
按下Enter键出现用户登陆的命令行:
在这里插入图片描述
输入root登陆…
在这里插入图片描述
这样,系统就从网络启动起来了…
此时,LCD的显示如下:
在这里插入图片描述
字因为太小拍不清,我把字打出来如下:

NXP i.MX Release Distro 5.4-zeus imx6ull14x14evk tty1
imx6ull14x14evk login:

可见这个LCD上的终端的设备名字为tty1
再从前面的截图中,我们知道串口终端的设备名字为ttymxc0

由于我们是从网络启动的Linux,所以我们在移植内核心的过程中,如果重新修改生成了设备树、内核镜像,只需要改TFTP目录中的文件,然后重新加载就行了,就不用再去重新麻烦的烧写了。

接下来就可以开始移值各种外设的驱动了。

触摸屏驱动移植适配

官方文档里说经验证,触摸屏无法使用…
至于是怎么验证的,就不知道了…

不管那么多,反正知道了现在要去移植触摸屏驱动。

具体移植过程如下:

01-复制驱动源码到内核的相应目录

复制百问网提供的Linux4.9.88内核源码中的触摸屏驱动到咱们本次移植的Linux 5.4内核源码中。

即将路径/home/book/100ask_imx6ull-sdk/Linux-4.9.88/drivers/input/touchscreen/中的目录gt9xx复制到目录/home/book/mybuild/Linux-BSP_raw/linux-imx/drivers/input/touchscreen中:
在这里插入图片描述
在这里插入图片描述

02-编辑相应的Makefile文件

编辑文件:/home/book/mybuild/Linux-BSP_raw/linux-imx/drivers/input/touchscreen/Makefile
在这里插入图片描述
在其末尾加上下面的Makefile语句:

obj-$(CONFIG_TOUCHSCREEN_GT9XX)	+= gt9xx/

在这里插入图片描述
关于这条Makefile语句的详细解释见 https://blog.youkuaiyun.com/wenhao_ir/article/details/144556756 【搜索“CONFIG_TOUCHSCREEN_GT9XX”】,你要知道,最终obj-$(CONFIG_TOUCHSCREEN_GT9XX)会被展开为obj-yobj-m

03-编辑相应的Kconfig文件

编辑文件/home/book/mybuild/Linux-BSP_raw/linux-imx/drivers/input/touchscreen/Kconfig
在这里插入图片描述
在其中加上下面的source命令语句:

source "drivers/input/touchscreen/gt9xx/Kconfig"

关于source命令的详情,见我的另一篇博文:
https://blog.youkuaiyun.com/wenhao_ir/article/details/145589497

具体的添加位置如下图所示:
在这里插入图片描述

04-通过配置将驱动增加进内核中

终端进入内核目录:

cd /home/book/mybuild/Linux-BSP_raw/linux-imx

然后执行下面的命令进入配置界面:

make menuconfig

在这里插入图片描述
在这里插入图片描述
通过选择进入 Device Drivers --> Input device support --> Touchrscreens 详细的配置页面
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
把上面截图中的第1项“Goodix touchpanel GT9xx series”用空格选中:
在这里插入图片描述
然后移动到Save那里保存配置。
在这里插入图片描述
然后在弹出的确让界面中用Enter键点击OK按钮:
在这里插入图片描述
用Enter键点击OK按钮后,再在弹出来的界面中用Enter键点击Exit按钮返回到配置界面。
在这里插入图片描述
用Enter键点击上图中的Exit按钮后返回到配置界面:
在这里插入图片描述
再点击上图中的Exit按钮退出内核的配置界面,注意,要连续点击几次,一次一次地退出,最后退出后的终端界面如下:
在这里插入图片描述
如果这里想不用这个图形配置界面进行配置,也可以直接修改.config文件来配置,这个文件就在根目录中,但是直接看不到,可以用下面的命令打开:

gedit .config

打开之后在文件中增加下面几个配置就行了:

CONFIG_TOUCHSCREEN_GT9XX=y
CONFIG_TOUCHSCREEN_GT9XX_UPDATE=y
CONFIG_TOUCHSCREEN_GT9XX_TOOL=y

由于之前我已经通过图形界面来配置了,所以可以看到这几个配置项已经存在了,如下图所示:
在这里插入图片描述

05-重新编译内核镜像

执行编译内核镜像命令,来生成包含触摸屏驱动的内核镜像文件:

make zImage -j4

当然,如果处理器的资源够多,可以用8线程加快构建速度,即把-j4改为-j8
在这里插入图片描述
开始时间:2025-02-28 15:21:00
结束时间:2025-02-28 15:22:04
这次相比第一次编译内核(第一次编译用了8分多钟),就快很多了,原因是没有改动的部分不需要再进行编译。
在这里插入图片描述

06-复制新生成的镜像到TFTP目录中并重启系统

在这里插入图片描述
然后按本博文目录“设置好u-boot的相关环境变量,然后从网络启动Linux系统”中的方法重启内核。
在这里插入图片描述
在这里插入图片描述
启动后用root用户登陆:
在这里插入图片描述

07-测试触摸屏驱动是否成功加载并正常运行

系统启动后执行下面的命令来查看内核打印信息,看是否成功加载触摸屏驱动并识别出触摸屏芯片:

dmesg | grep "goodix-ts"
root@imx6ull14x14evk:~# dmesg | grep "goodix-ts"
[    2.421786] goodix-ts 1-005d: GTP Driver Version: V2.8.0.2<2017/12/14>
[    2.428468] goodix-ts 1-005d: GTP I2C Address: 0x5d
[    2.433413] goodix-ts 1-005d: touch input parameters is [id x y w p]<5 800 480 1024 1024>
[    2.441811] goodix-ts 1-005d: 1-005d supply vdd_ana not found, using dummy regulator
[    2.449859] goodix-ts 1-005d: 1-005d supply vcc_i2c not found, using dummy regulator
[    2.458144] goodix-ts 1-005d: Failed get pinctrl state:output_high
[    2.464399] goodix-ts 1-005d: Success request irq-gpio
[    2.469659] goodix-ts 1-005d: Success request rst-gpio
[    2.474833] goodix-ts 1-005d: try to reset and read Guitar 0
[    2.480563] goodix-ts 1-005d: Guitar reset
[    2.519341] goodix-ts 1-005d: I2C Addr is 5d
[    2.525133] goodix-ts 1-005d: IC Version: 911_1060
[    2.531740] goodix-ts 1-005d: Driver set not send config
[    2.566206] goodix-ts 1-005d: Use slot report protocol
[    2.572164] input: goodix-ts as /devices/virtual/input/input0
[    2.578881] goodix-ts 1-005d: INT num 77, trigger type:2
[    2.584844] goodix-ts 1-005d: create proc entry gt9xx_config success
[    2.591475] goodix-ts 1-005d: Alloc memory size:1534.
[    2.596832] goodix-ts 1-005d: I2C function: without pre and end cmd!
[    2.603247] goodix-ts 1-005d: Create proc entry success!

在这里插入图片描述
以上输出日志表明没有问题。

并且我们还根据下面这条日志信息知道了其设备文件的位置和名字:

[    2.572164] input: goodix-ts as /devices/virtual/input/input0

接下来使用下面这个命令来打印输出触摸屏的数据输出:
运行下面的命令后用手触摸触摸屏幕应该有数据输出:

hexdump /dev/input/event0

至于为什么是/dev/input/event0,而不是/dev/input/event1,请参看我的另一篇博文:
https://blog.youkuaiyun.com/wenhao_ir/article/details/145433887
当然,前面的日志输出中有input0,也显示其编号为0了。
运行结果如下,可见,用手触摸触摸屏幕有数据输出了。

在这里插入图片描述

当然,我们还可以用命令evtes命令来测试其数据值对不对:

evtest

在这里插入图片描述
在这里插入图片描述
我用手划了下屏幕,输出如下:
在这里插入图片描述
具体的意义就不去详细分析了,以后如果遇到这方面的问题再详细研究。

至此,触摸屏的驱动移植就顺利结束了。

USB蓝牙设备的驱动适配(将驱动改为模块的形式进行加载)

01-蓝牙USB协议栈、驱动的结构(HCI是何意?)

问:为什么蓝牙USB的驱动和配置中常出现hci(HCI)这个词?

答:“HCI” 是 “Host Controller Interface”(主机控制器接口)的缩写,它是蓝牙协议栈中的一个重要部分,负责主机与蓝牙适配器(如蓝牙USB适配器)之间的通信。具体来说,HCI作为蓝牙硬件和上层蓝牙协议栈(如L2CAP、RFCOMM等)之间的桥梁,它定义了主机与蓝牙硬件之间的数据交换方式。

在蓝牙USB驱动和配置中,常见的 hci 相关词汇通常表示和蓝牙控制器(如蓝牙USB适配器)通信的接口。例如:

  • hci_usb: 这是蓝牙USB适配器的驱动,处理USB总线和蓝牙硬件之间的通信。
  • hci_dev: 这是一个代表蓝牙设备的结构体,管理蓝牙设备的状态和配置。

简而言之,HCI是蓝牙通信的一个基础接口标准,用来确保蓝牙设备和主机系统之间可以有效地进行信息传输。在蓝牙USB适配器的驱动中,hci指的就是通过这个接口与蓝牙硬件进行交互的过程。

02-1-发现问题在哪里

内核启动时与USB蓝牙设备的日志信息如下:
在这里插入图片描述

[    3.511977] Bluetooth: hci0: RTL: examining hci_ver=06 hci_rev=000b lmp_ver=06 lmp_subver=8723
[    3.522944] Bluetooth: hci0: RTL: rom_version status=0 version=1
[    3.529197] Bluetooth: hci0: RTL: loading rtl_bt/rtl8723b_fw.bin
[    3.535589] bluetooth hci0: Direct firmware load for rtl_bt/rtl8723b_fw.bin failed with error -2
[    3.544849] bluetooth hci0: Falling back to sysfs fallback for: rtl_bt/rtl8723b_fw.bin

从这个日志中,我们可以看出主要的异常在于蓝牙主机接口Bluetooth: hci0表示无法加载蓝牙固件 rtl_bt/rtl8723b_fw.bin

02-2-尝试把固件复制到相应的目录中看行不行

所以我们需要去找到配套的蓝牙估固件并将其拷贝到对应的目录。

可以从下面这个git仓库获取:

https://gitee.com/weidongshan/linux-firmware

运行下面的命令获取:

git clone https://gitee.com/weidongshan/linux-firmware

在这里插入图片描述
在这里插入图片描述
最后的结果是成功拉取,但是目录radeon下的文件存在大小写敏感的问题(关于这个问题 详见 https://blog.youkuaiyun.com/wenhao_ir/article/details/144871115),不过我们要用的文件在目录rtl_bt中,所以这个问题与我们当下做的事无关。

我把从百问网拉取得到的整个固件库压缩传到了百度网盘,百度网盘下载链接:
https://pan.baidu.com/s/1yKqA5F11ESxdLxrC5MIUZg?pwd=4k9n

单独的蓝牙固件百度网盘下载地址如下:
https://pan.baidu.com/s/1kjXfhJlhGZ4UNHEZb1B8iQ?pwd=hj5q

我们把拉取得到的目录复制到根文件系统的相关目录中,具体是复制到下面的目录中:

/home/book/mybuild/nfs_linux_rootfs/lib/firmware

在这里插入图片描述
然后查看下这个目录的权限,

ls -ld /home/book/mybuild/nfs_linux_rootfs/lib/firmware/rtl_bt

在这里插入图片描述
可见是777的权限,drwxrwxrwx中的d代表这是一个目录。

也可像下面这样看:
在这里插入图片描述
我们再看一下我们感兴趣的文件rtl_bt/rtl8723b_fw.bin的权限:

ls -l /home/book/mybuild/nfs_linux_rootfs/lib/firmware/rtl_bt/rtl8723b_fw.bin

在这里插入图片描述
可见,它还没有达到777的权限,执行下面的命令将目录/home/book/mybuild/nfs_linux_rootfs/lib/firmware/rtl_bt/中的所有文件的权限都改变为777:

sudo chmod -R 777 /home/book/mybuild/nfs_linux_rootfs/lib/firmware/rtl_bt

在这里插入图片描述
然后我们再看我们感兴趣的文件rtl_bt/rtl8723b_fw.bin的权限:

ls -l /home/book/mybuild/nfs_linux_rootfs/lib/firmware/rtl_bt/rtl8723b_fw.bin

在这里插入图片描述
可见权限为777了。

然后,我们重启开发板…发现内核依旧提示找不到 rtl_bt/rtl8723b_fw.bin 文件。

我们需要静下心来分析原因。

相关日志如下:
在这里插入图片描述
从日志中来看:Linux的内核在启动时,蓝牙驱动的加载时间是早于利用NFS网络文件系统挂载根文件的时间的,这就是问题的所在了,当蓝牙驱动加载时,根文件系统都还没有挂载上,怎么能找到相应的固件文件呢。

解决方法:我们可以把蓝牙驱动编译成模块,等系统启动后,让系统再自动去加载模块,通过这种方式,应该就没有问题了。

03-配置内核,使蓝牙驱动变成ko模块

在内核源码目录下用 make menuconfig 命令进入配置页面:

make menuconfig

参考下述配置路径来找到具体的配置项:

-> Networking support 
 -> Bluetooth subsystem support 
   -> Bluetooth device drivers

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在上图中HCI USB driver的选项上按两次空格,将其设置为M,表示使其成为一个模块。
在这里插入图片描述
然后保存,退出。
在这里插入图片描述
Save完记得还要点击上图中的 Exit按钮若干 次才能一层一层的退出…

此时我们来看下配置文件:

gedit .config

在这里插入图片描述
可见通过配置,使相关的驱动成为了可加载的模块。

04-重新编译内核镜像(必须先编译内核镜像再编译模块)

注意:在编译 Linux 内核镜像和模块时,必须先编译内核镜像,再编译模块,顺序不可随意调整。原因见我的另一篇博文 https://blog.youkuaiyun.com/wenhao_ir/article/details/145947194

执行编译内核镜像命令,来生成包含触摸屏驱动的内核镜像文件:

make zImage -j4

当然,如果处理器的资源够多,可以用8线程加快构建速度,即把-j4改为-j8
在这里插入图片描述
开始时间 2025-02-28 17:21:08
完成时间 2025-02-28 17:22:00
在这里插入图片描述

05-编译生成模块

注意:在编译 Linux 内核镜像和模块时,必须先编译内核镜像,再编译模块,顺序不可随意调整。原因见我的另一篇博文 https://blog.youkuaiyun.com/wenhao_ir/article/details/145947194

在内核根目录下,用下面的命令编译生成模块

make modules -j4

开始时间 2025-02-28 18:15:27
结束时间 2025-02-28 18:16:30
可见耗时很短…
运行结果如下:
在这里插入图片描述
其中与蓝牙模块有关的输出信息如下:
在这里插入图片描述

06-将编译生成的模块安装到根文件系统的相应目录中

在内核根目录下,用下面的命令将编译生成的模块安装到根文件系统的相应目录中:

sudo make ARCH=arm INSTALL_MOD_PATH=/home/book/mybuild/nfs_linux_rootfs/ modules_install

在这里插入图片描述
安装到根文件目录中的具体位置如下:

/home/book/mybuild/nfs_linux_rootfs/lib/modules/5.4.47-00055-g5ec03d06f54e-dirty/

在这里插入图片描述
在这里插入图片描述
我们感兴趣的模块的文件位置如下图所示:

/home/book/mybuild/nfs_linux_rootfs/lib/modules/5.4.47-00055-g5ec03d06f54e-dirty/kernel/drivers/bluetooth

在这里插入图片描述
不妨运行下面的命令再次修改下整个根文件系统目录的权限:

sudo chmod -R 777 /home/book/mybuild/nfs_linux_rootfs

07-复制新生成的镜像到TFTP目录中

在这里插入图片描述

08-重启系统并观察启动日志有无蓝牙驱动的信息输出

然后按本博文目录“设置好u-boot的相关环境变量,然后从网络启动Linux系统”中的方法重启内核。
在这里插入图片描述
在这里插入图片描述
启动后用root用户登陆:
在这里插入图片描述
之前在网络配置前有蓝牙设备启动失败的日志输出,如下图所示:
在这里插入图片描述
但这次启动后没有了,相关的日志截图如下(红线之下是网络配置及NFS目录挂载的日志):
在这里插入图片描述

09-测试蓝牙驱动模块是否能正常运行

先执行 lsmod 看一下系统有没有默认自动装载 USB 蓝牙驱动模块:

lsmod

在这里插入图片描述
可见这几个与蓝牙有关的模块都已被加载了。

至于为什么这些蓝牙模块会在启动后被自动加载,我也不清楚,可能与启动时加载的某些脚本有关吧~也可能是与这是个USB设备有关吧,USB总线检测到设备后会自动去加载它的驱动模吧。
不过我们可以通过查看系统日志来看下能不能获得一些线索,运行下面的命令查看与蓝牙相关的日志:

dmesg | grep "Bluetooth"

在这里插入图片描述

root@imx6ull14x14evk:~# dmesg | grep "Bluetooth"
[    0.355237] Bluetooth: Core ver 2.22
[    0.355405] Bluetooth: HCI device and connection manager initialized
[    0.355442] Bluetooth: HCI socket layer initialized
[    0.355465] Bluetooth: L2CAP socket layer initialized
[    0.355541] Bluetooth: SCO socket layer initialized
[    2.656148] Bluetooth: HCI UART driver ver 2.3
[    2.660979] Bluetooth: HCI UART protocol H4 registered
[    2.666159] Bluetooth: HCI UART protocol BCSP registered
[    2.671655] Bluetooth: HCI UART protocol LL registered
[    2.676938] Bluetooth: HCI UART protocol Three-wire (H5) registered
[    2.683291] Bluetooth: HCI UART protocol Marvell registered
[    3.152393] Bluetooth: RFCOMM TTY layer initialized
[    3.157567] Bluetooth: RFCOMM socket layer initialized
[    3.162827] Bluetooth: RFCOMM ver 1.11
[    3.166632] Bluetooth: BNEP (Ethernet Emulation) ver 1.3
[    3.172045] Bluetooth: BNEP filters: protocol multicast
[    3.177365] Bluetooth: BNEP socket layer initialized
[    3.182359] Bluetooth: HIDP (Human Interface Emulation) ver 1.2
[    3.188353] Bluetooth: HIDP socket layer initialized
[   19.625136] Bluetooth: hci0: RTL: examining hci_ver=06 hci_rev=000b lmp_ver=06 lmp_subver=8723
[   19.635941] Bluetooth: hci0: RTL: rom_version status=0 version=1
[   19.646171] Bluetooth: hci0: RTL: loading rtl_bt/rtl8723b_fw.bin
[   19.683460] Bluetooth: hci0: RTL: loading rtl_bt/rtl8723b_config.bin
[   19.705625] Bluetooth: hci0: RTL: cfg_sz 25, total sz 22793
[   20.261940] Bluetooth: hci0: RTL: fw version 0x1e6ca747

从这个日志中我们可以看,在这次系统启动过程中,对文件rtl_bt/rtl8723b_fw.bin的加载是在19.646171时进行的了,并且加载成功了,这个时间已经是系统启动的末期的时间了…但是还是不知道为什么蓝牙的驱动模块会被自动加载,只能说估计在这个时间段内,有个脚本把这几个蓝牙驱动模块进行了加载吧。

接着我们再利用hci tools工具来启用设备并扫描周边蓝牙设备确认设备是否已经可以正常使用:

运行下面的命令查看蓝牙设备的状态:

hciconfig -a

在这里插入图片描述
运行下面的命令打开蓝牙设备:

hciconfig hci0 up

在这里插入图片描述
然后再次运行下面的查看蓝牙设备的状态:

hciconfig -a

运行结果如下:

root@imx6ull14x14evk:~# hciconfig -a
hci0:   Type: Primary  Bus: USB
        BD Address: 2C:C3:E6:5C:27:5B  ACL MTU: 1021:8  SCO MTU: 255:16
        UP RUNNING 
        RX bytes:1880 acl:0 sco:0 events:165 errors:0
        TX bytes:24257 acl:0 sco:0 commands:163 errors:0
        Features: 0xff 0xfb 0xff 0xfe 0xdb 0xfd 0x7b 0x87
        Packet type: DM1 DM3 DM5 DH1 DH3 DH5 HV1 HV2 HV3 
        Link policy: RSWITCH HOLD SNIFF PARK 
        Link mode: SLAVE ACCEPT 
        Name: 'BlueZ 5.50'
        Class: 0x200000
        Service Classes: Audio
        Device Class: Miscellaneous, 
        HCI Version: 4.0 (0x6)  Revision: 0x1e6c
        LMP Version: 4.0 (0x6)  Subversion: 0xa747
        Manufacturer: Realtek Semiconductor Corporation (93)

在这里插入图片描述
可见设备已启用并且运行中了,并且蓝牙对外展示的名字是“BlueZ 5.50”。

接着通过以下命令将蓝牙设备切换到主动扫描模式:

hciconfig hci0 piscan

此时再运行命令hciconfig -a查看状态:
在这里插入图片描述
这种模式下我的手机进行附近的蓝牙设备扫描时才能找到开发板上的蓝牙设备。
当开启PSCAN ISCAN模式后,我的手机进行附近的蓝牙设备扫描时就发现了开发板上的这个蓝牙设备,如下图所示:
在这里插入图片描述
此时我们运行下面的命令:

hcitool scan

然后趁这条命令执行时赶紧在手机上尝试连接开发板上的蓝牙设备,即此时手机上点击下图红框中的位置:
在这里插入图片描述
然后终端上就能发现我的手机设备了,如下图所示:
在这里插入图片描述
经测试,在这里如果你不先在手机上点击连接开发板这个蓝牙设备,再运行命令hcitool scan,那么是搜索不到任何蓝牙设备的。

如果手机上出现连接失败,如下图所示:
在这里插入图片描述
那么多试几次一般是能成功的,连接成功后会提示配对信息:
在这里插入图片描述
在这里插入图片描述
至此,USB蓝牙驱动的测试就算成功了。

10-USB蓝牙驱动适配的总结

至此,我们就把蓝牙的驱动也移植到内核中了,从中我们可以看到,这个蓝牙驱动的实现关键是加载相应的二进制固件文件,整个过程我们没有去写什么驱动代码,也没有去复制粘贴什么源代码文件。

Wifi驱动的移植

其实我也不知道百问网是如何发现Wifi也不能用的

其实我也不知道百问网是如何发现Wifi也不能用的,在系统的启动日志中,搜索WLAN,并无发现任何异常:
在这里插入图片描述

[    3.458222] usb 1-1.1: New USB device found, idVendor=0bda, idProduct=b720, bcdDevice= 2.00
[    3.466807] usb 1-1.1: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[    3.474571] usb 1-1.1: Product: 802.11n WLAN Adapter
[    3.480075] usb 1-1.1: Manufacturer: Realtek
[    3.484591] usb 1-1.1: SerialNumber: 00e04c000001

不过这个问题不是啥大问题,所以就先不用深究。

其实蓝牙和Wifi都用的是同一块芯片(型号为RTL8723)

在这里插入图片描述

在这里插入图片描述

RTL8723 芯片(通常指的是 Realtek RTL8723BERTL8723BS)是一款集成了蓝牙Wi-Fi功能的芯片,它同时支持无线信号的发射和接收功能。

具体功能包括:

  1. Wi-Fi:RTL8723 芯片支持 Wi-Fi 802.11b/g/n标准,能够进行无线网络通信,包括无线信号的发射和接收。它能够通过无线局域网(Wi-Fi)与路由器或其他设备进行数据传输。

  2. 蓝牙:RTL8723 芯片还支持蓝牙4.0(通常为蓝牙低能耗技术,BLE),用于短距离无线通信。它允许设备与蓝牙耳机、键盘、鼠标等蓝牙设备进行配对和通信。

因此,RTL8723 芯片不仅支持无线局域网(Wi-Fi)的信号发射与接收,还支持蓝牙设备的信号发射与接收。

如果你在使用这个芯片的设备,通常会同时支持Wi-Fi和蓝牙功能,允许设备进行无线网络连接及蓝牙设备的配对通信。

wifi固件复制到根文件系统中

之前在“USB蓝牙设备的驱动适配”中,已经把相应的固件配通过git仓库克隆到Windows中了,如下图所示:
在这里插入图片描述
现在我们把它复制到Ubuntu的根文件系统挂载目录的相应路径下,具体的目录路径为:

/home/book/mybuild/nfs_linux_rootfs/lib/firmware

在这里插入图片描述
不妨用下面的命令将根文件目录中的所有子目录和文件的权限都设为777,这样的话刚才复制进去的目录和文件的权限也变为777了。

sudo chmod -R 777 /home/book/mybuild/nfs_linux_rootfs

在这里插入图片描述

配置内核(某些项配置为*状态、某些项配置为M状态)

在内核源码目录下用 make menuconfig 命令进入配置页面:

cd /home/book/mybuild/Linux-BSP_raw/linux-imx
make menuconfig

参考下述配置路径来找到具体的配置项:

-> Device Drivers 
 -> Network device support 
  -> Wireless LAN

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
把上图中用红框选中的三项分别作下面的设置:
①“Realtek 8187 and 8187B USB support”用空格键选择为M,即编译为.ko模块。选择好后如下图所示:
在这里插入图片描述
②“Realtek rtlwifi family of devices”保持不变,即仍然是*状态。* 代表该功能被编译进内核(Built-in),而不是作为模块存在,也不是没启用的意思。
③“RTL8723AU/RTL8188[CR]U/RTL819[12]cU (mac80211) support””用空格键选择为M,即编译为.ko模块。
在这里插入图片描述
当把“RTL8723AU/RTL8188[CR]U/RTL819[12]cU (mac80211) support””用空格键选择为M后,下面紧接着出现了选项“Include support for untested Realtek 8xxx USB devices (EXPERIMENTAL
) (NEW)”,如下图所示:
在这里插入图片描述我把这里需要把选项“Include support for untested Realtek 8xxx USB devices (EXPERIMENTAL
) (NEW)”用空格键选为*状态,即编译进内核的状态,如下图所示:
在这里插入图片描述
最终这4项配置好的截图如下:
在这里插入图片描述
这里如果你要问为什么要这样配置,我也知道,我相信百问网也是看相关的教程,甚至是芯片官方出的教程操作的,这种东西靠自己就能知道怎么做几乎是不可能的。

配置完后:
Save→然后一层一层的Exit 退出。
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

重新编译内核镜像(必须先编译内核镜像再编译模块)

注意:在编译 Linux 内核镜像和模块时,必须先编译内核镜像,再编译模块,顺序不可随意调整。原因见我的另一篇博文 https://blog.youkuaiyun.com/wenhao_ir/article/details/145947194

make zImage -j4

在这里插入图片描述
在这里插入图片描述
耐心等待一两分钟,由于之前已经编译过内核镜像了,所以这里时间就比较快了。

在这里插入图片描述

复制新生成的镜像到TFTP目录中

在这里插入图片描述

编译生成wifi驱动模块

注意:在编译 Linux 内核镜像和模块时,必须先编译内核镜像,再编译模块,顺序不可随意调整。原因见我的另一篇博文 https://blog.youkuaiyun.com/wenhao_ir/article/details/145947194

在内核根目录下,用下面的命令编译生成模块

make modules -j4

在这里插入图片描述
在这里插入图片描述
可见,本次编译,新生成了下面这个模块:

  LD [M]  drivers/net/wireless/realtek/rtl818x/rtl8187/rtl8187.ko
  LD [M]  drivers/misc/eeprom/eeprom_93cx6.ko
  LD [M]  drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.ko

将编译生成的模块安装到根文件系统的相应目录中

在内核根目录下,用下面的命令将编译生成的模块安装到根文件系统的相应目录中:

sudo make ARCH=arm INSTALL_MOD_PATH=/home/book/mybuild/nfs_linux_rootfs/ modules_install

在这里插入图片描述
在这里插入图片描述
这些模块被安装到NFS挂载的根文件系统的下面这个目录中:

/home/book/mybuild/nfs_linux_rootfs/lib/modules/5.4.47-00055-g5ec03d06f54e-dirty/

在这里插入图片描述
在这里插入图片描述
我们感兴趣的模块的文件位置如下图所示:

rtl8187.ko:

/home/book/mybuild/nfs_linux_rootfs/lib/modules/5.4.47-00055-g5ec03d06f54e-dirty/kernel/drivers/net/wireless/realtek/rtl818x/rtl8187

在这里插入图片描述
eeprom_93cx6.ko:

/home/book/mybuild/nfs_linux_rootfs/lib/modules/5.4.47-00055-g5ec03d06f54e-dirty/kernel/drivers/misc/eeprom

在这里插入图片描述

rtl8xxxu.ko:

/home/book/mybuild/nfs_linux_rootfs/lib/modules/5.4.47-00055-g5ec03d06f54e-dirty/kernel/drivers/net/wireless/realtek/rtl8xxxu

在这里插入图片描述

重启Linux系统

按本博文目录“设置好u-boot的相关环境变量,然后从网络启动Linux系统”中的方法重启内核。
在这里插入图片描述
在这里插入图片描述
启动后用root用户登陆:
在这里插入图片描述

测试wifi驱动模块是否正常

注意:如果你要进行二次测试,请把这个标题下的内容再读完,因为过程充满了曲折~,当然如果你不想曲折,可以查看博文 https://blog.youkuaiyun.com/wenhao_ir/article/details/145953214 【搜索“所以我不妨把最终精简的过程记录到下面”】

先用下面的命令看下有没有相应的USB设备:

lsusb

在这里插入图片描述
上面划红线的语句表示有相应的Wifi设备了,其ID号为:0bda:b720,其生产公司为 Realtek Semiconductor Corp

然后我们再运行下面的命令查看下相关的日志信息,看相关的固件是否加载了。

dmesg | grep "rtl"

结果居然只有下面的输出:
在这里插入图片描述
这两个是与蓝牙模块有关的信息啊, 而不是wifi模块的呀。按照教程,如果是与wifi模块相关的,应该是下面的固件加载信息:

[ 19.493995] usb 1-1.1: rtl8723bu_parse_efuse: dumping efuse (0x200 bytes):
[ 25.999107] usb 1-1.1: rtl8xxxu: Loading firmware rtlwifi/rtl8723bu_nic.bin
[ 28.017185] usbcore: registered new interface driver rtl8xxxu

我们的蓝牙模块和wifi模块我之前说了,其实都是用的同一块芯片,即瑞昱的RTL8723,所以与这两个模块相关的关键词都是RTLrtl

再运行下面的命令看下wifi驱动模块加载没有:

lsmod

在这里插入图片描述
发现也没有,正常情况下应该有下面这个模块:
在这里插入图片描述
那我们不妨运行下面的命令去直接加载一下试一下呢:
【注意:从这里可以直接跳到本文后面的内容来看,搜索“奇怪的事:”】
【注意:从这里可以直接跳到本文后面的内容来看,搜索“奇怪的事:”】

进入模块rtl8xxxu.ko所在的目录:

cd /lib/modules/5.4.47-00055-g5ec03d06f54e-dirty/kernel/drivers/net/wireless/realtek/rtl8xxxu

执行加载模块的命令:

insmod rtl8xxxu.ko

在这里插入图片描述
在这里插入图片描述
这个输出中前面的语句:

[16152.728847] usb 1-1.1: This Realtek USB WiFi dongle (0x0bda:0xb720) is untested!
[16152.737020] usb 1-1.1: Please report results to Jes.Sorensen@gmail.com

表示的意思是:
这个驱动对于USB WiFi 设备(VID: 0x0bda, PID: 0xb720)尚未经过正式测试,有可能会出现不兼容的情况。单词 dongle 在计算机领域指的是一种小型外接设备,通常通过 USB、蓝牙或其他接口连接到计算机或其他主机设备,提供额外的功能,这里单词 dongle 是指这个Realtek 的 USB WiFi设备是一种小型外接设备。 如果你在使用过程中发现什么问题,可以联系 Jes.Sorensen@gmail.com(该驱动的维护者之一。
从上面我们可以看到,实际上我们还编译出了另一个名叫rtl8187.ko的驱动模块,如下所示:

/home/book/mybuild/nfs_linux_rootfs/lib/modules/5.4.47-00055-g5ec03d06f54e-dirty/kernel/drivers/net/wireless/realtek/rtl818x/rtl8187

在这里插入图片描述
如果加载这个应该就不会出现这个未经测试的信息吧。

不过末尾的输出信息表示相应的固件被成功加载了:

[16153.595783] usb 1-1.1: rtl8xxxu: Loading firmware rtlwifi/rtl8723bu_nic.bin

同时最后一条信息:

[16153.595783] usb 1-1.1: rtl8xxxu: Loading firmware rtlwifi/rtl8723bu_nic.bin

表示 usbcore(Linux 内核的 USB 子系统)成功注册了 rtl8xxxu 这个 WiFi 驱动,即 该驱动已经被加载到内核并准备使用。

接下来测试wifi模块能否找到附近的wifi 设备:
先运行下面的命令打开wifi:

ifconfig wlan0 up

然后运行下面的命令扫描周围的wifi设备:

iw wlan0 scan | grep "SSID"

运行结果如下:
在这里插入图片描述
可见,已经发现了我们家和邻居家的wifi。


接下来,我们重新从网络启动系统,换成加载模块rtl8187.ko试试。
在这里插入图片描述

进入模块rtl8187.ko所在的目录:

cd /lib/modules/5.4.47-00055-g5ec03d06f54e-dirty/kernel/drivers/net/wireless/realtek/rtl818x/rtl8187

执行加载模块的命令:

insmod rtl8187.ko

在这里插入图片描述
从上面的报错信息,我们想到了,其实这次模块编译我们还编译出了另一个名字叫eeprom_93cx6.ko的模块,我们应该是要先加载它:

cd /lib/modules/5.4.47-00055-g5ec03d06f54e-dirty/kernel/drivers/misc/eeprom/
insmod eeprom_93cx6.ko

在这里插入图片描述
可见,加载模块eeprom_93cx6.ko是一点问题没有。

然后再去加载rtl8187.ko

cd /lib/modules/5.4.47-00055-g5ec03d06f54e-dirty/kernel/drivers/net/wireless/realtek/rtl818x/rtl8187

执行加载模块的命令:

insmod rtl8187.ko

在这里插入图片描述
这就没有提示未经测试了…

然后打开wifi…

ifconfig wlan0 up

扫描附近的wifi

iw wlan0 scan | grep "SSID"

在这里插入图片描述
可见,也发现了我们家和邻居家的wifi…

奇怪的事:后来我关闭电源再重启系统,发现wifi模块自动加载了

奇怪的事:后来我关闭电源再重启系统,发现wifi模块自动加载了,相关日志如下:
在这里插入图片描述
在这里插入图片描述
lsmod命令查看模块居然有wifi的驱动了:
在这里插入图片描述
不过自动加载的是模块rtl8xxxu.ko,而不是模块rtl8187.ko,不过模块rtl8xxxu.ko也能用。

打开wifi…

ifconfig wlan0 up

扫描附近的wifi

iw wlan0 scan | grep "SSID"

在这里插入图片描述
没问题…

所以奇怪的事来了,为什么我前一次启动时没有自动加载wifi模块呢??为什么关电之后重新启动就自动加载了呢?这个问题留在这里吧…我一时半会儿也是搞不明白的,好在这不是什么严重或关键的问题。

思考:是驱动模块调用固件还是固件调用驱动模块?

从上面加载模块rtl8xxxu.ko的日志输出可以看出,是驱动模块,即驱动程序去调用固件。
命令:

insmod rtl8xxxu.ko

的日志输出信息如下:
在这里插入图片描述

烧写设备树dtb文件、内核镜像、根文件系统到eMMC中

之前在博文 https://blog.youkuaiyun.com/wenhao_ir/article/details/145662136 中已经把支持eMMC启动方式的u-boot烧写到了eMMC中,所以接下来的任务我们要烧写设备树dtb文件、内核镜像、根文件系统到eMMC中,并了解一些其中的细节:比如每一部分具体是烧写到eMMC的哪个位置?u-boot又怎么知道该内核放在eMMC存储器的哪个位置?内核又怎么知道根文件系统在哪个位置?这些问题不理解也是不行了。
鉴于内容有点多,我们就在下一篇博文中来写。
下一篇博文的链接为:
https://blog.youkuaiyun.com/wenhao_ir/article/details/145953214

附这篇博文涉及到的相关文件的下载地址

01-修改设备树时涉及到的相关设备树文件

在这里插入图片描述
https://pan.baidu.com/s/1wvtvH3FQRWWfdkhZvWt1pg?pwd=ytur

02-各个阶段的内核源码下载地址

FSL Yocto Project Community BSP使用的Linux内核源码

百度网盘下载地址如下:
https://pan.baidu.com/s/1Y-Wz69K9tsWFxTTdhZWV_g?pwd=n79q
注意:文件有点大…4.04GB呢…

百问网提供的修改完的源码

这个源码是从百问网的仓库中获取的,仓库地址和获取命令如下:

git clone https://gitee.com/weidongshan/linux-imx

拉取得到的百问网修改完的源码的百度网盘下载地址:
https://pan.baidu.com/s/1mHjR9yr_rB_zeyX6PmZdoA?pwd=zgp4

我自己移植修改完内核后的源码(编译出了内核镜像和相关模块)

百度网盘下载地址如下:
https://pan.baidu.com/s/1qkHXDLybZPrr5lyvNxxc-Q?pwd=y2nc

03-TFTP根目录(含设备树文件、各阶段的镜像文件)

TFTP根目录中含下面的文件:
在这里插入图片描述
百度网盘下载地址如下:
https://pan.baidu.com/s/1GSch4rbQKsg-pFPLWneS4A?pwd=4g75

04-根文件系统

百问网提供的原版根文件系统

百度网盘下载地址如下:
https://pan.baidu.com/s/1NUnuC9dzBFS9oOC0EhjarQ?pwd=qcyz

我自己使用过的从Ubuntu中压缩出的根文件系统

下面这个nfs_linux_rootfs目录:
在这里插入图片描述
压缩时需要用下面的带sudo的压缩命令来压缩:

sudo zip -r nfs_linux_rootfs.zip /home/book/mybuild/nfs_linux_rootfs

否则会出现权限不足的提示:
在这里插入图片描述

很奇怪的是本来只有663.MB的大小,但是压缩完之后居然有8.81GB…
在这里插入图片描述
在这里插入图片描述
那就更改下权限,然后用系统右键功能进行压缩:

sudo chmod -R 777 /home/book/mybuild/nfs_linux_rootfs

在这里插入图片描述
在这里插入图片描述
这下得到的压缩文件就只有513.3MB的大小了:
在这里插入图片描述

可以向gpt发起下面的提问得到答案:
为什么我在Ubuntu终端 中使用下面的命令:

sudo zip -r nfs_linux_rootfs.zip /home/book/mybuild/nfs_linux_rootfs

压缩存放在Ubuntu中的根文件系统,压缩前查看目录nfs_linux_rootfs的属性为663.MB,但是压缩完成得的压缩文件却足足有8.81GB。但是我用Ubuntu右键菜单“Compress”进行zip压缩,得到的压缩文件就只有513.3MB的大小。

答案我总结如下:
根文件系统可能包含稀疏文件(Sparse Files),即文件系统中包含大量的空洞(未实际占用磁盘空间的数据块)。zip 在默认情况下会将这些空洞填充为实际数据,从而导致压缩文件变大。Ubuntu 的 GUI 压缩工具可能使用了 xz 或 bzip2 进行更高效的压缩,从而把这些稀疏文件的空洞处理得很好,而命令行进行 zip 压缩默认使用 DEFLATE 算法,没有去处理好稀疏文件的这些空洞。

所以,如果用命令行进行压缩的话,不建议使用ZIP类型压缩,而要使用tar类型压缩,命令如下:

sudo tar --sparse -czf nfs_linux_rootfs.tar.gz /home/book/mybuild/nfs_linux_rootfs

我用Ubuntu右键菜单“Compress”进行zip压缩得到的压缩文件的百度网盘的下载地址如下:
https://pan.baidu.com/s/1IA_LzGzsI996XOUsbnRCTg?pwd=nnsv

05-从百问网拉取得到的整个固件库

我把从百问网拉取得到的整个固件库压缩传到了百度网盘,百度网盘下载链接:
https://pan.baidu.com/s/1yKqA5F11ESxdLxrC5MIUZg?pwd=4k9n

固件库目录的截图如下:
在这里插入图片描述

附移植完成后的完整启动日志文件

我把日志保存为txt文件了,百度网盘下载地址:
https://pan.baidu.com/s/1ErLKLsuBPXBjDM5RkbBh9Q?pwd=3tck

评论 4
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

昊虹AI笔记

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值