正点原子 I.MX6ULL study 系统 USB 无线网卡联网实战:从无法启动到成功连接手机热点/局域网

目录



摘要

最近在学习正点原子的 I.MX6ULL 开发板,想在 study 系统里把 USB 无线网卡跑通,用来替代教程里常见的网线开发环境。
我的 USB 无线网卡型号通过 lsusb 识别为:

0bda:8176

对应 Realtek RTL8188CU / RTL8192CU 这一类芯片。

这次最终是成功的,而且不是仅仅“识别出网卡”,而是真正完成了:

  • 驱动加载
  • 无线认证
  • DHCP 获取 IP
  • 外网通信
  • DNS 解析

最终成功的方案不是系统里原有的 8192cu.ko,而是基于内核源码重新编译:

  • 新的 zImage
  • rtlwifi.ko
  • rtl_usb.ko
  • rtl8192c-common.ko
  • rtl8192cu.ko

并通过:

wpa_supplicant -D nl80211

成功连接手机热点。

本文先讲最终成功路径,再统一总结过程中踩过的坑。


一、环境说明

1. 硬件与系统

  • 开发板:正点原子 I.MX6ULL
  • 系统:study 版 Linux
  • 启动介质:eMMC
  • USB 无线网卡:0bda:8176
  • 开发环境:Ubuntu 虚拟机 + 交叉编译工具链

2. 无线网卡识别

在开发板上执行:

lsusb

得到:

Bus 001 Device 003: ID 0bda:8176

这说明 USB 网卡硬件本身是能被系统识别到的。


二、最终成功路径

这一部分只讲最后证明有效的路线,适合后续直接复现。

1. 先修正 study 系统启动参数

最开始 study 系统启动时,U-Boot 还在加载错误的设备树文件,导致内核启动异常。
最终使用的 eMMC 启动参数如下:

setenv bootcmd 'mmc dev 1;fatload mmc 1:1 80800000 zImage;fatload mmc 1:1 83000000 imx6ull-alientek-emmc.dtb;bootz 80800000 - 83000000'
setenv bootargs 'console=ttymxc0,115200 root=/dev/mmcblk1p2 rootwait rw'
saveenv

这里的核心是:

  • zImage 要与当前编译的内核一致
  • dtb 要使用正确的 imx6ull-alientek-emmc.dtb

如果设备树文件名不对,系统即使勉强启动,后面很多现象也会非常混乱。


2. 修改内核配置并重新编译内核

为了让无线驱动链正常工作,最终我在内核中启用了以下配置:

CONFIG_WIRELESS_EXT=y
CONFIG_WEXT_CORE=y
CONFIG_WEXT_PROC=y
CONFIG_WEXT_PRIV=y
CONFIG_CFG80211_WEXT=y

CONFIG_RTL_CARDS=y
CONFIG_RTLWIFI=m
CONFIG_RTLWIFI_USB=m
CONFIG_RTL8192C_COMMON=m
CONFIG_RTL8192CU=m

在源码目录中,可以使用:

./scripts/config --enable WIRELESS_EXT
./scripts/config --enable WEXT_CORE
./scripts/config --enable WEXT_PROC
./scripts/config --enable WEXT_PRIV
./scripts/config --enable CFG80211_WEXT

./scripts/config --module RTLWIFI
./scripts/config --module RTLWIFI_USB
./scripts/config --module RTL8192CU
./scripts/config --module RTL8192C_COMMON

make oldconfig

然后重新编译内核:

make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- -j$(nproc) zImage

原理说明

这里要强调一点:

  • 无线驱动能不能工作,不只是模块的问题
  • 运行中的内核本身也要具备相应的无线子系统支持

尤其是之前遇到的 wireless_send_event 未定义问题,实际上就是运行内核本身缺少对应支持,而不是单纯重编模块就能解决。


3. 编译最终成功的驱动模块

最终成功联网,使用的是 Linux 标准 rtlwifi 驱动链,而不是系统中原本带的那个 8192cu.ko

