驱动开发、移植

一、任务明确:把创龙MX8的驱动 按照我们的要求 然后移植到 我们的板子

1.Linux系统启动卡制作,

sd卡 先按照 《用户手册—3-2-Linux系统启动卡制作及系统固化》 把创龙的Linux系统刷进去。

2. 把TLIMX8-EVM的板子过一遍

把刚刚烧好系统的sd卡插入 创龙TLIMX8-EVM的板子,
用SecureCRT调试窗口 串口或者SSH远程登陆 创龙创龙TLIMX8-EVM的板子
然后按照 《2-1-评估板测试手册》 把评估版创龙TLIMX8-EVM下面这些功能测试一遍
在这里插入图片描述

3. 把TLIMX8-EVM的板子的Liunx系统编译一遍

按照 《3-1-Linux系统使用手册》 把创龙的TLIMX8-EVM的板子配套的Liunx系统下面图这些U-Boot、Linux内核编译一遍,也就是把刚刚刷进去SD卡的Linux系统内核编译一遍。(之后可以按照自己的需求对内核进行配置和裁剪)
在这里插入图片描述

4.按照我们的需求去修改、配置内核,编译成内核镜像文件,修改设备树dts,编译生成设备树dtb文件

按照我们的需求去修改、配置内核,编译成内核镜像文件,烧录到我们自己的板子;
之后我们就把创龙的TLIMX8-EVM 板 对应的Linux系统内核,也就是上面刷的那个系统内核 根据 我们这边的需求去修改、去配置内核,然后编译出来生成Linux系统镜像文件,然后把这个镜像文件烧进SD卡—Linux系统启动卡,然后把这个卡插到我们自己做的板子,启动这个系统。

修改设备树dts文件,重新编译生成设备树dtb二进制文件,拷贝到SD卡—Linux系统启动卡的BOOT分区。
然后在虚拟机上修改设备树dts文件,重新编译生成设备树dtb二进制文件,拷贝到SD卡—Linux系统启动卡的BOOT分区。


5.之后工作的任务步骤

在虚拟机上使用 创龙的TLIMX8-EVM 板 对应的SDK(里面有文件可以编译生成对应版本的Linux系统。可以编译生成U-Boot、内核、文件系统、设备树文件)编译生成对应版本的Linux系统,烧录到SD卡—Linux系统启动卡。

1.内核配置,内核编译

首先先在虚拟机使用官方提供的SDK按照我们的需求去修改、配置内核,编译成内核镜像文件,烧录到我们自己的板子;

2.驱动适配调式过程:

将烧录好系统的sd卡插入 创龙TLIMX8-EVM的板子,板子使用SD卡里面的系统进行启动,
用SecureCRT调试窗口 串口连接或者SSH远程登陆 创龙TLIMX8-EVM的板子去测试刚刚烧录到这个Linux系统跟板子的功能模块适不适配,参考资料《2-1-评估板测试手册.pdf》
如果这个系统的某个功能模块(例如LED指示灯)在创龙TLIMX8-EVM板子上正常,说明原本的LDE指示灯驱动程序.c源文件没有问题。这时候我们就要去对应自己的板子去简单的修改LED指示灯驱动程序.c源文件,让这个驱动程序去适配我们的板子上的LED指示灯,如果.c源文件没有问题,或者不需要修改了,这时候就要去修改创龙TLIMX8-EVM板子对应的设备树文件,去修改成适配我们板子的设备树文件,然后拷贝到我们板子系统的BOOT分区(例如我们的板子使用的是SD卡—Linux系统启动卡,那我们就要插上这个卡连接到我们的PC机的虚拟机上,然后把这个设备树文件拷贝到SD卡—Linux系统的BOOT分区,然后在把这个卡拔掉,然后插到我们的板子,使用SD卡-Linux系统启动卡运行系统)。
除了LED指示灯功能模块,其他的功能模块的驱动也是类似进行开发,移植,
当自己的板子所有的功能模块的驱动都适配后,这时候就可以把SD卡-Linux系统启动卡中的系统 固化 到板子的 eMMC里面。

二、实战

1.虚拟机的账号和密码均是:Hugo

在这里插入图片描述

虚拟机开启root用户,设置了root用户密码

在这里插入图片描述

评估版的账号密码,都是root

遇到问题

共享文件夹的问题,cd 到 /mnt/hgfs/ 路径下,ls没有看到 Shared Folders 共享文件夹

系统自动挂载功能未启用,系统里面有这个共享文件夹,但是系统没有把这个文件夹自动挂载到/mnt/hgfs/下。
使用vmware-hgfsclient命令列出所有共享文件夹(在VM->setting->options->shared Folders里面设置的),可以看到所以共享文件夹都在系统中,只是没有自动挂载在 /mnt/hgfs/ 路径下。
在这里插入图片描述
我们手动挂载一下。先创建一个文件夹,然后把主机hots的共享文件夹SharedFolders 挂载到虚拟机这个文件夹 、mnt/hgfs/SharedFolders
在这里插入图片描述

1 根目录 / 是Linux文件系统的最顶层目录
~ 是一个快捷方式,代表当前用户的主目录。这是一种方便的方式来引用主目录而不需要输入完整的路径。比如,如果用户 hugo 的家目录是 /home/hugo,那么 ~/IMX8 就相当于 /home/hugo/IMX8 。
总是指向执行命令的那个用户的家目录。
2 U-Boot配置界面

在这里插入图片描述
在每次打开U-Boot配置界面时,要先

export LINES=24
export COLUMNS=80

强制设定终端的高度为24行,宽度为80列。请注意,这种方法不一定总是有效,因为实际显示效果还取决于终端的实际大小。

三、BL360_X8M板驱动移植

1. 【设备树】—修改、编译的步骤和命令

如图所示:
在这里插入图片描述

先cd到NXP i.MX8系列处理器(IMX8)的内核(kernel)目录下的 Linux内核版本为5.4.70(Linux-5.4.70)的内核源代码、配置文件、编译结果(内核源码)路径

cd IMX8/Kernel/Linux-5.4.70/

然后在这个路径下重新编译生成二进制设备树文件:
① 先使能SDK环境变量
② 在内核源码目录 IMX8/Kernel/Linux-5.4.70/ 下编译生成二进制设备树 dtb 文件(生成的 dtb文件位于arch/arm64/boot/dts/freescale/路径下)

source /home/hugo/SDK/environment-setup-aarch64-poky-linux
make freescale/tlimx8-evm.dtb

插上SD系统启动卡连接到PC机上的虚拟机,然后把生成的二进制dtb设备树文件拷贝到SD系统启动卡(Linux系统)的BOOT分区。
在这里插入图片描述

cd /media/hugo/BOOT
cp /home/hugo/IMX8/Kernel/Linux-5.4.70/arch/arm64/boot/dts/freescale/tlimx8-evm.dtb ./

2. 【pice】系统启动时pice问题

2.1 问题描述(启动系统被卡住)

BL360_X8M板插入sd系统启动卡,插上电启动的过程的时候,调试器SecureCRT显示出串口打印的信息,有pcie 。。。time out。 然后系统就一直卡在这里,进不去。

2.2 问题解决

BL360_X8M板插入sd系统启动卡,启动前要先把设备树的pcie屏蔽掉。

1.首先把sd系统启动卡拿出来,通过读卡器插到pc机上,然后挂载到虚拟机上。
2.根据《3-1-Linux系统使用手册.pdf》的 《3.4 编译设备树文件》的提示,进入这个链接去修改tlimx8-evm.dts

hugo@hugo-virtual-machine:~/IMX8/Kernel/Linux5.4.70/arch/arm64/boot/dts/freescale$ vi tlimx8-evm.dts

在这里插入图片描述
3.然后切换回内核源码安装目录下,执行如下命令使能SDK环境变量,并在内核源码目录"arch/arm/boot/dts/"路径中编译生成 dtb 文件。
在这里插入图片描述
4.把这个生成的dtb文件拷贝至Linux系统启动卡BOOT分区。
在这里插入图片描述
5.然后把系统启动卡断开链接,然后拔出来,插到BL360_X8M板上,重新启动。


