4. 蓝牙HCI UART设备树节点

在嵌入式Linux系统中,蓝牙HCI(Host Controller Interface)通过UART与主机通信时,需要在设备树(Device Tree)中精确描述硬件连接、芯片型号及电源管理策略。本章将深入讲解蓝牙HCI UART节点的定义方法、主流蓝牙芯片的compatible字符串匹配规则,以及电源管理属性的配置要点。

前置知识:设备树是描述硬件资源的结构化数据,Linux内核通过解析设备树来初始化驱动、分配资源。蓝牙HCI UART节点通常挂载在UART控制器节点下,作为子节点或通过bluetooth子节点定义。

4.1 蓝牙HCI UART节点定义

一个标准的蓝牙HCI UART设备树节点包含以下核心属性:

  • compatible:匹配蓝牙芯片驱动的字符串,格式为"vendor,chip"。
  • reg:指定UART端口号(如reg = <0>表示UART0)。
  • max-speed:UART波特率,通常为3000000或4000000。
  • shutdown-gpios:蓝牙芯片复位或使能引脚。
  • device-wakeup-gpios:主机唤醒蓝牙芯片的GPIO。
  • host-wakeup-gpios:蓝牙芯片唤醒主机的GPIO。
  • clocks:外部时钟源,如32.768kHz低速时钟或26MHz高速时钟。
  • vbat-supply / vddio-supply:电源供应节点。
典型节点结构示例:
&uart0 {
    status = "okay";
    pinctrl-names = "default";
    pinctrl-0 = <&uart0_pins>;

    bluetooth {
        compatible = "brcm,bcm43438-bt";
        reg = <0>;
        max-speed = <3000000>;
        shutdown-gpios = <&gpio0 6 GPIO_ACTIVE_HIGH>;
        device-wakeup-gpios = <&gpio0 7 GPIO_ACTIVE_HIGH>;
        host-wakeup-gpios = <&gpio0 8 GPIO_ACTIVE_HIGH>;
        clocks = <&clk32k>;
        clock-names = "lpo";
        vbat-supply = <&vbat_reg>;
        vddio-supply = <&vddio_reg>;
    };
};

上述节点中,bluetooth子节点挂载在UART0控制器下,内核通过compatible匹配到hci_uart驱动中的BCM协议驱动。所有GPIO属性使用GPIO_ACTIVE_HIGH或GPIO_ACTIVE_LOW定义有效电平。

常见错误:忘记在UART父节点中设置status = "okay",或未正确配置pinctrl导致UART引脚功能错误,蓝牙芯片无法通信。
蓝牙HCI UART设备树节点结构 / (根节点) soc (芯片总线) uart0 (UART控制器) bluetooth (HCI UART子节点) compatible = "brcm,bcm43438-bt" GPIO & 时钟属性 • shutdown-gpios • device-wakeup-gpios • host-wakeup-gpios • clocks / clock-names 电源 & 速率属性 • vbat-supply • vddio-supply • max-speed • reg (UART端口)

4.2 蓝牙芯片的compatible字符串

compatible字符串是设备树与驱动匹配的关键。不同厂商的蓝牙芯片使用不同的命名规则,内核中的hci_uart驱动通过此字符串加载对应的协议驱动(如h4、bcsp、ll、bcm、intel等)。

芯片型号 compatible字符串 驱动模块 典型波特率
BCM4343W brcm,bcm43438-bt hci_uart / bcm 3000000 / 4000000
BCM4345 brcm,bcm4345c5 hci_uart / bcm 3000000
CC2564C ti,cc2564c hci_uart / ll 3000000
WL18xx ti,wl18xx-bt hci_uart / ll 3000000
CSR8811 csr,csr8811-bt hci_uart / bcm 3000000
RTL8723BS realtek,rtl8723bs-bt hci_uart / btrtl 115200 / 921600
匹配原理:内核在启动时遍历设备树节点,将compatible字符串与驱动中of_match_table进行比对。例如BCM驱动中定义:{ .compatible = "brcm,bcm43438-bt", .data = &bcm43438_device_data }。

