硬件:iMX6ULL 开发板 + RTL8189FTV WiFi 模块(SDIO 接口)
内核:Linux 4.14
目标:编译 8189fs.ko,加载驱动,连接 WiFi 热点
一、硬件与驱动对应关系
| 芯片丝印 | 驱动名称 | 接口 |
|---|---|---|
| RTL8189FTV | rtl8189fs | SDIO |
| RTL8189ES | rtl8189es | SDIO |
RTL8189FTV 是 RTL8189FS 的不同封装变体(FTV = Fine pitch Thin package with exposed pad V-shape),内核驱动完全相同,使用 rtl8189fs 驱动。
该驱动是树外驱动(out-of-tree),不在 Linux 主线内核中,需要单独获取源码后集成到内核树。
二、系统层次结构
用户层: wpa_supplicant / ifconfig / iwlist
↓
内核层: cfg80211 / mac80211(Linux WiFi 协议栈)
↓
驱动层: 8189fs.ko(SDIO 设备驱动,注册到 mac80211)
↓
总线层: MMC/SDIO 子系统
↓
硬件层: iMX6ULL SDIO 控制器 → RTL8189FTV 芯片
三、驱动集成步骤
3.1 放置驱动源码
将 rtl8189FS 源码目录放入内核树:
drivers/net/wireless/realtek/rtl8189FS/
├── Kconfig
├── Makefile
├── core/
├── hal/
├── include/
├── os_dep/
└── platform/
3.2 修改上层 Makefile
编辑 drivers/net/wireless/realtek/Makefile,添加:
obj-$(CONFIG_RTL8189FS) += rtl8189FS/
3.3 修改上层 Kconfig
编辑 drivers/net/wireless/realtek/Kconfig,添加:
source "drivers/net/wireless/realtek/rtl8189FS/Kconfig"
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- menuconfig
路径:Device Drivers → Network device support → Wireless LAN → Realtek devices → RTL8189FS
选择 M(编译为模块),不选 Y(选 Y 会编译进内核,不生成 .ko 文件)。
3.5 编译模块
# 只编译该模块,速度快
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf-
M=drivers/net/wireless/realtek/rtl8189FS modules
# 编译完成后 .ko 文件在驱动目录下
ls drivers/net/wireless/realtek/rtl8189FS/8189fs.ko
3.6 拷贝到开发板
# 通过 NFS 或 scp 拷贝到开发板
cp drivers/net/wireless/realtek/rtl8189FS/8189fs.ko /nfsroot/
四、加载驱动
insmod 8189fs.ko
正常输出:
RTL871X: module init start
RTL871X: rtl8189fs v4.3.24.8_22657.20170607
RTL871X: rtw_ndev_init(wlan0) if1 mac_addr=30:4a:26:b0:b9:af
RTL871X: module init ret=0
⚠️ 加载时会出现
WARNING: possible recursive locking detected警告,这是 RTL8189FS 驱动在 Linux 4.14 上的已知历史遗留问题(rtw_alloc_stainfo和rtw_alloc_macid嵌套获取同类型自旋锁触发 lockdep 检测)。实际运行不会死锁,可忽略。
验证 wlan0 接口已创建:
ifconfig wlan0
# 或
ip link show wlan0
五、扫描与连接 WiFi
5.1 激活接口
ifconfig wlan0 up
# 内核会打印 "wlan0: link is not ready",正常现象(还未关联 AP)
5.2 扫描周围热点
iwlist wlan0 scan | grep ESSID
5.3 创建 wpa_supplicant 配置文件
cat > /etc/wpa_supplicant.conf << 'EOF'
ctrl_interface=/var/run/wpa_supplicant
network={
ssid="你的WiFi名称"
psk="你的WiFi密码"
key_mgmt=WPA-PSK
}
EOF
注:该 rootfs 没有
wpa_passphrase工具,需手动创建配置文件。
5.4 后台连接
wpa_supplicant -B -i wlan0 -c /etc/wpa_supplicant.conf
连接成功的 dmesg 日志:
RTL871X: start auth
RTL871X: auth success, start assoc
RTL871X: assoc success
RTL871X: recv eapol packet ← WPA2 四次握手开始
RTL871X: send eapol packet
RTL871X: set pairwise key camid:4, type:AES ← 单播密钥
wlan0: link becomes ready
RTL871X: set group key camid:5, type:TKIP ← 组播密钥
5.5 获取 IP
udhcpc -i wlan0
# 应输出:lease of 192.168.2.xxx obtained
⚠️ BusyBox udhcpc 的坑:
lease obtained只表示 DHCP 协商成功,但 BusyBox 的 udhcpc 依赖/usr/share/udhcpc/default.script将 IP 实际写入接口。若该脚本不存在,ifconfig wlan0看不到 IPv4 地址。解决方法:手动配置(将 xxx 替换为 udhcpc 获取到的实际 IP):
ifconfig wlan0 192.168.2.xxx netmask 255.255.255.0
5.6 配置默认路由
udhcpc 不一定自动添加默认网关,需手动补充:
# 添加默认网关
route add default gw 192.168.2.1 dev wlan0
# 验证路由表
route -n
注:若开发板同时接有 eth0(有线网络),路由表中会出现两条
192.168.2.0/24路由,eth0 那条优先级更高(先添加)。局域网流量走 eth0,外网流量走 wlan0 默认路由,互不干扰。
5.7 配置 DNS
echo "nameserver 192.168.2.1" > /etc/resolv.conf
使用路由器作为 DNS 服务器(192.168.2.1),路由器会转发 DNS 查询到上游。也可填写其他 DNS,但需确认运营商未屏蔽该地址。
六、验证网络连通性
# ping 路由器(验证 wlan0 局域网通信)
ping -I wlan0 192.168.2.1 -c 3
# 验证外网 TCP 连接(最可靠)
wget -O /dev/null http://neverssl.com
# 输出 100% 下载完成即为外网畅通
⚠️ 注意事项:
- 不要用
ping测试外网:中国联通等运营商在 ISP 层面屏蔽 ICMP,ping 外网全部超时,但 HTTP 完全正常。- 不要用
wget http://baidu.com:百度会将 HTTP 重定向到 HTTPS,而 BusyBox 的 wget 不支持 HTTPS(无 SSL/TLS),会报error getting response。改用 neverssl.com(永远不跳 HTTPS 的测试站)。
七、已知问题与说明
- 外网连通性验证:ICMP 被运营商屏蔽;改用
wget -O /dev/null http://neverssl.com验证,下载成功,外网畅通 - ko 文件持久化:将 8189fs.ko 安装到
/lib/modules/$(uname -r)/并执行depmod,实现modprobe加载 - 开机自动连接:暂不配置,开发阶段手动连接即可(
modprobe 8189fs→ifconfig wlan0 up→wpa_supplicant→udhcpc)
关联笔记
- MMC-SD-SDIO协议概述 — SDIO 接口原理,RTL8189 通过 SDIO 与 iMX6ULL 通信
- WSL2搭建iMX6ULL开发环境完整教程 — 编译环境搭建,ko 文件传输方式
延伸阅读
WiFi 驱动可用吞吐测试验证效果,底层适配问题则常需回到内核与设备树。