3.【LED】驱动移植

3.1 需求背景(修改LED驱动)

把创龙MX8评估板的系统移植到 自己的板子BL360_X8M,修改调试LED驱动(led驱动源码.c 和 修改设备树)适配我们的板子。

3.2 基础适配步骤

首先led.c的驱动源码不用动,别人写好驱动了,我们只改设备树,改下引脚

① 设备树初步修改
1.定位关键节点

在tlimx8-evm.dts中定位leds节点。

2.引脚重映射(根据原理图修改目标引脚)

根据自己的原理图,看到我们自己板子上的LED1和LED2分别连接到GPIO3_23和GPIO3_34。
把leds这里的GPIO的口改成我们板子的LED连接的GPIO口。

然后重新编译生成设备树dtb,烧录后LED未点亮,进入深度排查阶段。

一般就这样修改,LED就会亮了,但是LED还是不亮,
如何解决看——4.《【 遇到问题】(引脚功能被复用)》
在这里插入图片描述


3【 遇到问题】(引脚功能被复用)

根据原理图修改成我们板子的LED的GPIO引脚号后,但是LED还是不亮

② pinctrl配置优化

然后有经验的工程师来教我,他先把led的pin_ctrl给注释掉了,说不用写也可以
在这里插入图片描述
为什么不需要配置pinctrl_gpio_led

内核自动处理:
因为在LED节点中直接指定gpios = <&gpio3 23 ...>时,
内核会自动去检查该引脚是否被其他模块占用,
如果没有冲突,自动将引脚配置为GPIO模式。

但需注意:
如果引脚被其他模块占用(如PDM),内核会拒绝配置,将不会自动将引脚配置为GPIO模式,从而导致LED失败,
此时必须手动释放冲突模块(如禁用PDM)。

技术原理:

  • 当gpios属性直接指定引脚时,内核会自动处理以下事项:
    • 检查引脚复用状态(通过Pad Mux寄存器)
    • 若无冲突,自动配置为GPIO模式
    • 设置默认电气特性(上拉/下拉等)
  • 冲突场景:若引脚被外设(如PDM、I2C等)占用,内核将输出-EBUSY错误
③ 引脚复用分析

然后通过NXP芯片官网提供的config tool软件找到了GPIO3_23引脚,对应AD13,找到了这个脚有其他的功能复用的可能,然后通过这段代码在设备树上查找:MX8MM_IOMUXC_SAI5_RXD2_PDM_DATA2

在这里插入图片描述

确实在设备树找到了代码:MX8MM_IOMUXC_SAI5_RXD2_PDM_DATA2 0xd6,说明配置了这个功能,刚好这个功能占用的口跟GPIO3_IO23冲突。
在这里插入图片描述

④ 禁用复用功能外设引脚

然后通过在设备树搜索 :pinctrl_pdm
在这里插入图片描述
找到了用这个功能的代码,把这个功能(micfil)注释掉就行。
在这里插入图片描述

⑤ 重新编译设备树,启动系统,可以看到有节点

可以先cd到 /sys/class/leds 路径下,然后 ls ,看看有没有 user-led0 和 user-led1 节点:
在这里插入图片描述

⑥ 使用命令测试,观察LED指示灯的亮灭,LED灯正常亮:
echo 0 > /sys/class/leds/user-led0/brightness 
echo 1 > /sys/class/leds/user-led0/brightness 
echo 0 > /sys/class/leds/user-led1/brightness 
echo 1 > /sys/class/leds/user-led1/brightness 

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


4. 【以太网ethernet】配置千兆以太网口驱动

4.0 要实现的效果

插上网线,就能正常ping通,或者需要udhcpc -i eth0分配一下ip。然后就能直接ping通
1.ip route查看路由器
看看能不能ping通
2.看看能不能ping通外网www.baidu.com

现在遇到的问题,网线插上后,有时候系统刚启动,ip可以自动分配,然后可以ping通www.baidu.com;
有时候系统去ping www.baidu.com 刚启动则不行
(因为有时候没有ip,等一会,有ip了,但是去ping还是不行,dns服务器有问题;
得自己手写dns;但是手写的dns,系统重启后之前手写的dns就会没有)

现在怀疑是网卡或PHY芯片(如提到的YT8521SH)可能存在不稳定的情况,导致连接不稳定。因为这个板子的系统老是重启,感觉电源不稳。
先尝试看看怎么样把dns写死,系统重启后不会没有。

4.1 正常的检测

① 把网线插上
② 看是否能正常检测到开发板的所有网口。
ifconfig
ifconfig -a
ip link show

在这里插入图片描述

③ 配置ip
1)动态获取

使用DHCP自动获取IP地址。可以通过运行dhclient eth0或相应地启用并启动systemd-networkd服务来实现。

udhcpc -i eth0

在这里插入图片描述

2)静态IP配置
④ 配置DNS

虽然使用udhcpc -i eth0命令尝试获取网络配置,包括DNS服务器地址。这一步显示获得了IP地址,但DNS配置可能没有正确更新或应用。
手动向/etc/resolv.conf添加Google的公共DNS服务器(8.8.8.8 和 8.8.4.4)。
重启systemd-networkd服务以确保新的DNS设置生效

root@IMX8-Tronlong:/# echo "nameserver 8.8.8.8" | sudo tee /etc/resolv.conf
erver 8.8.4.4" | sudo tee -a /etc/resolv.confnameserver 8.8.8.8

root@IMX8-Tronlong:/# echo "nameserver 8.8.4.4" | sudo tee -a /etc/resolv.conf
nameserver 8.8.4.4

5. 【4G】驱动配置


设备状况:

首先要想知道创龙的评估板关于4G模块的设备树定义在哪?
因为目前的状态是创龙的评估板插上4G模块是可以直接就用的了,可以ping通www.baidu.com;
然后我提供的dts和dtsi代码就是创龙评估板自带的设备树文件,它的板子用的就是这个设备树文件,并且dts设备树文件引用dtsi设备树文件。它们的配置是正确的,那关于4G的配置在哪?
找到它,并且分析为什么要做这样做?

其它信息:
创龙开发板用的是 MIC29302S/TR芯片,芯片有个地方连接这4G的3.3V,引脚,并且芯片有个引脚是R23/ETH_nRST/4G_ONn/CAP_TS_nRST/GPIO2_10/3V3。

评估底板通过USB HUB芯片将USB2总线拓展为4路USB HOST总线,其中引出一路
进行4G模块拓展。4G模块拓展接口(CON11)采用Mini PCIe插槽座。
CON10 为Micro SIM 卡座,采用插卡自弹形式,不带检测引脚。

为了保证4G模块有稳定的电源供应,其3.3V电源需由MIC29302S/TR(U25)独立
供电,至少提供2A电流输出。


完整解决方案:分步配置4G模块


第一步:修复设备树冲突

问题定位
  • 现象:在LED节点中添加 led@4 使用 GPIO2_10 并将其设为 default-state = "off" 后,4G模块正常工作。
  • 原因:我的自定义板中 GPIO2_10 实际是 4G模块的电源使能引脚,而非LED控制引脚。当设置为 off 时,GPIO输出低电平,意外触发了4G模块的使能信号。
操作步骤
  1. 删除冲突的LED配置
    打开设备树文件(如 dts.txt),移除 led@4 节点:

    leds {
        // ... 保留其他LED配置 ...
        // 删除以下内容:
        // led@4 {
        //     label = "user-led2";
        //     gpios = <&gpio2 10 GPIO_ACTIVE_HIGH>;
        //     default-state = "off";
        // };
    };
    
  2. 释放GPIO2_10给4G模块使用
    确保GPIO2_10未被其他节点占用(如LED、按键等)。


第二步:配置4G模块的电源和复位

1. 配置电源使能

在设备树中添加以下内容,控制4G模块的电源:

