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不太一样——固件和配置是打包在一起的,通过mlanmoal两个模块协同工作。

NXP驱动有个好处:它自带一个wlan_sdio.c文件,专门处理SDIO的电源管理和中断。你只需要在DTS里配好vmmc-supplywlan-en-gpio就行。

我的建议:NXP的驱动默认是不开启802.11ac的。如果你需要5GHz频段,记得在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的openssltls支持没开。

注意:车载系统经常需要连接企业级AP。编译wpa_supplicant时,务必打开CONFIG_EAPCONFIG_TLSCONFIG_OPENSSL。否则你连PEAP、TTLS这些认证方式都用不了。

另外,Android Automotive里有个特殊要求——wpa_supplicant必须支持P2PHotspot 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_uartbtusb
  • bluetoothd:蓝牙守护进程,负责协议栈管理
  • libbluetooth:用户空间库,供上层调用

我在项目中遇到过,蓝牙能扫描到设备,但就是连不上。查日志发现bluetoothdHCI command timeout。后来发现是UART的波特率不对。BCM的蓝牙默认是115200,但NXP的蓝牙需要3000000。改一下DTS里的current-speed就好了。

DTS配置示例(NXP蓝牙):
&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与蓝牙移植知识体系 Wi-Fi驱动移植 BCM / NXP wpa_supplicant 配置与编译 蓝牙协议栈 BlueZ适配 共存与功耗 优化策略 • 内核配置 • 固件加载 • DTS配置 • SDIO时序 • EAP认证 • P2P支持 • Hotspot 2.0 • 编译选项 • HCI驱动 • bluetoothd • UART波特率 • 协议配置 • 硬件共存 • 软件仲裁 • 功耗策略 • 唤醒配置 核心原则:驱动是基础,协议是桥梁,共存是难点,功耗是底线 每个环节都要在开发板上反复验证,不要跳步

好了,这一章的内容就到这里。Wi-Fi和蓝牙移植,说难也难,说简单也简单。难在细节多、坑多;简单在只要按部就班,每个环节都验证到位,总能跑起来。我个人觉得,做无线移植最重要的不是技术,而是耐心——因为很多时候,问题出在你根本想不到的地方。