对于BCM4343W芯片,其完整节点通常还包含固件加载路径和BD地址配置:

&uart1 {
    status = "okay";
    bluetooth {
        compatible = "brcm,bcm43438-bt";
        reg = <1>;
        max-speed = <4000000>;
        shutdown-gpios = <&gpio2 4 GPIO_ACTIVE_HIGH>;
        device-wakeup-gpios = <&gpio2 5 GPIO_ACTIVE_HIGH>;
        host-wakeup-gpios = <&gpio2 6 GPIO_ACTIVE_HIGH>;
        clocks = <&clk32k>;
        clock-names = "lpo";
        vbat-supply = <&vbat_3v3>;
        vddio-supply = <&vddio_1v8>;
        brcm,bt-local-bd-address = [00 11 22 33 44 55];
        firmware-name = "brcm/BCM4343W.hcd";
    };
};

CC2564C芯片的节点则略有不同,TI的驱动使用ti,cc2564c字符串,且通常需要额外的nshutdown-gpios属性:

&uart2 {
    status = "okay";
    bluetooth {
        compatible = "ti,cc2564c";
        reg = <2>;
        max-speed = <3000000>;
        nshutdown-gpios = <&gpio3 0 GPIO_ACTIVE_HIGH>;
        device-wakeup-gpios = <&gpio3 1 GPIO_ACTIVE_HIGH>;
        host-wakeup-gpios = <&gpio3 2 GPIO_ACTIVE_HIGH>;
        clocks = <&clk26m>;
        clock-names = "ext_clock";
        vbat-supply = <&vbat_3v3>;
        vddio-supply = <&vddio_1v8>;
    };
};
compatible字符串匹配流程 设备树节点 compatible = "brcm,bcm43438-bt" 内核OF匹配层 of_match_table 遍历 hci_uart/bcm BCM协议驱动 compatible 字符串匹配规则 • 精确匹配:字符串必须完全一致,区分大小写 • 厂商前缀:使用标准厂商名(brcm、ti、realtek、csr等) • 芯片型号:使用芯片数据手册中的型号标识 • 后缀约定:蓝牙子节点通常添加"-bt"后缀(如bcm43438-bt) • 回退机制:可定义多个compatible值,内核按优先级尝试 • 驱动数据:匹配成功后通过.data传递芯片特定参数

4.3 电源管理属性

蓝牙芯片的电源管理直接影响系统功耗和射频性能。设备树中通过以下属性实现精细化的电源控制:

4.3.1 核心电源属性

属性名 类型 说明 典型值
vbat-supply phandle 蓝牙芯片主电源(通常3.3V) &vbat_3v3
vddio-supply phandle UART IO电源(通常1.8V或3.3V) &vddio_1v8
vddcore-supply phandle 核心逻辑电源(部分芯片需要) &vddcore_1v2
clocks phandle数组 外部时钟源,用于低功耗模式 &clk32k
clock-names 字符串数组 时钟名称,与clocks对应 "lpo" / "ext_clock"

4.3.2 GPIO唤醒与电源控制

蓝牙芯片的电源管理依赖GPIO信号实现主机与蓝牙模块之间的唤醒协同:

  • shutdown-gpios:硬件复位或使能引脚。拉低时芯片进入硬复位或断电状态,拉高时正常供电。驱动在初始化时先拉低再拉高完成复位时序。
  • device-wakeup-gpios:主机主动唤醒蓝牙芯片的信号。当主机需要发送数据时,拉高此引脚唤醒蓝牙芯片从休眠状态恢复。
  • host-wakeup-gpios:蓝牙芯片唤醒主机的信号。蓝牙芯片收到远程数据或需要上报事件时,拉高此引脚唤醒主机CPU。
电源管理最佳实践:在系统休眠时,驱动通过suspend回调将蓝牙芯片置于深度睡眠模式,关闭UART时钟并释放GPIO中断;唤醒时通过resume回调重新初始化芯片并恢复通信。设备树中的wakeup-source属性可标记该节点支持唤醒功能。

4.3.3 完整电源管理节点示例