// 在iomuxc节点定义GPIO复用
&iomuxc {
    pinctrl_4g_power: 4gpowergrp {
        fsl,pins = <
            MX8MM_IOMUXC_SD1_RESET_B_GPIO2_IO10     0x00000056  // GPIO2_10,低电平有效
        >;
    };
};

// 在根节点添加电源控制
/ {
    reg_4g_power: regulator-4g {
        compatible = "regulator-fixed";
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_4g_power>;
        regulator-name = "4G_POWER_EN";
        regulator-min-microvolt = <3300000>;
        regulator-max-microvolt = <3300000>;
        gpio = <&gpio2 10 GPIO_ACTIVE_LOW>;  // 低电平使能电源
        enable-active-low;                   // 使能信号为低有效
        startup-delay-us = <2000>;           // 电源稳定后等待2ms
        regulator-always-on;                 // 保持常开
        status = "okay";
    };
};
2. 配置复位信号(不用设置)

如果4G模块需要复位引脚,添加复位控制(添加这个前,需要这个引脚硬件上支持复位功能):

// 假设复位引脚为GPIO2_15
&iomuxc {
    pinctrl_4g_reset: 4grstgrp {
        fsl,pins = <
            MX8MM_IOMUXC_SD1_DATA4_GPIO2_IO15       0x00000116  // GPIO2_15,低电平有效
        >;
    };
};

// 复位控制器
&gpio2 {
    4g_reset {
        compatible = "gpio-reset";
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_4g_reset>;
        gpios = <&gpio2 15 GPIO_ACTIVE_LOW>;
        startup-delay-us = <3000>;    // 电源稳定后3ms再复位
        reset-duration-us = <10000>;  // 复位信号持续10ms
    };
};

第三步:启用USB Host控制器

确保4G模块连接的USB接口(如usbotg2)设置为 Host模式

&usbotg2 {
    dr_mode = "host";        // 必须为Host模式
    pinctrl-names = "default";
    pinctrl-0 = <&pinctrl_usbotg2>;
    status = "okay";         // 启用USB接口
};

第四步:编译并更新设备树

  1. 编译设备树
    进入内核源码目录,执行命令去生成.dtb设备树文件:

    make ARCH=arm64 your_board.dtb  # 替换为你的板级设备树文件名
    
  2. 替换设备树文件
    将生成的 .dtb 设备树文件复制到开发板的 /BOOT 目录并重启:

    cp arch/arm64/boot/dts/your_board.dtb /boot/
    reboot
    

第五步:验证4G模块状态

1. 检查GPIO2_10状态

在开发板上执行命令
(42这个值具体看《四、驱动理解—7.GPIO引脚控制》):

# 导出GPIO2_10并查看电平
echo 42 > /sys/class/gpio/export
cat /sys/class/gpio/gpio42/value  # 应为0(低电平)
2. 查看USB设备列表

插入4G模块后运行:

lsusb
  • 预期输出:显示类似 12d1:15c1(华为模块)或 2c7c:0125(移远模块)的USB设备。
    在这里插入图片描述
3. 检查内核日志
dmesg | grep -E 'usb|gpio'
  • 预期输出:看到GPIO操作日志和USB设备枚举记录。

第六步:配置4G网络连接(可选,我这直接插上SIM卡就可以连网了)

1. 安装PPP拨号工具
apt-get install ppp
2. 创建PPP配置文件
vim /etc/ppp/peers/4g-ppp

内容:

/dev/ttyUSB0
115200
defaultroute
persist
usepeerdns
noauth
connect '/usr/sbin/chat -v -f /etc/ppp/chatscript'
3. 创建拨号脚本
vim /etc/ppp/chatscript

内容(以中国移动为例):

ABORT "BUSY"
ABORT "NO CARRIER"
TIMEOUT 30
"" "AT"
OK "AT+CGDCONT=1,\"IP\",\"CMNET\""
OK "ATD*99#"
CONNECT
4. 启动拨号连接
pon 4g-ppp

第七步:测试网络连通性

ping www.baidu.com
  • 成功标志:收到响应数据包。

4G模块工作流程详解

1. 系统启动
  • 电源使能
    内核解析设备树,加载 regulator-fixed 驱动。
    设备树中 reg_4g_power 节点通过GPIO2_10输出低电平,使能4G模块电源,等待2ms确保稳定。
2. 复位模块(可选)

如果配置了复位信号,系统在电源稳定后3ms拉低GPIO2_15持续10ms,完成硬件复位。

3. USB枚举

4G模块通过PCIe接口转USB连接到USB控制器。
USB控制器(如usbotg2)检测到4G模块,内核加载驱动(如 qmi_wwanusbserial),生成 /dev/ttyUSB*wwan0 接口。

4. 网络连接/拨号

用户空间工具(如ModemManager)通过AT指令或QMI协议拨号,建立蜂窝网络连接。
通过PPP或QMI协议发送AT指令拨号,建立蜂窝网络连接。

5. 数据传输

4G模块通过USB与系统通信,实现互联网访问。


关键问题解答

为什么需要配置GPIO2_10?
  • 硬件设计:我的ZT7103T芯片需要低电平信号才能开启4G模块电源,而创龙用的MIC29302S芯片,但是4G模块因为已经集成板子上,可能默认已使能电源。
为什么USB控制器必须设为Host模式?
  • 主从关系:4G模块是USB设备,开发板需作为Host主动管理设备。
为什么需要复位信号?
  • 初始化时序:某些4G模块要求上电后复位引脚拉低一段时间,确保芯片正确初始化。

总结

通过以下步骤,自定义板将实现4G功能:

  1. 释放冲突的GPIO:将GPIO2_10从LED节点移除。
  2. 配置电源和复位:确保4G模块正确上电和初始化。
  3. 启用USB Host模式:识别4G模块的USB接口。
  4. 网络拨号配置:通过PPP或QMI建立连接。

如果还有问题,再检查硬件原理图中GPIO连接和电源芯片的使能逻辑。

6. 【wifi】驱动配置

USB HUB芯片将USB2总线拓展为4路USB HOST总线
所以我们的wifi模块插入pcie接口,然后里面有转换芯片要么协议,将pcie转换为usb,然后接入4路usb host总线(USB2总线)其中的一条总线中。

6.1 不正常连接的情况

现在是我4G插在pcie插口上,然后我现在通过设备树的配置GPIO2_10可以给pcie的插口供电,然后pcie转usb连接到usb总线,让4G工作。所以GPIO2_10的脚是正常供电的,然后我现在插上wifi模块,并且wifi模块我也有驱动,是创龙提供的,我们用的wifi模块是一模一样的,把4G模块拔掉,插上wifi模块却出现了下面的情况:

在配置过程中遇到的问题:
1.经过尝试,在原来4G模块的pcie插口,4G模块可以用,说明pcie接口供电没有问题,但是拔下4G模块,插上wifi模块却没有反应。
2.插上wifi模块,把设备树的 regulator-4g节点和 iomuxc中的4gpowergrp复用引脚的代码屏蔽掉。把leds节点中的led4的代码添加进来,然后wifi模块插上pcie插口就能正常工作了,系统能检测到wlan0,wlan0也能获取到ip地址。
3.后续换回来 regulator-4g节点和 iomuxc中的4gpowergrp复用引脚的代码,把leds节点中的led4的代码屏蔽掉,也没有问题,说明两个代码都没问题。
4.最后发现是接触不良。

在这里插入图片描述
遇到这个一下断开,一下又检测到,可能就是接触不良。
在这里插入图片描述
反复报这个警告也很大概率是接触不良。

6.2 正常去配置的连接的情况

————————————————命令1:
root@IMX8-Tronlong:~# ifconfig eth0 down
root@IMX8-Tronlong:~# ifconfig eth1 down
root@IMX8-Tronlong:~# ifconfig eth2 down
root@IMX8-Tronlong:~# killall -9 wpa_supplicant
root@IMX8-Tronlong:~# insmod 8188eu.ko

