简介:RTL8189FS Linux驱动包是由Realtek官方提供的无线网卡驱动源码包,面向嵌入式Linux或Android开发者,专为海思平台上的RTL8189FS芯片移植、编译与调试设计,支持802.11b/g/n标准,并针对设备厂商提供了一站式驱动方案。包内共45个文件,约15.53MB,包括23份PDF文档、10个gz压缩包、4个diff补丁、4个conf配置文件、2个txt说明、1个sh脚本和1个tgz包,涵盖驱动源码、编译脚本、HAL层、配置文件和用户空间工具,并包含README说明和测试程序。驱动包覆盖Android 4.4、5.x、8.0、9.0等版本对应的Wi-Fi SDK,并提供wpa_supplicant/hostapd工具集,以及TDLS、WOW、SoftAP等功能的说明文档。已有995人学习使用。开发者可借助Quick Start系列快速完成环境搭建,通过diff补丁移植内核模块,利用配置和测试工具验证无线功能;文档按版本和功能模块分类,结构清晰,定位便捷,是一套适用于设备厂商和驱动开发人员的完整参考资源。 干了这么多年嵌入式Linux,跟射频芯片驱动的爱恨情仇能写一箩筐。今天要拆的RTL8189FS_linux_v5.7.9_35795.20191128.zip,是Realtek官方放出来的RTL8189FS WiFi模组Linux驱动包。这颗芯片在低成本的平板、电视盒子、工控板、开源开发板上出现频率极高,SDIO接口,2.4GHz单频,802.11 b/g/n,架构简单到没什么可吹的,但它恰恰是很多设备联网的唯一通道。
这个zip包里的东西说复杂不复杂,说简单也不简单。很多人拿到手,第一反应是丢给内核编译一下,结果不是编译报错,就是加载后wlan0不出现,再不然就是频繁掉线。我自己在好几个方案上都踩过同样的坑,所以这篇文章打算把这包驱动的完整使用链路从头到尾捋一遍:怎么认识包名、怎么配交叉编译、怎么加载固件、怎么调设备树,最后把常见坑也列出来。无论你是刚入行的学生,还是半路接手项目的工程师,照着这个流程走,基本能把RTL8189FS整明白。
1. 拆解包名:RTL8189FS、v5.7.9和35795这些数字到底是什么意思
1.1 先搞清楚芯片本身是什么
RTL8189FS是瑞昱推出的一颗SDIO接口WiFi芯片,工作在2.4GHz频段,支持802.11 b/g/n,空间流只有1x1,最高协商速率72.2Mbps。这颗芯片最大的特点是便宜、外围器件少、内部集成了PA和LNA,所以模组厂做出来pcb面积可以做到很小,非常适合对成本敏感的消费类产品。
它跟USB WiFi芯片RTL8188FU是同一个IP体系的兄弟芯片,只不过接口从USB换成了SDIO。两种芯片的驱动代码结构几乎一样,很多厂商在移植的时候,甚至会把8188FU的驱动改个名字来用。这也解释了为什么你在翻代码的时候会看到很多重复的宏定义和ifdef分支。
这颗芯片在市场上的定位很清晰:不需要太高的吞吐量,但要求连接稳定、成本可控。比如Linux单板的学习板、安卓平板、OTT盒子、智能家电的联网模组,这些都是RTL8189FS的典型用武之地。它走SDIO把数据交到主控SoC,不占用USB控制器资源,对同时需要挂U盘、4G模组、蓝牙等USB设备的方案来说,比USB WiFi更友好。
1.2 版本号v5.7.9不是Linux内核版本
这是我把很多工程师带跑偏的地方。看到文件名里的v5.7.9,下意识以为驱动要求内核5.7.9,实际上这是瑞昱自己的驱动版本号。瑞昱的驱动包命名规则一直是“芯片型号_操作系统_驱动版本_内部构建号.zip”,所以35795.20191128是瑞昱内部构建号加构建日期,代表2019年11月28日编译的版本。
驱动版本和内核版本没有一一对应关系,这对移植很关键。RTL8189FS官方这套驱动的代码是基于Linux 3.x到4.x时代的内核接口写的,如果你把它拿到Linux 5.15甚至更高版本的内核上直接编译,大概率会遇到API不兼容的报错。这不是驱动坏了,而是内核变了,驱动没跟上。
注意:判断驱动能不能用,要看的是SoC厂商BSP里自带的内核版本,以及是否有过适配补丁,而不是驱动包文件名里的版本号。
我经手过的项目里,有在Linux 3.10的老内核上跑得好好的,也有在Linux 5.4内核上被补丁修过之后正常工作的。最稳妥的办法是先找主控厂商(Rockchip、Amlogic、Allwinner这些)提供的BSP源码里是否已经带了对应的RTL8189FS驱动分支,如果没有,再回到官方包基础上自己打补丁。
2. 拿到源码包后的第一件事:目录结构与构建前准备
2.1 解压并看懂目录结构
先把包解压出来:
unzip RTL8189FS_linux_v5.7.9_35795.20191128.zip tar -xjf RTL8189FS_linux_v5.7.9_35795.20191128.tar.bz2 cd RTL8189FS_linux_v5.7.9_35795.20191128打开目录后别急着make,先花五分钟把结构搞清楚。这套驱动的代码规模不小,但目录逻辑很清晰:
core/:驱动的协议栈核心,RTL8189F的MAC层、命令处理、电源管理等逻辑都在这,通称为RTW(Realtek WiFi)核心。hal/:寄存器级硬件抽象层,RTL8189FS跟硬件打交道的寄存器读写、RF初始化、PHY配置都在这里。os_dep/:操作系统适配层,所有跟Linux内核API相关的封装都在这个目录里,比如网络设备注册、工作队列、定时器、线程休眠,这部分是移植时改动最频繁的地方。platform/:平台相关的文件,从平台获取IO、功耗控制等。Makefile:编译入口,同时也是整个移植过程中需要重点修改的文件。
如果把驱动比作一套房子,os_dep就是大门的门槛,所有的Linux内核更新导致的问题,绝大多数都会先砸到这块门槛上。
2.2 Makefile里的交叉编译三板斧:平台、工具链、内核路径
官方包默认生成的Makefile,第一眼是给x86 PC编译用的。我们做嵌入式ARM平台,首先要做三件事:
打开Makefile,找到里面大写的CONFIG_PLATFORM系列选项:
CONFIG_PLATFORM_I386_PC = n CONFIG_PLATFORM_ARM_S3C6K4 = n ... CONFIG_PLATFORM_ARM_RK3188 = y不同SoC平台对应不同的配置项,比如瑞芯微方案选CONFIG_PLATFORM_ARM_RK3188,三星平台选CONFIG_PLATFORM_ARM_S3C6K4,全志平台可能选CONFIG_PLATFORM_ARM_SUN6I或别的变量名。选好之后,再改工具链前缀和内核源码路径:
CONFIG_CROSS_COMPILE = "arm-linux-gnueabihf-" CONFIG_KERNEL_DIR = /home/workspace/kernel有些厂商BSP的Makefile写法不太一样,会把ARCH和CROSS_COMPILE放在编译命令里而不是Makefile内,但本质一样。这里最常见的翻车点是:选了某个平台选项之后,Makefile内部会额外做一些平台相关的配置,比如自动启用某些电源管理宏,导致你明明只改了一个选项,编译结果跟预期不一样。所以改完Makefile后,建议执行一下make clean,把之前的编译中间文件全部清掉。
提示:工具链版本尽量和主控SoC厂商BSP的要求一致。比如arm-linux-gnueabihf交叉编译器版本太新或太老,都可能冒出莫名其妙的头文件兼容问题。
3. 编译入口:从x86到ARM的完整编译流程
3.1 编译模块并确认产物
做好Makefile配置后,执行编译。一般情况下编译命令是这样:
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- -j4如果你的Makefile里Platform选的是某个固定ARM平台,也可以只敲make。编译过程中看到的输出是在编译一组.o文件,最终产物中最重要的文件是8189fs.ko。这个ko文件名是从芯片型号来的:8189f + sdio的s,连起来就是8189fs。
编译结束后,先用file命令检查ko文件的架构:
file 8189fs.ko输出里应该明确看到ARM架构,比如ARM, EABI, mod_unload modversions ARMv7。如果显示x86-64,说明ARCH没传对,要么是Makefile里的平台没选到ARM分支,要么是命令里没带ARCH参数。
接下来把ko文件放到板子的文件系统里,然后加载:
insmod 8189fs.ko模块加载成功后,用以下命令确认:
lsmod | grep 8189 dmesg | tail -n 30 iw dev正常执行完insmod后,dmesg里一般会出现类似“RTL8189FS: init”和“wlan0”的日志,iw dev也会列出wlan0这个无线网卡接口。如果走到这一步,驱动的基本加载就已经成功。
3.2 固件处理、开机自启和调试参数
RTL8189FS的驱动跟很多WiFi驱动一样,运行时需要固件。区别在于,瑞昱很多老版本驱动把固件数组直接编译进了驱动的C代码里,不需要额外放固件文件;但也有编译选项会把固件放在内核固件路径下加载。
如果dmesg后看到类似“Direct firmware load for rtlwifi/rtl8189fs.bin failed”的日志,那就是需要外部固件的版本。此时把源码包里的rtl8189fs.bin或者rtl8189fs_fw.bin文件复制到板子文件系统的/lib/firmware/rtlwifi/目录下就行了:
mkdir -p /lib/firmware/rtlwifi cp rtl8189fs.bin /lib/firmware/rtlwifi/要驱动开机自动加载,建议把它写进modprobe配置文件,而不是直接在rc.local里insmod,因为modprobe会自动解析依赖:
echo "8189fs" >> /etc/modules或者进一步指定加载参数,比如关闭节能模式保证无线稳定:
echo "options 8189fs rtw_power_mgnt=0" > /etc/modprobe.d/8189fs.confrtw_power_mgnt这个参数值得单独说一下。RTL8189FS默认开了省电模式,在部分板子上可能导致响应慢、Ping延迟高甚至断流。rtw_power_mgnt=0表示关闭省电,rtw_power_mgnt=1是普通省电,rtw_power_mgnt=2是最大省电。很多做产品的人会直接把它设成0,用一点功耗换取稳定,实测效果立竿见影。
4. 设备树与SDIO的配合:为什么在开发板上总是识别不到wlan0
4.1 硬件层面容易踩的坑
代码编译加载只是一半,另一半在硬件和内核设备树。RTL8189FS走的是SDIO接口,它本质上是一个SDIO外设,所以内核能不能识别它,取决于SDIO控制器驱动能不能枚举到这颗芯片,以及芯片的上电时序和复位脚是否正常。
硬件上最典型的几个坑:
- SDIO_D1、SDIO_D2、SDIO_D3这三个数据线没接全,只用1-bit模式,导致速率极低。
- 复位脚/使能脚的GPIO没在设备树里正确配置,芯片一直处于复位状态,SDIO枚举完全看不到设备。
- VCCIO和主控的IO电平不匹配,实测表现是时好时坏,有时候开机偶尔识别,有时候完全不识别。
排查的时候,如果dmesg里看不到类似“mmc1: new high speed SDIO card at address 0001”的日志,基本可以断定是SDIO总线层面就没枚举出设备,先别急着查驱动,回头检查硬件和电源时序才是正确的方向。
4.2 设备树节点示例
设备树配置没有一个放之四海而皆准的模板,因为不同SoC的MMC控制器节点写法不一样。但核心思路是相同的:让RTL8189FS连接的MMC控制器在系统启动时被正确初始化,SDIO主机控制器能发出SDIO卡检测流程。
下面是一个在ARM平台设备树中比较典型的配置片段:
&mmc1 { status = "okay"; non-removable; bus-width = <4>; cap-sdio-irq; keep-power-in-suspend; mmc-pwrseq = <&wifi_pwrseq>; vmmc-supply = <&vcc_sdio>; vqmmc-supply = <&vcc_sdio_io>; #address-cells = <1>; #size-cells = <0>; rtl8189fs: wifi@1 { compatible = "realtek,rtl8189fs"; reg = <1>; interrupt-parent = <&pio>; interrupts = <0 6 IRQ_TYPE_LEVEL_LOW>; }; }; wifi_pwrseq: wifi_pwrseq { compatible = "mmc-pwrseq-simple"; reset-gpios = <&pio 0 7 GPIO_ACTIVE_LOW>; };这里的non-removable很重要,告诉内核这张SDIO卡不是可插拔设备,不要去做热插拔轮询和电源切换。bus-width = <4>把数据线改成4位模式,如果不写,默认可能只跑1位,吞吐量直接砍到四分之一。
interrupts里的中断脚和reset-gpios里的GPIO,要根据自己板子的实际走线来填。很多新手直接抄网上别人的DTS,抄完发现完全识别不了,十有八九就是GPIO号跟实际硬件对不上。这块没有捷径,必须对着原理图一个个确认。
5. 常见问题与排查记录
5.1 编译期间的典型错误:Linux内核API变更
旧驱动的最大敌人是内核API变动。RTL8189FS官方包在Linux 5.x以上版本编译时,最常见的报错集中在这些位置:
sk_buff结构体字段的存取方式变了。timer_list相关的初始化接口变了,旧代码用init_timer,新内核要求timer_setup。set_fs在5.10以后被移除了,而驱动里可能在读写固件时用了它。- 各种
rtw_mdelay、udelay的封装跟内核版本不匹配。
解决办法没有银弹。如果BSP内核版本跟官方包发布时间差距在两年以内,通常一个小补丁就能过;如果差距太大,建议先看厂商有没有已适配版本,再决定是否要继续啃。我个人的习惯是:在公司内部维护一个补丁文件,记录每个内核版本下改了什么,下次再换内核就有的放矢。
这里给一个判断思路:编译报错时,先去os_dep/目录下找对应的头文件和c文件,看它调用的内核函数在当前内核里的定义。比如报错指向net device操作函数,就去include/linux/netdevice.h里看struct net_device_ops成员是否变化。这样定位比盲改快得多。
5.2 加载模块时的固件与SDIO识别问题
驱动编译好了,insmod也不报错,但iw dev里就是没有wlan0。这种情况多半是驱动在等待固件加载,但固件没放到预期位置。打开服务端日志抓重点:
dmesg | grep -i firmware dmesg | grep -i rtl看到Firmware H2C fail这类日志,一般是固件和驱动版本不匹配,解决办法是换同一个版本包里的固件文件,或者改成编进驱动的固件数组版本,重新编译一次。
另一种情况SDIO识别问题。dmesg里可能只有“mmc1: error”。这种情况优先检查SDIO时钟频率。有些SoC的MMC控制器默认跑在某些频率下,和WiFi芯片的最高频率不匹配,需要把SDIO频率上限限制到50MHz左右,比如在DTS里加max-frequency = <50000000>。
还有一种非常容易被忽略的情况:wlan0在insmod的时候没出现,但在rmmod再insmod一次后就出现了。这大概率是上电时序问题,芯片没能在第一次枚举窗口内准备好。此时不是反复重启驱动,而是应该调整硬件上电时序,或者让WiFi芯片的上电早于主控SDIO控制器初始化。
5.3 连接不稳定、频繁掉线
驱动能起来,也能扫描到AP,但连接上之后过一会就掉,或者传大文件就断流。这种情况首先排查的还是省电模式,把模块参数里的rtw_power_mgnt调成0,大部分都稳定住了。
如果调完还掉线,再看硬件信号质量。RTL8189FS是单天线芯片,天线匹配不好时RSSI会很低,驱动出于保护机制主动断开连接。用iw dev wlan0 link或者iwinfo命令看信号强度,如果信号低于-70dBm,硬件层面的问题大于软件层面的问题,得回去改天线设计或换模组位置。
我把这几个高频问题整理成一张速查表,方便对照排查:
| 现象 | 可能原因 | 处理办法 |
|---|---|---|
| 编译报错,函数或字段找不到 | 内核API不兼容 | 查对应内核版本的struct定义,改驱动适配层 |
| insmod成功,但无wlan0 | 固件缺失或SDIO未枚举成功 | 检查/粘贴固件位置;检查设备树SDIO节点和GPIO |
| dmesg提示mmc error | SDIO信号/时钟频率问题 | 检查电压、IO电平、max-frequency参数 |
| 连接后频繁掉线 | 省电模式或信号弱 | 设置rtw_power_mgnt=0;检查天线匹配 |
| 吞吐量只有协商速率四分之一 | SDIO未跑4-bit模式 | 修改设备树bus-width=<4> |
6. 实操验收:编译完成后如何全面验证无线性能
6.1 先用基础工具确认无线网卡状态
模块加载并创建wlan0后,先做基础确认:
ip link set wlan0 up iw dev wlan0 scan | head -n 30能看到扫描结果,说明射频收发链路基本是好的。ip link set wlan0 up这一步如果报错,优先看dmesg有没有RF初始化失败的日志。扫描出来的AP列表里信号强度普遍偏低,那就要回到硬件信号通路查天线和匹配网络。
连接AP前,确认WPA配置工具存在,常见的做法是用wpa_supplicant:
wpa_passphrase "MyAP" "mypassword" > /etc/wpa_supplicant.conf wpa_supplicant -B -i wlan0 -c /etc/wpa_supplicant.conf udhcpc -i wlan0这里有个细节,wpa_supplicant能成功连接并不代表驱动完全正常,它只说明802.11关联成功了。真正的稳定性测试要到下一步。
6.2 吞吐量和丢包测试
RTL8189FS的物理层协商速率最高是72.2Mbps,TCP实际吞吐量通常能跑到40Mbps左右就算正常。用iperf3测试时,建议先把省电模式关掉,否则结果会波动很大:
iperf3 -c 192.168.1.100 -i 1 -t 30另外一项快速测试是Ping大包加连续Ping:
ping -s 1400 -c 200 192.168.1.100重点看丢包率和时延抖动。如果Ping小包(64字节)没问题,大包丢包严重,有可能是MTU协商问题,检查AP端和Linux端的MTU设置是否一致。
我测试时还会测弱信号场景:人拿着板子往远处走,看信号到多少dBm开始丢包,这个数据直接决定产品实际使用距离。如果RSSI降到-65dBm就开始大量丢包,说明灵敏度不行,硬件上还要调。
7. 说点项目上拿命换来的经验
RTL8189FS这套驱动我前后用了好几年,说没有心理阴影是假的,但摸透之后,它其实是个非常稳定的低成本方案。现在接手新项目,只要看到WiFi模组用的是RTL8189FS,第一件事就是去厂商BSP里翻有没有对应补丁,而不是直接拿官方原始包硬编。厂商BSP往往已经解决了内核适配和平台设备树的问题,比自己啃makefile和源码省一天时间。
另外我强烈建议源码包解压后第一时间复制一份带版本号的备份目录,不要直接在原目录上改。因为这类专有驱动不像主线内核会有人持续维护,今天改完能编译,三个月后换新内核可能又要重新改。如果没有原始干净版本做对照,你会被自己之前改过的东西坑到怀疑人生。
在项目验收阶段,务必保留“驱动版本 + 内核版本 + 工具链版本 + 设备树文件”这四个信息。我见过太多项目半年后无人能维护,就是因为当初代码编过了,但没人记录是怎么编过的。这四样信息凑齐,换任何一个人来,都能在一天内复现编译环境。
RTL8189FS不是性能猛兽,但它用极低的成本解决了大量设备的联网问题。只要掌握交叉编译、固件加载、设备树配置这三板斧,这个芯片在Linux下的开发并没有想象中那么可怕。
本文还有配套的精品资源,点击获取