&uart3 {
    status = "okay";
    bluetooth {
        compatible = "brcm,bcm43438-bt";
        reg = <3>;
        max-speed = <3000000>;
        shutdown-gpios = <&gpio4 0 GPIO_ACTIVE_HIGH>;
        device-wakeup-gpios = <&gpio4 1 GPIO_ACTIVE_HIGH>;
        host-wakeup-gpios = <&gpio4 2 GPIO_ACTIVE_HIGH>;
        clocks = <&clk32k>;
        clock-names = "lpo";
        vbat-supply = <&vbat_3v3>;
        vddio-supply = <&vddio_1v8>;
        wakeup-source;
        /* 电源序列时序参数(微秒) */
        brcm,shutdown-time-us = <10000>;
        brcm,wakeup-time-us = <5000>;
        brcm,host-wakeup-interval-ms = <100>;
    };
};
蓝牙芯片电源管理状态机 运行状态 UART全速 / 射频开启 空闲状态 UART空闲 / 低功耗监听 深度休眠 时钟关闭 / 仅唤醒IO 复位/断电 shutdown拉低 / 无供电 空闲超时 深度休眠 shutdown拉低 shutdown拉高 + 初始化 host-wakeup device-wakeup

4.4 电源管理属性配置要点

关键配置原则:
  1. 电源轨顺序:vbat-supply必须在vddio-supply之前稳定,否则IO引脚可能漏电。设备树中电源节点的regulator-boot-on属性可确保早期供电。
  2. 时钟精度:低功耗时钟(lpo)通常为32.768kHz,精度需在±250ppm以内,否则蓝牙休眠唤醒后可能出现时钟漂移导致连接断开。
  3. GPIO电平匹配:shutdown、device-wakeup、host-wakeup的GPIO电平必须与蓝牙芯片数据手册一致,错误电平可能导致芯片无法启动或误唤醒。
  4. 唤醒延迟:从深度休眠到恢复UART通信通常需要5~15ms,设备树中的brcm,wakeup-time-us可调整驱动等待时间,过短可能导致初始化失败。
  5. 电源域隔离:如果蓝牙芯片与主控使用不同电源域,需在设备树中通过power-domains属性指定,确保休眠时正确关闭电源。
调试提示:如果蓝牙芯片在系统休眠后无法唤醒,首先检查host-wakeup-gpios对应的中断是否在/proc/interrupts中注册,并确认GPIO控制器未在休眠时关闭。使用echo 1 > /sys/kernel/debug/gpio可查看GPIO状态。

4.5 多芯片兼容性配置

在实际产品中,同一硬件平台可能兼容多种蓝牙芯片。设备树支持通过compatible字符串的优先级实现多芯片支持:

&uart0 {
    status = "okay";
    bluetooth {
        compatible = "brcm,bcm43438-bt", "ti,cc2564c", "csr,csr8811-bt";
        reg = <0>;
        max-speed = <3000000>;
        shutdown-gpios = <&gpio0 6 GPIO_ACTIVE_HIGH>;
        device-wakeup-gpios = <&gpio0 7 GPIO_ACTIVE_HIGH>;
        host-wakeup-gpios = <&gpio0 8 GPIO_ACTIVE_HIGH>;
        clocks = <&clk32k>;
        clock-names = "lpo";
        vbat-supply = <&vbat_3v3>;
        vddio-supply = <&vddio_1v8>;
    };
};

内核按照compatible列表的顺序依次尝试匹配驱动,第一个匹配成功的驱动将被加载。这种方式允许同一设备树镜像支持多种蓝牙模块,降低固件维护成本。

设备树节点 compatible = "brcm,bcm43438-bt", "ti,cc2564c", "csr,csr8811-bt" 内核匹配引擎 ① 尝试 brcm,bcm43438-bt ② 失败 → 尝试 ti,cc2564c ③ 失败 → 尝试 csr,csr8811-bt 匹配成功 加载对应驱动 初始化芯片 多芯片兼容设计要点 • 将最常用的芯片放在compatible列表首位,减少匹配时间 • 不同芯片的GPIO和电源属性需保持一致,否则需使用pinctrl-0和pinctrl-1区分 ← 上一章 📖 返回目录 下一章 →