————————————————结果1:
[  104.241422] 8188eu: loading out-of-tree module taints kernel.
[  104.285313] bFWReady == _FALSE call reset 8051...
[  104.329119] usbcore: registered new interface driver 8188eu
root@IMX8-Tronlong:~# [  128.142539] bridge: filtering via arp/ip/ip6tables is no longer available by default. Update your scripts to load br_netfilter if you need this.
[  128.172597] Bridge firewalling registered



————————————————命令2:
root@IMX8-Tronlong:~# ifconfig wlan0 up
root@IMX8-Tronlong:~# ifconfig

————————————————结果2:
docker0   Link encap:Ethernet  HWaddr 02:42:73:ec:35:bf
          inet addr:172.17.0.1  Bcast:172.17.255.255  Mask:255.255.0.0
          UP BROADCAST MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:130 errors:0 dropped:0 overruns:0 frame:0
          TX packets:130 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:9148 (8.9 KiB)  TX bytes:9148 (8.9 KiB)

wlan0     Link encap:Ethernet  HWaddr 78:22:88:c9:c7:03
          UP BROADCAST MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)


————————————————命令3:
root@IMX8-Tronlong:~# ./wifi_setup.sh -i bliiot -p bebetter

————————————————结果3:
conf  : /etc/wpa_supplicant.conf
ssid  : bliiot
psk   : bebetter
device: wlan0
update /etc/wpa_supplicant.conf
startup wpa_supplicant ...
Successfully initialized wpa_supplicant
rfkill: Cannot open RFKILL control device
udhcpc: started, v1.31.0
udhcpc: sending discover
[  184.201886] ------------[ cut here ]------------
[  184.206528] WARNING: CPU: 1 PID: 897 at net/wireless/nl80211.c:16300 cfg80211_ch_switch_notify+0xa4/0xb0
[  184.216006] Modules linked in: xt_MASQUERADE iptable_nat xt_addrtype iptable_filter ip_tables xt_conntrack x_tables nf_nat nf_conntrack nf_defrag_ipv6 nf_defrag_ipv4 libcrc32c br_netfilter bridge overlay 8188eu(O) smsc95xx crct10dif_ce ina2xx
[  184.237491] CPU: 1 PID: 897 Comm: RTW_CMD_THREAD Tainted: G           O      5.4.70-g497a4c6 #14
[  184.246272] Hardware name: TLIMX8-EVM HDMI (DT)
[  184.250800] pstate: 60000005 (nZCv daif -PAN -UAO)
[  184.255589] pc : cfg80211_ch_switch_notify+0xa4/0xb0
[  184.260672] lr : rtw_cfg80211_ch_switch_notify+0xf4/0x130 [8188eu]
[  184.266848] sp : ffff80001ce73c30
[  184.270159] x29: ffff80001ce73c30 x28: ffff800011e9a0e4
[  184.275468] x27: ffff800011e99b00 x26: 0000000000000000
[  184.280778] x25: ffff0000394ccb00 x24: 0000000000000001
[  184.286086] x23: 0000000000000000 x22: 000000000000096c
[  184.291395] x21: ffff000038adc000 x20: ffff0000394cc800
[  184.296704] x19: ffff80001ce73cb8 x18: 0000000000000000
[  184.302013] x17: 0000000000000000 x16: 0000000000000000
[  184.307322] x15: 0000000000000000 x14: 0000000000000000
[  184.312630] x13: 00000000000000ff x12: ffff800011e997b4
[  184.317939] x11: ffff800011e99c2a x10: 0000000000000018
[  184.323248] x9 : 0000000000000053 x8 : ffff80001ce73d58
[  184.328558] x7 : 0000000000000040 x6 : ffff0000394ccc10
[  184.333867] x5 : ffff00003444d0f8 x4 : ffff00003444d118
[  184.339176] x3 : ffff000039729000 x2 : ffff800000000000
[  184.344484] x1 : 0000000000000000 x0 : ffff00003444d000
[  184.349793] Call trace:
[  184.352241]  cfg80211_ch_switch_notify+0xa4/0xb0
[  184.356941]  rtw_cfg80211_ch_switch_notify+0xf4/0x130 [8188eu]
[  184.362838]  rtw_chk_start_clnt_join+0x270/0x3e0 [8188eu]
[  184.368294]  join_cmd_hdl+0x1d0/0x348 [8188eu]
[  184.372795]  rtw_cmd_thread+0x320/0x4c0 [8188eu]
[  184.377412]  kthread+0x138/0x158
[  184.380640]  ret_from_fork+0x10/0x1c
[  184.384212] ---[ end trace 7959c7c9134abb64 ]---
[  184.388953] ------------[ cut here ]------------
[  184.393582] WARNING: CPU: 1 PID: 897 at net/wireless/nl80211.c:3157 nl80211_send_chandef+0x150/0x160
[  184.402711] Modules linked in: xt_MASQUERADE iptable_nat xt_addrtype iptable_filter ip_tables xt_conntrack x_tables nf_nat nf_conntrack nf_defrag_ipv6 nf_defrag_ipv4 libcrc32c br_netfilter bridge overlay 8188eu(O) smsc95xx crct10dif_ce ina2xx
[  184.424188] CPU: 1 PID: 897 Comm: RTW_CMD_THREAD Tainted: G        W  O      5.4.70-g497a4c6 #14
[  184.432967] Hardware name: TLIMX8-EVM HDMI (DT)
[  184.437495] pstate: 40000005 (nZcv daif -PAN -UAO)
[  184.442284] pc : nl80211_send_chandef+0x150/0x160
[  184.446985] lr : nl80211_send_chandef+0x30/0x160
[  184.451598] sp : ffff80001ce73b80
[  184.454909] x29: ffff80001ce73b80 x28: ffff800011e9a0e4
[  184.460218] x27: ffff80001166cac0 x26: 0000000000000000
[  184.465527] x25: ffff80001ce73cb8 x24: ffff0000394cc800
[  184.470837] x23: ffff000038adc108 x22: ffff00003959aa00
[  184.476146] x21: ffff0000347e4014 x20: ffff00003844bc00
[  184.481455] x19: ffff80001ce73cb8 x18: 0000000000000000
[  184.486763] x17: 0000000000000000 x16: 0000000000000000
[  184.492072] x15: 0000000000000000 x14: 0000000000000000
[  184.497382] x13: 0000007242345855 x12: 0000000000000000
[  184.502690] x11: 0000000000000000 x10: 0000000000000000
[  184.507999] x9 : ffff00003fd87e50 x8 : ffff0000347e401c
[  184.513307] x7 : 0000000000000000 x6 : ffff0000347e401c
[  184.518616] x5 : 0000000000000000 x4 : 000000000000096c
[  184.523925] x3 : 000000000000096c x2 : 0000000000000000
[  184.529234] x1 : 0000000039729000 x0 : 0000000000000000
[  184.534543] Call trace:
[  184.536988]  nl80211_send_chandef+0x150/0x160
[  184.541344]  nl80211_ch_switch_notify.isra.0.constprop.0+0xe4/0x178
[  184.547607]  cfg80211_ch_switch_notify+0x7c/0xb0
[  184.552339]  rtw_cfg80211_ch_switch_notify+0xf4/0x130 [8188eu]
[  184.558238]  rtw_chk_start_clnt_join+0x270/0x3e0 [8188eu]
[  184.563693]  join_cmd_hdl+0x1d0/0x348 [8188eu]
[  184.568194]  rtw_cmd_thread+0x320/0x4c0 [8188eu]
[  184.572810]  kthread+0x138/0x158
[  184.576037]  ret_from_fork+0x10/0x1c
[  184.579609] ---[ end trace 7959c7c9134abb65 ]---
[  185.990794] IPv6: ADDRCONF(NETDEV_CHANGE): wlan0: link becomes ready
udhcpc: sending discover
udhcpc: sending select for 192.168.1.223
udhcpc: lease of 192.168.1.223 obtained, lease time 86400
/etc/udhcpc.d/50default: Adding DNS 192.168.1.1
wifi setup successfully!
root@IMX8-Tronlong:~#