最终编译成功的模块有 4 个:

  • rtlwifi.ko
  • rtl_usb.ko
  • rtl8192c-common.ko
  • rtl8192cu.ko

关键编译命令如下:

make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- -j$(nproc) \
  drivers/net/wireless/rtlwifi/rtl8192c/rtl8192c-common.ko

make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- -j$(nproc) \
  drivers/net/wireless/rtlwifi/rtl8192cu/rtl8192cu.ko

编译完成后,相关文件位于:

drivers/net/wireless/rtlwifi/rtlwifi.ko
drivers/net/wireless/rtlwifi/rtl_usb.ko
drivers/net/wireless/rtlwifi/rtl8192c/rtl8192c-common.ko
drivers/net/wireless/rtlwifi/rtl8192cu/rtl8192cu.ko

原理说明

这里之所以最后能成功,是因为 rtl8192cu 并不是一个完全独立的模块,它依赖:

  • rtlwifi
  • rtl_usb
  • rtl8192c-common

一开始只盯着 rtl8192cu.ko 去编译和加载,后面一直报各种符号未定义,本质上就是因为它后面还有一层公共依赖没拉全。


4. 通过 SD 卡将文件传到开发板

在网络还没打通之前,我采用的是最稳妥的方式:

  • 虚拟机中编译
  • 复制到 SD 卡
  • 开发板挂载 SD 卡后再复制到系统目录

将以下文件复制到 SD 卡:

cp drivers/net/wireless/rtlwifi/rtlwifi.ko /media/maomao/E5FB-CD25/
cp drivers/net/wireless/rtlwifi/rtl_usb.ko /media/maomao/E5FB-CD25/
cp drivers/net/wireless/rtlwifi/rtl8192c/rtl8192c-common.ko /media/maomao/E5FB-CD25/
cp drivers/net/wireless/rtlwifi/rtl8192cu/rtl8192cu.ko /media/maomao/E5FB-CD25/
cp arch/arm/boot/zImage /media/maomao/E5FB-CD25/
sync

在开发板上挂载 SD 卡:

mount -t vfat /dev/mmcblk0p1 /mnt/sd

将模块复制到系统目录:

cp /mnt/sd/rtlwifi.ko /lib/modules/4.1.15/
cp /mnt/sd/rtl_usb.ko /lib/modules/4.1.15/
cp /mnt/sd/rtl8192c-common.ko /lib/modules/4.1.15/
cp /mnt/sd/rtl8192cu.ko /lib/modules/4.1.15/
sync

同时把新 zImage 替换到 eMMC 启动分区:

mount -t vfat /dev/mmcblk1p1 /mnt/boot
cp /mnt/boot/zImage /mnt/boot/zImage.old
cp /mnt/sd/zImage /mnt/boot/zImage
sync

原理说明

在嵌入式开发中,网络环境不稳定时,SD 卡/U 盘中转反而是最可靠的方式。
这也是为什么很多时候不要一开始死磕网络传输,先用最稳的方法把文件送上去更重要。


5. 按依赖顺序加载模块

替换完文件后,在开发板上先卸掉旧模块:

killall wpa_supplicant 2>/dev/null

rmmod 8192cu 2>/dev/null
rmmod rtl8192cu 2>/dev/null
rmmod rtl8192c_common 2>/dev/null
rmmod rtl_usb 2>/dev/null
rmmod rtlwifi 2>/dev/null

然后按依赖顺序加载新模块:

insmod /lib/modules/4.1.15/rtlwifi.ko
insmod /lib/modules/4.1.15/rtl_usb.ko
insmod /lib/modules/4.1.15/rtl8192c-common.ko
insmod /lib/modules/4.1.15/rtl8192cu.ko

之后可以看到 wlan0 接口。

原理说明

模块之间是有依赖关系的。
如果先加载 rtl8192cu.ko,但 rtlwifi.kortl8192c-common.ko 还没加载,就会报错。


