正点原子 I.MX6ULL study 系统 USB 无线网卡联网实战:从无法启动到成功连接手机热点/局域网
正点原子 I.MX6ULL study 系统 USB 无线网卡联网实战:从无法启动到成功连接手机热点/局域网
目录
摘要
最近在学习正点原子的 I.MX6ULL 开发板,想在 study 系统里把 USB 无线网卡跑通,用来替代教程里常见的网线开发环境。
我的 USB 无线网卡型号通过 lsusb 识别为:
0bda:8176
对应 Realtek RTL8188CU / RTL8192CU 这一类芯片。
这次最终是成功的,而且不是仅仅“识别出网卡”,而是真正完成了:
- 驱动加载
- 无线认证
- DHCP 获取 IP
- 外网通信
- DNS 解析
最终成功的方案不是系统里原有的 8192cu.ko,而是基于内核源码重新编译:
- 新的
zImage rtlwifi.kortl_usb.kortl8192c-common.kortl8192cu.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.kortl_usb.kortl8192c-common.kortl8192cu.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 并不是一个完全独立的模块,它依赖:
rtlwifirtl_usbrtl8192c-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.ko 或 rtl8192c-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 私有驱动,而是:
rtlwifirtl_usbrtl8192c-commonrtl8192cu
这套标准 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
更多推荐
所有评论(0)