四、驱动移植的理解

1. 一个I2C总线挂载多个从设备

一个I2C总线理论上可以挂载的设备数量取决于所使用的地址空间
对于标准7位地址空间,I2C协议允许最多 (2的7次方)128个 不同的地址(从0x00到0x7F)。
然而,实际上有几个地址是保留用于特殊用途的,比如通用调用地址和起始字节地址,所以实际可用的地址略少一些。
所以一个I2C总线最多挂载的设备是少于128个的。
所以一个I2C总线可以挂载多个设备。

比如下图的设备树可以看到,
一个i2c4的接口节点,有3个compatible,分别代表连接的设备为ds1307、isl1208、ov5640_mipi,这代表i2c-4上挂载了三种不同的设备:
一个兼容dallasds1307实时时钟(RTC)设备(地址0x68)
一个兼容isil.isl1208RTC设备(地址0x6f) ,
以及一个兼容ovti,ov5640 mipi摄像头模块(地址0x3c) .
只要它们的reg属性不同 (也就是12C的给他们分配的唯一的i2C地址) ,那这些设备挂载在一个i2C总线上就不会发生冲突,i2C总线是通过挂载在I2C的设备唯一的I2C地址识别是哪个设备,从而跟对应的设备通信,所以一个I2C总线接多个设备不会冲突。

在这里插入图片描述

2.设备树配置和i2c地址挂载的联系

2.1 使用命令扫描出挂载在I2C总线上的设备地址 (这个设备地址是设备连接对应的I2C总线时,I2C提供的唯一的地址)

下面是在linux系统中使用 i2cdetect -y x (x的值I2C总线的编号) 命令扫描出来的4个I2C总线各自挂载的设备的设备地址。
在这里插入图片描述
我的硬件设备有4个I2C总线,在原理图中编号分别为I2C1 I2C2 I2C3 I2C4,在系统设备文件的对照关系分别为:

原理图I2C1标识 、设备树i2c1 —— linux系统 /dev/i2c-0 设备文件
原理图I2C2标识 、设备树i2c2 —— linux系统 /dev/i2c-1 设备文件
原理图I2C3标识 、设备树i2c3 —— linux系统 /dev/i2c-2 设备文件
原理图I2C4标识 、设备树i2c4 —— linux系统 /dev/i2c-3 设备文件

这个对照关系可以通过一些命令来判断,因为有时候不一定是按顺序对应:
(命令可以问Ai:
在设备树中的定义了 I2C控制器节点的名称分别为:i2c1、i2c2、i2c3、i2c4,
但是在Linux系统中,我在 /dev 路径下通过 ls 出来的 i2c-0、i2c-1、i2c-2、i2c-3 是内核为I2C总线分配的编号,
那我怎么确定设备树中的I2C控制器节点名称 和 Linux系统中内核为I2C总线分配的编号这两者之间的对应关系)
在这里插入图片描述

2.2 设备树中的配置 和 系统文件i2c被扫描出来的设备地址 两者之间的联系

在这里插入图片描述

如上图:

1.设备树中i2c1中配置了以下设备:

  • 设备树pca9450@250x25)节点:在系统文件 i2c-0 中被扫描出设备地址0x25显示为 UUUU 表示该地址已被内核驱动占用,内核驱动占用,是因为我们在设备树上配置了这个设备,系统启动过程中,会加载内核,内核启动的过程中根据设备树的配置去加载了I2C总线中的这个地址,所以加载了这个设备,并且我们硬件也连接了这个设备,这说明驱动已加载。
  • 设备树ina220@400x40)节点:没有在系统文件 i2c-0 中被扫描出,但是在设备树 i2c1中我们有配置这个设备地址,说明可能是硬件没有连上i2c1总线。原因是系统启动过程中,会加载内核,内核启动的过程中根据设备树的配置去加载了I2C总线中的这个地址,但是我们I2C总线这个地址没有连接硬件,所以不会被扫描到。
  • 设备树ina220@410x41)节点:未在系统文件 i2c-0 中被扫描出,但是在设备树 i2c1中有配置,说明硬件没有连上i2c1总线。和上面同理

2.设备树中i2c2中没有配置任何设备:
设备树i2c2控制器没有配置任何设备,但是使用命令在系统文件i2c-1中扫描出了4个设备地址,说明有4个设备连接到了i2c2总线,只是没有在设备树中进行配置,所以没有内核驱动占用这4个设备地址,
在硬件上,这4个设备(不一定是4个设备,解析看 《3.一个功能芯片使用了3个I2C地址》)是连接上了I2C总线,并且没有被内核驱动占用,可以被用户使用。

3.设备树中i2c3中配置了以下设备:

  • tlv320aic3106@180x18)在系统文件i2c-2中被扫描出地址0x18显示为 UU,说明驱动已加载。
  • gpio@210x21):未在系统文件i2c-2中被扫描出,但是在设备树i2c3中有配置,说明可能硬件没有连接上i2c3总线。

4.设备树中i2c4中配置了以下设备:

  • rtc@680x68):在系统文件i2c-3中被扫描出地址0x68显示为 UU,说明驱动已加载。
  • rtc@6f0x6f):未在系统文件i2c-3中被扫描出,但是在设备树i2c4中有配置,说明硬件没有连上i2c4总线。
  • ov5640_mipi@3c0x3c):未在系统文件i2c-3中被扫描出,但是在设备树i2c4中有配置,说明硬件没有连上i2c4总线。

2.3 一些注意点

1.系统文件i2c3显示为UU的原因
  • UU 表示该地址已被内核驱动占用,用户空间无法直接访问。
  • 因为在设备树中,i2c4 总线上配置了 rtc@68 设备(0x68),并且其驱动已成功加载,所以显示为UU,说明已被内核驱动占用。

2. 系统文件i2c3**0x6f0x3c 未显示的原因**

设备树中配置了以下设备:

  • rtc@680x68):显示为 UU,驱动已加载。
  • rtc@6f0x6f):未显示。
  • ov5640_mipi@3c0x3c):未显示。

可能的原因包括:

(1)硬件未连接
  • 设备树中配置了设备,但实际硬件上并未连接到 i2c4 总线。
  • 例如:
    • 0x6f 的 RTC 设备未焊接或未连接。
    • 0x3c 的摄像头模块未连接。
(2)设备初始化失败
  • 设备已连接,但驱动初始化失败。
  • 可能的原因:
    • 设备供电异常。
    • 设备引脚配置错误(如 SDA、SCL 未正确连接)。
    • 设备驱动未正确加载。
(3)设备树配置错误
  • 设备树中配置的设备地址或兼容性字符串有误,导致驱动无法正确匹配。
  • 例如:
    • compatible 字符串错误。
    • 设备寄存器地址(reg)配置错误。
(4)设备被禁用
  • 设备树中配置了设备,但其状态为 disabled
  • 例如:
    ov5640_mipi: ov5640_mipi@3c {
        compatible = "ovti,ov5640_mipi";
        reg = <0x3c>;
        status = "disabled";  // 设备被禁用
    };
    

3. 排查步骤
(1)检查硬件连接
  • 确认 0x6f0x3c 设备是否实际连接到 i2c4 总线。
  • 使用万用表或示波器检查设备的电源、SDA、SCL 引脚是否正常。
(2)检查设备树配置
  • 确认设备树中 0x6f0x3c 设备的配置是否正确。
  • 例如,检查 compatible 字符串和 reg 地址:
    isl1208: rtc@6f {
        compatible = "isil,isl1208";  // 确认兼容性字符串正确
        reg = <0x6f>;                 // 确认地址正确
        status = "okay";              // 确认设备已启用
    };
    
    ov5640_mipi: ov5640_mipi@3c {
        compatible = "ovti,ov5640_mipi";  // 确认兼容性字符串正确
        reg = <0x3c>;                     // 确认地址正确
        status = "okay";                  // 确认设备已启用
    };
    
(3)检查内核日志
  • 使用 dmesg 查看内核日志,确认设备是否初始化失败:
    dmesg | grep i2c
    
  • 如果设备初始化失败,日志中会显示相关错误信息。
