13、Wi-Fi与蓝牙移植:Wi-Fi驱动(BCM/NXP)移植、wpa_supplicant配置、蓝牙协议栈(BlueZ)适配、共存与功耗优化
各位好,欢迎来到第13章。今天聊的话题,是车载系统里最让人头疼、也最绕不开的——无线连接。Wi-Fi和蓝牙,这两个东西在手机上你可能觉得理所当然,但在i.MX平台上,尤其是Android Automotive系统里,移植起来那叫一个“步步惊心”。
我个人习惯把无线移植分成四个阶段:驱动能跑、协议能通、共存不打架、功耗能看。咱们今天就按这个逻辑来拆解。
13.1 Wi-Fi驱动移植:BCM与NXP的“性格”差异
Wi-Fi驱动移植,说白了就是让内核认识你的Wi-Fi芯片。市面上主流的车载Wi-Fi芯片,基本被Broadcom(BCM)和NXP两家包揽。这两家的驱动风格完全不同,我分别说说。
13.1.1 BCM驱动移植要点
BCM的驱动,在Linux内核里通常叫bcmdhd。它是个全功能驱动,但有个特点——固件和配置参数是分离的。你需要把固件文件放到/lib/firmware/目录下,同时还要提供nvram.txt文件。
我在项目中遇到过,BCM芯片死活扫描不到AP。查了半天,发现是nvram.txt里的ccode(国家码)设成了US,而我们的测试环境在中国。改一下就好了。嗯,这种小坑特别多。
CONFIG_BCMDHD:内核配置里必须打开CONFIG_BCMDHD_FW_PATH:指定固件路径CONFIG_BCMDHD_NVRAM_PATH:指定nvram路径
另外,BCM驱动对SDIO接口的时序要求很严格。如果你用的是SDIO接口,记得检查DTS里的时钟频率。我曾经因为SDIO时钟设高了,导致Wi-Fi间歇性断连,降频到50MHz就稳了。
13.1.2 NXP驱动移植要点
NXP的Wi-Fi芯片(比如88W8987、88W9098),驱动在drivers/net/wireless/nxp/目录下。它的风格和BCM不太一样——固件和配置是打包在一起的,通过mlan和moal两个模块协同工作。
NXP驱动有个好处:它自带一个wlan_sdio.c文件,专门处理SDIO的电源管理和中断。你只需要在DTS里配好vmmc-supply和wlan-en-gpio就行。
defconfig里加上CONFIG_NXP_WIFI_11AC=y。
13.2 wpa_supplicant配置:别小看这个“小管家”
驱动搞定了,接下来就是wpa_supplicant。它是Wi-Fi连接的管理者,负责扫描、认证、密钥协商。Android Automotive里,wpa_supplicant的配置主要在/etc/wifi/wpa_supplicant.conf。
我见过很多工程师,驱动移植好了,但连不上企业级Wi-Fi(比如WPA2-Enterprise)。为什么?因为wpa_supplicant的openssl和tls支持没开。
CONFIG_EAP、CONFIG_TLS、CONFIG_OPENSSL。否则你连PEAP、TTLS这些认证方式都用不了。
另外,Android Automotive里有个特殊要求——wpa_supplicant必须支持P2P和Hotspot 2.0。因为车载系统经常需要做Wi-Fi热点分享,或者连接运营商提供的Wi-Fi offload网络。这些功能在编译时都要显式打开。
我个人习惯,在wpa_supplicant/.config里加上这几行:
CONFIG_P2P=y
CONFIG_WIFI_DISPLAY=y
CONFIG_HS20=y
CONFIG_INTERWORKING=y
CONFIG_EAP_PEAP=y
CONFIG_EAP_TTLS=y
CONFIG_EAP_TLS=y
13.3 蓝牙协议栈适配:BlueZ的“三件套”
蓝牙这块,Android Automotive用的是BlueZ(而不是Android原生的Fluoride)。为什么?因为BlueZ对车载的HFP(免提)、A2DP(音频)、PBAP(电话本)支持更成熟。
BlueZ的适配,核心是三个组件:
- kernel driver:蓝牙驱动,通常是
hci_uart或btusb - bluetoothd:蓝牙守护进程,负责协议栈管理
- libbluetooth:用户空间库,供上层调用
我在项目中遇到过,蓝牙能扫描到设备,但就是连不上。查日志发现bluetoothd报HCI command timeout。后来发现是UART的波特率不对。BCM的蓝牙默认是115200,但NXP的蓝牙需要3000000。改一下DTS里的current-speed就好了。
&uart3 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_uart3>;
current-speed = <3000000>;
bluetooth {
compatible = "nxp,88w8987-bt";
fw-init-baudrate = <3000000>;
};
};
13.4 共存与功耗优化:最难啃的骨头
Wi-Fi和蓝牙共存,是无线移植里最考验功力的地方。为什么?因为它们共用2.4GHz频段,而且很多芯片是单天线设计。你想想看,Wi-Fi在下载,蓝牙在通话,谁先谁后?
BCM和NXP的共存方案不太一样:
| 方案 | BCM | NXP |
|---|---|---|
| 硬件共存 | 通过BT_WAKE、WL_WAKE等GPIO信号 | 通过MWS(Multi-Wireless Subsystem)接口 |
| 软件共存 | 内核里的btcoex模块 |
固件内部自动仲裁 |
| 优先级策略 | 可配置(默认蓝牙优先) | 可配置(默认Wi-Fi优先) |
我曾经在BCM平台上,遇到蓝牙耳机断断续续。查了共存日志,发现Wi-Fi在大量下载时,蓝牙的时隙被挤占了。解决方案是:在nvram.txt里设置btc_mode=1,让蓝牙优先。代价是Wi-Fi吞吐量下降20%,但蓝牙通话保住了。
- Wi-Fi的
wowlan(Wake on Wireless LAN)一定要配好。车载系统经常需要远程唤醒,这个功能省电又实用。 - 蓝牙的
LE Advertising扫描间隔,默认是30ms。如果不需要频繁扫描,可以调到100ms,能省不少电。 - 如果芯片支持
802.11 Power Save,记得在wpa_supplicant里开启wowlan_triggers=any。
13.5 知识体系总览
说了这么多,我画了一张图,帮你把整个Wi-Fi与蓝牙移植的知识体系串起来。你可以把它当作一个检查清单,每完成一项就打个勾。
好了,这一章的内容就到这里。Wi-Fi和蓝牙移植,说难也难,说简单也简单。难在细节多、坑多;简单在只要按部就班,每个环节都验证到位,总能跑起来。我个人觉得,做无线移植最重要的不是技术,而是耐心——因为很多时候,问题出在你根本想不到的地方。