一、任务明确:把创龙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模块的使能信号。
操作步骤
-
删除冲突的LED配置
打开设备树文件(如dts.txt
),移除led@4
节点:leds { // ... 保留其他LED配置 ... // 删除以下内容: // led@4 { // label = "user-led2"; // gpios = <&gpio2 10 GPIO_ACTIVE_HIGH>; // default-state = "off"; // }; };
-
释放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接口
};
第四步:编译并更新设备树
-
编译设备树
进入内核源码目录,执行命令去生成.dtb设备树文件:make ARCH=arm64 your_board.dtb # 替换为你的板级设备树文件名
-
替换设备树文件
将生成的.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_wwan
或 usbserial
),生成 /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功能:
- 释放冲突的GPIO:将GPIO2_10从LED节点移除。
- 配置电源和复位:确保4G模块正确上电和初始化。
- 启用USB Host模式:识别4G模块的USB接口。
- 网络拨号配置:通过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.isl1208
的RTC设备(地址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@25
(0x25
)节点:在系统文件 i2c-0 中被扫描出设备地址0x25显示为UU
,UU
表示该地址已被内核驱动占用,内核驱动占用,是因为我们在设备树上配置了这个设备,系统启动过程中,会加载内核,内核启动的过程中根据设备树的配置去加载了I2C总线中的这个地址,所以加载了这个设备,并且我们硬件也连接了这个设备,这说明驱动已加载。 - 设备树
ina220@40
(0x40
)节点:没有在系统文件 i2c-0 中被扫描出,但是在设备树 i2c1中我们有配置这个设备地址,说明可能是硬件没有连上i2c1总线。原因是系统启动过程中,会加载内核,内核启动的过程中根据设备树的配置去加载了I2C总线中的这个地址,但是我们I2C总线这个地址没有连接硬件,所以不会被扫描到。 - 设备树
ina220@41
(0x41
)节点:未在系统文件 i2c-0 中被扫描出,但是在设备树 i2c1中有配置,说明硬件没有连上i2c1总线。和上面同理
2.设备树中i2c2中没有配置任何设备:
设备树i2c2控制器没有配置任何设备,但是使用命令在系统文件i2c-1中扫描出了4个设备地址,说明有4个设备连接到了i2c2总线,只是没有在设备树中进行配置,所以没有内核驱动占用这4个设备地址,
在硬件上,这4个设备(不一定是4个设备,解析看 《3.一个功能芯片使用了3个I2C地址》)是连接上了I2C总线,并且没有被内核驱动占用,可以被用户使用。
3.设备树中i2c3中配置了以下设备:
tlv320aic3106@18
(0x18
)在系统文件i2c-2中被扫描出地址0x18显示为UU
,说明驱动已加载。gpio@21
(0x21
):未在系统文件i2c-2中被扫描出,但是在设备树i2c3中有配置,说明可能硬件没有连接上i2c3总线。
4.设备树中i2c4中配置了以下设备:
rtc@68
(0x68
):在系统文件i2c-3中被扫描出地址0x68显示为UU
,说明驱动已加载。rtc@6f
(0x6f
):未在系统文件i2c-3中被扫描出,但是在设备树i2c4中有配置,说明硬件没有连上i2c4总线。ov5640_mipi@3c
(0x3c
):未在系统文件i2c-3中被扫描出,但是在设备树i2c4中有配置,说明硬件没有连上i2c4总线。
2.3 一些注意点
1.系统文件i2c3显示为UU的原因
UU
表示该地址已被内核驱动占用,用户空间无法直接访问。- 因为在设备树中,
i2c4
总线上配置了rtc@68
设备(0x68
),并且其驱动已成功加载,所以显示为UU
,说明已被内核驱动占用。
2. 系统文件i2c3**0x6f
和 0x3c
未显示的原因**
设备树中配置了以下设备:
rtc@68
(0x68
):显示为UU
,驱动已加载。rtc@6f
(0x6f
):未显示。ov5640_mipi@3c
(0x3c
):未显示。
可能的原因包括:
(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)检查硬件连接
- 确认
0x6f
和0x3c
设备是否实际连接到i2c4
总线。 - 使用万用表或示波器检查设备的电源、SDA、SCL 引脚是否正常。
(2)检查设备树配置
- 确认设备树中
0x6f
和0x3c
设备的配置是否正确。 - 例如,检查
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)手动探测设备
- 使用
i2cget
或i2cset
手动探测设备,确认设备是否存在。 - 例如,探测
0x6f
设备:i2cget -y 3 0x6f
- 如果设备存在,会返回数据。
- 如果设备不存在,会返回错误。
(5)检查驱动加载
- 确认设备的驱动是否已加载:
lsmod | grep isl1208 lsmod | grep ov5640
- 如果驱动未加载,手动加载驱动:
modprobe isl1208 modprobe ov5640
4. 解决方法
(1)如果硬件未连接
- 确认硬件设计,修复连接问题。
- 如果设备不需要使用,可以从设备树中移除相关配置。
(2)如果设备初始化失败
- 检查设备供电和引脚连接。
- 检查设备树配置,确保
compatible
和reg
正确。 - 检查内核日志,修复驱动初始化问题。
(3)如果设备树配置错误
- 修正设备树中的
compatible
字符串和reg
地址。 - 确保设备状态为
okay
。
(4)如果驱动未加载
- 确保内核中已编译相关驱动。
- 手动加载驱动,或修改设备树以正确匹配驱动。
5. 总结
0x68
显示为UU
:设备已连接且驱动已加载。0x6f
和0x3c
未显示:可能是硬件未连接、设备初始化失败、设备树配置错误或驱动未加载。- 通过检查硬件连接、设备树配置、内核日志和驱动加载情况,可以定位并解决问题。
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. 加密芯片- 整个操作的目的是什么?有什么用?
- 目的:在板子(BL360_X8M)上实现 硬件级加密认证功能,确保设备唯一性和合法性,防止未授权的设备运行你的系统或软件。
- 用途:
- 防克隆:通过加密芯片存储唯一标识(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
的可执行文件。 - 作用:编译后的程序将实现以下功能:
- 生成随机UUID并写入加密芯片。
- 将UUID保存到
/usr/rjgt_unique.json
。 - 每次运行程序时,从加密芯片读取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并写入加密芯片,保存到文件。
通俗的解释
- 加密芯片的作用:类似于一个“电子身份证”,每个芯片有唯一的加密标识(UUID)。
- 操作的核心逻辑:
- 写身份证:首次运行时,给加密芯片写入一个随机生成的“身份证号”(UUID),并保存到文件。
- 查身份证:每次启动时,检查加密芯片的“身份证号”是否与文件中的一致。如果被篡改或克隆,验证失败,系统可拒绝运行。
关键注意事项
- 硬件连接:确保加密芯片正确连接到I2C总线(如原理图中的I2C-5)。
- 权限问题:程序需有权限访问
/dev/i2c-5
和/usr/rjgt_unique.json
。 - 看门狗功能:若RJGT102集成看门狗,程序还需定期“喂狗”,否则芯片会复位系统。
——————
5. 格式化SD卡,重新烧录系统,重新挂载分区
6. 【Ethernet网口】USB hub——USB设备层级拆解
分步详解与问题解答
1. 区分千兆网口与百兆网口
问题:系统中有 eth0
、eth1
、eth2
三个网口,如何确定哪个是千兆(RGMII)网口,哪个是百兆(USB)网口?
方法1:通过MAC地址和驱动信息
- 步骤:
- 执行以下命令查看网口详细信息:
dmesg | grep -i "eth[0-9]" # 查看内核启动日志中网口的驱动加载信息
- 观察输出中的关键信息:
- 千兆网口(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
- 千兆网口(RGMII):通常会显示与
- 执行以下命令查看网口详细信息:
方法2:通过接口速度和MTU
- 步骤:
- 执行
ethtool
命令查看接口速率:ethtool eth0 | grep -i speed # 千兆网口显示 "Speed: 1000Mb/s" ethtool eth1 | grep -i speed # 百兆网口显示 "Speed: 100Mb/s"
- 示例输出:
# 千兆网口 Speed: 1000Mb/s # 百兆网口 Speed: 100Mb/s
- 执行
方法3:通过物理连接验证
- 步骤:
- 拔插网线:
- 拔掉
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
- 修改优先级:
- 编辑
/etc/gai.conf
,找到以下行并取消注释:#precedence ::ffff:0:0/96 100
- 重启网络服务:
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=01 | USB总线编号(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.00 | USB协议版本(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 | 轮询间隔 |
关键信息提取
-
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 网卡(第三级)。
-
网卡识别:
- 查找
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)已正确连接?
步骤
-
查看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
对应eth1
,Port 4
对应eth2
。
-
检查驱动绑定:
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模块工作流程:
- 拉低GPIO2_10 → 使能电源
- USB控制器检测到设备 → 加载驱动
- 发起网络拨号 → 联网成功
五、常用命令
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