(4)手动探测设备
  • 使用 i2cgeti2cset 手动探测设备,确认设备是否存在。
  • 例如,探测 0x6f 设备:
    i2cget -y 3 0x6f
    
    • 如果设备存在,会返回数据。
    • 如果设备不存在,会返回错误。
(5)检查驱动加载
  • 确认设备的驱动是否已加载:
    lsmod | grep isl1208
    lsmod | grep ov5640
    
  • 如果驱动未加载,手动加载驱动:
    modprobe isl1208
    modprobe ov5640
    

4. 解决方法
(1)如果硬件未连接
  • 确认硬件设计,修复连接问题。
  • 如果设备不需要使用,可以从设备树中移除相关配置。
(2)如果设备初始化失败
  • 检查设备供电和引脚连接。
  • 检查设备树配置,确保 compatiblereg 正确。
  • 检查内核日志,修复驱动初始化问题。
(3)如果设备树配置错误
  • 修正设备树中的 compatible 字符串和 reg 地址。
  • 确保设备状态为 okay
(4)如果驱动未加载
  • 确保内核中已编译相关驱动。
  • 手动加载驱动,或修改设备树以正确匹配驱动。

5. 总结
  • 0x68 显示为 UU:设备已连接且驱动已加载。
  • 0x6f0x3c 未显示:可能是硬件未连接、设备初始化失败、设备树配置错误或驱动未加载。
  • 通过检查硬件连接、设备树配置、内核日志和驱动加载情况,可以定位并解决问题。

3. 一个芯片占用了三个I2C地址 —— LT8912B芯片使用三个I2C地址(0x48、0x49、0x4A)

一般情况下,某条I2C总线连接到了一个系统的主芯片,然后每个连接到这个I2C总线的设备占用一个I2C地址,一个设备对应一个I2C的地址。
如下面原理图1所示:目前这里的情况是,I2C-2总线连接到了系统的主芯片,然后MIPI TO HDMI这个功能模块使用了LT8912B芯片,但是这个芯片连接到这个I2C-2总线占用了3个I2C地址(0x48、0x49、0x4A)。
在这里插入图片描述
并且在通过命令i2cdetect -y 1扫描系统的设备文件dev/i2c-1中(原理图I2C-2对应系统设备文件i2c-1)的I2C地址,确实发现了这三个I2C地址(0x48、0x49、0x4A)。
另外一个0x4b应该是属于其他的功能模块连接到了I2C总线中,这里不做讨论。
还有原理图还提到了0x50,这个是用来插HDMI屏幕,跟HDMI进行通信的I2C设备地址。目前没有插HDMI屏幕这个硬件,所以使用命令i2cdetect -y 1没有扫描出来,等插上了屏幕,I2C总线连接上了这个硬件,就会被扫描出来了,所以这里不做讨论。
在这里插入图片描述

3.1 那为什么一个功能芯片会占用三个I2C地址呢?

根据官方提供的《2-1-评估板测试手册.pdf》资料中的测试功能列表,我们可以进一步分析LT8912B芯片使用三个I2C地址(0x48、0x49、0x4A)的可能原因。
从测试功能可以看出,LT8912B需要支持多种显示输出模式(HDMI、LVDS、MIPI)以及相关的配置和校准功能,每种模式可能有独立的配置寄存器组。通过使用不同的I2C地址,可以方便地对不同模式进行独立配置和管理,避免寄存器地址冲突。

  • 0x48:HDMI模式相关寄存器组 —— HDMI相关配置(分辨率、音频、EDID等)。
  • 0x49:LVDS模式相关寄存器组 —— LVDS相关配置(亮度调节、校准等)。
  • 0x4A:MIPI模式相关寄存器组 —— MIPI相关配置(亮度调节、校准等)

4. 加密芯片- 整个操作的目的是什么?有什么用?

  1. 目的:在板子(BL360_X8M)上实现 硬件级加密认证功能,确保设备唯一性和合法性,防止未授权的设备运行你的系统或软件。
  2. 用途
    • 防克隆:通过加密芯片存储唯一标识(UUID),防止他人复制你的硬件。
    • 安全启动:系统启动时验证加密芯片中的UUID,若不一致则拒绝运行。
    • 数据保护:可用于加密敏感数据(如固件、密钥),增强系统安全性。

完整操作流程与实现的功能

1. 准备加密芯片驱动和工具
  • 操作:将 rjgt102.tar.gz.temp 文件重命名为 rjgt102.tar.gz 并解压。
  • 作用:获取加密芯片(RJGT102)的驱动代码和示例程序,为后续编译做准备。
    mv rjgt102.tar.gz.temp rjgt102.tar.gz
    tar -xvf rjgt102.tar.gz
    
2. 修改I2C设备节点
  • 操作:在 i2c.c 文件中修改设备节点路径(如 /dev/i2c-0/dev/i2c-5)。
  • 原因:加密芯片通过I2C总线与主控芯片通信,需确保代码中的I2C节点与硬件实际连接一致。
    // 修改前
    #define DEV_PATH "/dev/i2c-0"  // 默认节点
    // 修改后(根据硬件原理图调整)
    #define DEV_PATH "/dev/i2c-5"  // 实际连接的I2C总线号
    
3. 配置交叉编译工具链
  • 操作:修改 Makefile 中的交叉编译器路径。
  • 原因:你的板子使用ARM架构处理器(如RK3562),需用对应的编译器生成可在板子上运行的程序。
    # 示例路径(需根据实际SDK路径修改)
    CC=/path/to/your/cross-compiler/aarch64-none-linux-gnu-gcc
    
4. 编译生成可执行文件
  • 操作:执行 make 命令,生成名为 rjgt102 的可执行文件。
  • 作用:编译后的程序将实现以下功能:
    1. 生成随机UUID并写入加密芯片。
    2. 将UUID保存到 /usr/rjgt_unique.json
    3. 每次运行程序时,从加密芯片读取UUID并与文件中的值对比,验证合法性。
    make
    
5. 部署并测试
  • 操作:将 rjgt102 文件拷贝到板子上运行。
  • 验证逻辑
    • 首次运行:生成UUID并写入加密芯片,保存到文件。
      root@bliiot: ./rjgt102
      # 输出:open unique file failed, create unique file!
      #       random uuid would write rjgt102: b6275e22-4928-4828-88fb-54a6fd8!
      #       Contrast success
      
    • 后续运行:读取加密芯片的UUID并与文件对比,一致则通过。
      root@bliiot: ./rjgt102
      # 输出:Contrast success
      

通俗的解释

  • 加密芯片的作用:类似于一个“电子身份证”,每个芯片有唯一的加密标识(UUID)。
  • 操作的核心逻辑
    1. 写身份证:首次运行时,给加密芯片写入一个随机生成的“身份证号”(UUID),并保存到文件。
    2. 查身份证:每次启动时,检查加密芯片的“身份证号”是否与文件中的一致。如果被篡改或克隆,验证失败,系统可拒绝运行。

关键注意事项

  1. 硬件连接:确保加密芯片正确连接到I2C总线(如原理图中的I2C-5)。
  2. 权限问题:程序需有权限访问 /dev/i2c-5/usr/rjgt_unique.json
  3. 看门狗功能:若RJGT102集成看门狗,程序还需定期“喂狗”,否则芯片会复位系统。

——————

5. 格式化SD卡,重新烧录系统,重新挂载分区

在这里插入图片描述

6. 【Ethernet网口】USB hub——USB设备层级拆解

分步详解与问题解答


1. 区分千兆网口与百兆网口

问题:系统中有 eth0eth1eth2 三个网口,如何确定哪个是千兆(RGMII)网口,哪个是百兆(USB)网口?