6. 配置 Wi-Fi 并成功联网

我最终连接的是手机热点:

  • SSID:maomaoWang
  • 密码:88888888
  • 频段:2.4GHz

先创建配置文件:

cat > /etc/wpa_supplicant.conf <<'EOF'
ctrl_interface=/var/run/wpa_supplicant
ap_scan=1
network={
    ssid="maomaoWang"
    psk="88888888"
}
EOF

联网命令如下:

ifconfig wlan0 up
killall wpa_supplicant 2>/dev/null
wpa_supplicant -B -D nl80211 -i wlan0 -c /etc/wpa_supplicant.conf
udhcpc -i wlan0

最终获取到地址:

10.216.234.197

并成功 ping 通:

ping -c 4 10.216.234.176
ping -c 4 8.8.8.8
ping -c 4 www.baidu.com

原理说明

这一步里最关键的是:

  • 最终成功的是 nl80211
  • 不是 wext

这说明最终生效的是标准 Linux 无线控制路径,而不是之前那套老式私有接口。


三、最终验证结果

联网成功后,ifconfig wlan0 输出如下:

wlan0     Link encap:Ethernet  HWaddr 00:1F:05:73:8C:A2
          inet addr:10.216.234.197  Bcast:10.216.234.255  Mask:255.255.255.0
          inet6 addr: fe80::21f:5ff:fe73:8ca2/64 Scope:Link
          inet6 addr: 2409:8900:1a90:91e:21f:5ff:fe73:8ca2/64 Scope:Global
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1

网络测试结果:

  • 网关可达
  • 外网可达
  • DNS 解析正常

这说明:

  • 驱动链 OK
  • 无线认证 OK
  • DHCP OK
  • 路由 OK
  • DNS OK

到这里可以确认:
study 系统 USB 无线联网改造完全成功。


四、问题总结:这次踩过的坑

这一部分专门总结我过程中遇到的坑。
如果你也在折腾同类问题,我建议重点看这一节。

1. 第一个坑:study 系统并不是开箱即用

最开始我以为把 study 系统烧进去以后,至少能像出厂系统那样直接启动。
结果实际上,U-Boot 还是旧的 EVK 逻辑,启动时加载的是错误的 dtb。

这个坑告诉我:

在嵌入式开发里,系统能不能正常启动,内核镜像和 dtb 匹配是最基本的前提。


2. 第二个坑:lsusb 能看到设备,不等于驱动已经好了

我最开始看到:

0bda:8176

还挺高兴,以为系统至少已经“支持这块网卡”了。
但后面发现:

  • lsusb 只能说明 USB 总线识别到了设备
  • 并不代表无线驱动已经绑定
  • 更不代表无线接口已经可用

这是 Linux 里很典型的一个误区。


3. 第三个坑:系统里有模块,不代表模块真的能用

当我发现系统里有:

/lib/modules/4.1.15/8192cu.ko

当时是真的以为问题快结束了。
结果一加载,全是:

disagrees about version of symbol
Unknown symbol

这个坑很有代表性:

路径和文件名对,不代表模块就是当前内核构建出来的。

在开启 CONFIG_MODVERSIONS=y 的内核里,这种“历史残留模块”尤其容易骗人。


4. 第四个坑:wlan0 出现,不代表联网快成功了

后来 extra 8192cu 驱动终于把 wlan0 弄出来了,我一度觉得马上就能联网。

结果现实是:

  • wext 控制失败
  • nl80211 也不支持认证/关联

也就是说:

  • 设备接口出来了
  • 但控制面根本不完整

这个阶段是全程最容易让人产生错觉的地方。


5. 第五个坑:差点误以为标准 rtlwifi 路线也走不通

切换到 rtlwifi 路线后,一开始又报了一大堆 rtl92c_* 未定义。
说实话,这时候真的很容易想放弃。

因为当时感觉像是:

  • old 驱动不行
  • new 驱动也不行
  • 模块一直在报 undefined symbol