方法1:通过MAC地址和驱动信息
  • 步骤
    1. 执行以下命令查看网口详细信息:
      dmesg | grep -i "eth[0-9]"  # 查看内核启动日志中网口的驱动加载信息
      
    2. 观察输出中的关键信息:
      • 千兆网口(RGMII):通常会显示与 fec1(Flexible Ethernet Controller)相关的驱动,例如:
        fec 30be0000.ethernet eth0: registered PHC device 0
        
      • 百兆网口(USB):会显示 smsc95xx 驱动加载,例如:
        smsc95xx 1-1.4:1.0 eth1: register 'smsc95xx' at usb-0000:00:14.0-1.4
        

方法2:通过接口速度和MTU
  • 步骤
    1. 执行 ethtool 命令查看接口速率:
      ethtool eth0 | grep -i speed    # 千兆网口显示 "Speed: 1000Mb/s"
      ethtool eth1 | grep -i speed    # 百兆网口显示 "Speed: 100Mb/s"
      
    2. 示例输出
      # 千兆网口
      Speed: 1000Mb/s
      
      # 百兆网口
      Speed: 100Mb/s
      

方法3:通过物理连接验证
  • 步骤
    1. 拔插网线
      • 拔掉 eth0 的网线,观察 ifconfig 中哪个接口的 RX/TX 数据停止增长。
      • 插入百兆网口(USB_ETH1 或 USB_ETH2)的网线,观察哪个接口出现 RX 数据。

2. IPv4与IPv6的优先级问题

问题:为什么 ifconfig 显示 IPv4 地址,但 ping 默认使用 IPv6?


原因分析
  • IPv6优先级:Linux 系统默认优先使用 IPv6 协议(根据 /etc/gai.conf 的配置)。
  • DNS解析:当域名(如 www.baidu.com)同时有 IPv4 和 IPv6 地址时,系统优先选择 IPv6。

解决方案
  • 强制使用IPv4
    ping -4 www.baidu.com -I eth0   # 强制使用 IPv4
    
  • 修改优先级
    1. 编辑 /etc/gai.conf,找到以下行并取消注释:
      #precedence ::ffff:0:0/96  100
      
    2. 重启网络服务:
      systemctl restart networking
      

3. 解读 cat /sys/kernel/debug/usb/devices 输出
cd /sys/kernel/debug/usb
cat devices

使用cat /sys/kernel/debug/usb/devices命令去查看usb hub设备树层级
会出现如下日志内容:

T:  Bus=01 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#=  1 Spd=480  MxCh= 1
B:  Alloc=  4/800 us ( 1%), #Int=  3, #Iso=  0
D:  Ver= 2.00 Cls=09(hub  ) Sub=00 Prot=01 MxPS=64 #Cfgs=  1
P:  Vendor=1d6b ProdID=0002 Rev= 5.04
S:  Manufacturer=Linux 5.4.70-g497a4c6 ehci_hcd
S:  Product=EHCI Host Controller
S:  SerialNumber=ci_hdrc.1
C:* #Ifs= 1 Cfg#= 1 Atr=e0 MxPwr=  0mA
I:* If#= 0 Alt= 0 #EPs= 1 Cls=09(hub  ) Sub=00 Prot=00 Driver=hub
E:  Ad=81(I) Atr=03(Int.) MxPS=   4 Ivl=256ms

T:  Bus=01 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#=  2 Spd=480  MxCh= 4
D:  Ver= 2.00 Cls=09(hub  ) Sub=00 Prot=02 MxPS=64 #Cfgs=  1
P:  Vendor=05e3 ProdID=0610 Rev=60.60
S:  Product=USB2.0 Hub
C:* #Ifs= 1 Cfg#= 1 Atr=e0 MxPwr=100mA
I:  If#= 0 Alt= 0 #EPs= 1 Cls=09(hub  ) Sub=00 Prot=01 Driver=hub
E:  Ad=81(I) Atr=03(Int.) MxPS=   1 Ivl=256ms
I:* If#= 0 Alt= 1 #EPs= 1 Cls=09(hub  ) Sub=00 Prot=02 Driver=hub
E:  Ad=81(I) Atr=03(Int.) MxPS=   1 Ivl=256ms

T:  Bus=01 Lev=02 Prnt=02 Port=00 Cnt=01 Dev#=  3 Spd=480  MxCh= 0
D:  Ver= 2.00 Cls=ff(vend.) Sub=00 Prot=ff MxPS=64 #Cfgs=  1
P:  Vendor=0424 ProdID=9e00 Rev= 3.00
C:* #Ifs= 1 Cfg#= 1 Atr=80 MxPwr=500mA
I:* If#= 0 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=00 Prot=ff Driver=smsc95xx
E:  Ad=81(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
E:  Ad=02(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
E:  Ad=83(I) Atr=03(Int.) MxPS=  16 Ivl=1ms

T:  Bus=01 Lev=02 Prnt=02 Port=03 Cnt=02 Dev#=  4 Spd=480  MxCh= 0
D:  Ver= 2.00 Cls=ff(vend.) Sub=00 Prot=ff MxPS=64 #Cfgs=  1
P:  Vendor=0424 ProdID=9e00 Rev= 3.00
C:* #Ifs= 1 Cfg#= 1 Atr=80 MxPwr=500mA
I:* If#= 0 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=00 Prot=ff Driver=smsc95xx
E:  Ad=81(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
E:  Ad=02(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
E:  Ad=83(I) Atr=03(Int.) MxPS=  16 Ivl=1ms

问题:如何理解以下日志内容?

T:  Bus=01 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#=  1 Spd=480  MxCh= 1
B:  Alloc=  4/800 us ( 1%), #Int=  3, #Iso=  0
D:  Ver= 2.00 Cls=09(hub  ) Sub=00 Prot=01 MxPS=64 #Cfgs=  1
P:  Vendor=1d6b ProdID=0002 Rev= 5.04
S:  Manufacturer=Linux 5.4.70-g497a4c6 ehci_hcd
S:  Product=EHCI Host Controller
S:  SerialNumber=ci_hdrc.1
C:* #Ifs= 1 Cfg#= 1 Atr=e0 MxPwr=  0mA
I:* If#= 0 Alt= 0 #EPs= 1 Cls=09(hub  ) Sub=00 Prot=00 Driver=hub
E:  Ad=81(I) Atr=03(Int.) MxPS=   4 Ivl=256ms

逐字段解析
字段含义
T :设备拓扑(Topology)信息
- Bus=01USB总线编号(Bus 1)
- Lev=00设备层级(Root Hub为0级)
- Prnt=00父设备编号(Root Hub无父设备)
- Port=00在父设备上的端口号
- Cnt=00当前层级设备计数
- Dev#=1设备号(系统分配的编号)
- Spd=480速度(480 Mbps,即USB 2.0)
- MxCh=1最大子设备数(Root Hub支持1个子设备)
B:带宽分配(Bandwidth)
- Alloc=4/800 us已分配带宽占USB总带宽的比例(0.5%)
- #Int=3中断传输请求数
- #Iso=0等时传输请求数
D:设备描述符(Descriptor)
- Ver=2.00USB协议版本(2.0)
- Cls=09(hub)设备类(09表示Hub)
- Sub=00子类
- Prot=01协议
- MxPS=64最大数据包大小(64字节)
- #Cfgs=1配置描述符数量
P:设备标识(Product ID)
- Vendor=1d6b厂商ID(1d6b是Linux Foundation的保留ID)
- ProdID=0002产品ID(0002表示EHCI Host Controller)
- Rev=5.04固件版本
S:字符串描述符(String Descriptor)
- Manufacturer制造商信息(由内核虚拟生成)
- Product产品名称
- SerialNumber序列号(与设备树中的节点名对应)
C:配置描述符(Configuration)
- #Ifs=1接口数量
- Cfg#=1配置编号
- Atr=e0属性(总线供电、远程唤醒)
- MxPwr=0mA最大功耗
I:接口描述符(Interface)
- If#=0接口编号
- Alt=0备用设置编号
- #EPs=1端点数量
- Cls=09(hub)接口类(Hub)
- Driver=hub绑定的驱动
E:端点描述符(Endpoint)
- Ad=81(I)端点地址(81表示输入端点,编号1)
- Atr=03(Int.)传输类型(中断传输)
- MxPS=4最大数据包大小(4字节)
- Ivl=256ms轮询间隔

关键信息提取
  1. USB Hub的层级关系

    • Bus=01 Lev=00:Root Hub(第一级)。
    • Bus=01 Lev=01 Prnt=01:连接到 Root Hub 的 GL852G Hub(第二级)。
    • Bus=01 Lev=02 Prnt=02:连接到 GL852G Hub 的 LAN9500Ai 网卡(第三级)。
  2. 网卡识别

    • 查找 Cls=ff(vend.)Driver=smsc95xx,表示厂商自定义设备,使用 smsc95xx 驱动:
      T:  Bus=01 Lev=02 Prnt=02 Port=00 Cnt=01 Dev#=  3 Spd=480  MxCh= 0
      D:  Ver= 2.00 Cls=ff(vend.) Sub=00 Prot=ff MxPS=64 #Cfgs=  1
      P:  Vendor=0424 ProdID=9e00 Rev= 3.00
      C:* #Ifs= 1 Cfg#= 1 Atr=80 MxPwr=500mA
      I:* If#= 0 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=00 Prot=ff Driver=smsc95xx
      
      • Vendor=0424:SMSC(现为Microchip)的厂商ID。
      • ProdID=9e00:LAN9500Ai 的产品ID。

4. 验证硬件连接与驱动加载

问题:如何确认新网口(USB_ETH2)已正确连接?


步骤
  1. 查看USB设备树

    lsusb -t  # 显示USB设备层级
    

    示例输出

    /:  Bus 01.Port 1: Dev 1, Class=root_hub, Driver=ehci_hcd/1p, 480M
        |__ Port 1: Dev 2, If 0, Class=Hub, Driver=hub/4p, 480M
            |__ Port 1: Dev 3, If 0, Class=Vendor Specific, Driver=smsc95xx, 480M  # eth1
            |__ Port 4: Dev 4, If 0, Class=Vendor Specific, Driver=smsc95xx, 480M  # eth2
    
    • Port 1 对应 eth1Port 4 对应 eth2
  2. 检查驱动绑定

    ls -l /sys/bus/usb/drivers/smsc95xx  # 查看已绑定的设备
    

7. 【4G】在Linux系统中控制GPIO引脚的详细步骤

如何在系统中手动控制这个GPIO。
通常情况下,Linux系统通过sysfs接口提供GPIO的控制和状态查看。每个GPIO在sysfs中都有一个对应的目录,路径为/sys/class/gpio/gpio<number>,其中<number>是GPIO的全局编号。
例如对于GPIO2_10,要确定其对应的全局编号。由于i.MX8MM的GPIO组是从GPIO1开始的,每组有32个引脚,所以GPIO2_10的全局编号应该是(2-1)*32 + 10 = 42(怎么算出来的呢,因为一组有32个引脚,拿GPIO1有32个引脚,然后GPIO2_10是第二组GPIO的第10个引脚,所以GPIO2_10的引脚的全局编号是32+10 =42。可能因平台不同而有所变化,需要确认,可以百度i.MX8MM的GPIO2_10的引脚号是多少或者看芯片手册)。


7.1 确定GPIO2_10引脚的全局编号

在i.MX8MM平台中,GPIO的全局编号计算公式为:
全局编号 = (GPIO组号 - 1) * 32 + 引脚号
例如:

  • GPIO1_0(1-1)*32 + 0 = 0
  • GPIO2_10(2-1)*32 + 10 = 42
  • GPIO3_15(3-1)*32 + 15 = 79

验证方法:

# 查看GPIO映射(需要内核启用DEBUG_FS)
cat /sys/kernel/debug/gpio

输出中会显示所有已注册的GPIO,找到gpiochip1(对应GPIO2)的基地址,然后找到了我们自己在设备树给gpio-42(GPIO2_10)配置的节点名字:
在这里插入图片描述
在这里插入图片描述
此时,验证了GPIO2_10的全局编号确实为 32 + 10 = 42


7.2 导出GPIO到用户空间

通过sysfs接口操作GPIO需要先将其导出:

# 导出GPIO2_10(假设全局编号为42)
echo 42 > /sys/class/gpio/export
  • 成功标志:生成目录 /sys/class/gpio/gpio42
  • 常见错误
    • Device or resource busy:GPIO已被其他驱动占用(如设备树中的regulator-fixed节点)。
    • 解决方法
      在设备树中移除对该GPIO的占用(例如注释掉regulator-4g节点中的gpio属性)。

7.3 设置GPIO方向

GPIO需配置为输出模式才能控制电平:

# 设置为输出模式
echo "out" > /sys/class/gpio/gpio42/direction

7.4 控制GPIO电平

通过写入value文件控制电平:

# 拉高电平(3.3V)
echo 1 > /sys/class/gpio/gpio42/value

# 拉低电平(0V)
echo 0 > /sys/class/gpio/gpio42/value

7.5 查看GPIO当前状态
# 查看方向
cat /sys/class/gpio/gpio42/direction

# 查看电平值
cat /sys/class/gpio/gpio42/value

关键问题解答

1. 为什么GPIO2_10启动后是低电平?
  • 设备树配置
    如果在设备树中通过regulator-fixed节点配置了GPIO2_10为电源使能引脚(例如enable-active-low),则系统启动时会自动拉低该引脚。
    reg_4g_power: regulator-4g {
        gpio = <&gpio2 10 GPIO_ACTIVE_LOW>;  // 低电平使能
        enable-active-low;
        regulator-always-on;                 // 保持常开
    };
    
  • 是否“写死”
    • 如果regulator-always-on设为true,GPIO电平由驱动控制,用户无法通过sysfs修改。
    • 解决方法
      修改设备树,移除regulator-always-on或在不需要时关闭稳压器:
      reg_4g_power: regulator-4g {
          // ... 其他配置 ...
          regulator-always-on = <0>;  // 允许动态关闭
      };
      

2. 如何避免GPIO冲突?
  • 检查设备树
    确保GPIO2_10未被多个节点占用(如LED、按键、电源控制等)。
  • 释放已占用的GPIO
    如果GPIO被regulator-fixed占用,可以临时卸载驱动(需谨慎):
    # 查找驱动模块
    lsmod | grep gpio_regulator
    
    # 卸载模块(示例)
    rmmod gpio_regulator
    

完整操作示例

步骤1:导出并控制GPIO2_10
# 导出GPIO42(假设全局编号为42)
echo 42 > /sys/class/gpio/export

# 设置为输出模式
echo "out" > /sys/class/gpio/gpio42/direction

# 拉高电平(禁用4G电源)
echo 1 > /sys/class/gpio/gpio42/value

# 拉低电平(启用4G电源)
echo 0 > /sys/class/gpio/gpio42/value

# 查看当前电平
cat /sys/class/gpio/gpio42/value
步骤2:验证4G模块响应
# 插入4G模块后查看USB设备
lsusb

# 检查内核日志
dmesg | grep "New USB device"

总结

  • 控制GPIO本质:通过sysfs接口直接操作GPIO电平。
  • 设备树影响:若GPIO被其他驱动占用,需修改设备树释放控制权。
  • 4G模块工作流程
    1. 拉低GPIO2_10 → 使能电源
    2. USB控制器检测到设备 → 加载驱动
    3. 发起网络拨号 → 联网成功

五、常用命令

1. 分区挂载

查看连接的设备,设备的分区

sudo fdisk -l /dev/sda

查看设备挂载再哪个文件夹

lsblk
df -h

创建挂载目录

sudo mkdir /media/hugo/BOOT
sudo mkdir /media/hugo/rootfs
sudo mkdir /media/hugo/rootfs-backup

挂载磁盘

sudo mount /dev/sda1 /media/hugo/BOOT
sudo mount /dev/sda2 /media/hugo/rootfs
sudo mount /dev/sda3 /media/hugo/rootfs-backup

2. 网络

重启 SSH 服务:

sudo systemctl restart ssh
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值