但最后查源码发现:

  • 这些符号其实都在 rtl8192c-common
  • 而且还 EXPORT_SYMBOL
  • 只是依赖没有完全拉起来

这一步如果不往下查,很容易误判为“这条路线也完全不可用”。


6. 第六个坑:热点关了,表象会特别像驱动问题

后面成功用 nl80211 启动 wpa_supplicant 后,udhcpc 还在一直 discover
一开始也很容易怀疑驱动。

后来才发现:

是我手机热点关了。

这也是个很真实的坑:

  • 如果 AP 不存在
  • 驱动和配置再对
  • DHCP 也不可能成功

所以排障时一定要确认测试环境本身是存在的。


7. 第七个坑:5GHz 热点不要拿来测这类老 Realtek 网卡

我中途还试过 5GHz Wi-Fi 6 热点,后来才意识到这类老 RTL8188CU/RTL8192CU 基本不适合拿 5GHz 来测。

最终真正成功的是:

  • 2.4GHz
  • WPA2-个人
  • 802.11n
  • 手机热点

这说明测试环境本身也非常重要。


五、这次改造的最终结论

这次最终成功,不是靠“多试几条命令”碰出来的,而是靠下面这三件事同时做对了:

1. 修正 study 系统启动环境

包括:

  • 正确的 bootcmd
  • 正确的 dtb
  • 正确的 zImage

2. 修正内核配置

包括:

  • WEXT 相关配置
  • rtlwifi 相关配置
  • rtl8192c-common 依赖配置

3. 选对驱动路线

最终成功的不是系统自带模块,也不是 extra 8192cu 私有驱动,而是:

  • rtlwifi
  • rtl_usb
  • rtl8192c-common
  • rtl8192cu

这套标准 Linux 驱动链。


六、建议保存的一键联网脚本

既然最后已经成功联网,建议顺手做一个脚本,省得每次手敲:

cat > /usr/bin/wifi-up.sh <<'EOF'
#!/bin/sh
ifconfig wlan0 up
killall wpa_supplicant 2>/dev/null
wpa_supplicant -B -D nl80211 -i wlan0 -c /etc/wpa_supplicant.conf
udhcpc -i wlan0
EOF

chmod +x /usr/bin/wifi-up.sh

以后联网只要:

wifi-up.sh

七、结语

这次折腾最大的感受是:

嵌入式开发里最难的,往往不是某一条命令,而是整条链路。

这次无线联网看起来只是“让 study 系统连个 Wi-Fi”,但最后实际涉及了:

  • U-Boot
  • dtb
  • 内核配置
  • 内核重编
  • 模块重编
  • 模块依赖
  • 无线子系统
  • wpa_supplicant
  • 热点环境

中间确实几次差点放弃。
尤其是在:

  • wlan0 都出来了还是连不上
  • 标准驱动一开始也报 undefined symbol

那种时候最容易怀疑人生。

但好在最后还是打通了。
如果你也在折腾正点原子 I.MX6ULL 的 study 系统 USB 无线网卡,希望这篇文章能帮你少走一些弯路。


八、附:关键命令汇总

1. 编译内核

make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- -j$(nproc) zImage

2. 编译驱动

make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- -j$(nproc) \
  drivers/net/wireless/rtlwifi/rtl8192c/rtl8192c-common.ko

make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- -j$(nproc) \
  drivers/net/wireless/rtlwifi/rtl8192cu/rtl8192cu.ko

3. 加载驱动

insmod /lib/modules/4.1.15/rtlwifi.ko
insmod /lib/modules/4.1.15/rtl_usb.ko
insmod /lib/modules/4.1.15/rtl8192c-common.ko
insmod /lib/modules/4.1.15/rtl8192cu.ko

4. 联网

ifconfig wlan0 up
wpa_supplicant -B -D nl80211 -i wlan0 -c /etc/wpa_supplicant.conf
udhcpc -i wlan0
Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