4. 蓝牙控制器设备树节点:UART蓝牙、USB蓝牙、SDIO蓝牙的DTS配置差异

在实际嵌入式Linux开发中,蓝牙控制器的物理连接方式决定了设备树(DTS)节点的配置形态。最常见的三种接口——UART、USB、SDIO——在DTS中的描述方式、时钟管理、电源控制以及中断处理路径上存在显著差异。本章将逐一剖析这三种接口的DTS节点结构,并对比其关键配置项。

4.1 接口类型与DTS节点核心差异

下表从硬件特性、DTS绑定方式、中断模型和电源管理四个维度,对比三种接口的核心差异:

对比维度 UART蓝牙 USB蓝牙 SDIO蓝牙
物理层 串行异步收发(TX/RX/CTS/RTS) USB全速/高速差分信号 SDIO 4-bit/1-bit并行时钟
DTS绑定方式 挂载在uart节点下的子节点,使用serdev或bt-serial驱动 由USB核心枚举,通常不需要显式DTS节点,或仅需usb-device兼容属性 挂载在mmc/sdio控制器节点下,使用mmc-pwrseq和bt-sdio驱动
中断模型 依赖UART的RX中断或专用蓝牙唤醒GPIO中断 通过USB中断端点(Interrupt EP)传输HCI事件 通过SDIO的DAT[1]线中断或GPIO中断线
电源管理 需独立控制蓝牙使能(BT_EN)和UART电源域 由USB总线电源管理控制,支持远程唤醒 需控制SDIO卡电源、复位和唤醒信号
选型提示: UART蓝牙适合低功耗、低速率的HID设备(如鼠标、键盘);USB蓝牙适合高速率、即插即用的场景(如蓝牙适配器);SDIO蓝牙常用于Wi-Fi+蓝牙组合模块(如BCM43455、RTL8822),需要与Wi-Fi共享SDIO总线。

4.2 UART蓝牙DTS配置详解

UART蓝牙是最常见的HCI传输层之一,DTS节点通常作为UART控制器的子节点出现。核心配置包括:蓝牙使能GPIO、蓝牙唤醒GPIO、UART波特率、流控模式以及时钟源。

/* UART蓝牙节点示例:基于BCM43438(树莓派3) */
&uart1 {
    pinctrl-names = "default";
    pinctrl-0 = &uart1_pins;
    status = "okay";

    bluetooth {
        compatible = "brcm,bcm43438-bt";
        max-speed = <3000000>;
        clocks = <&clk_out_bluetooth>;
        clock-names = "lpo";
        device-wakeup-gpios = <&gpio 31 GPIO_ACTIVE_HIGH>;
        host-wakeup-gpios = <&gpio 32 GPIO_ACTIVE_HIGH>;
        shutdown-gpios = <&gpio 33 GPIO_ACTIVE_HIGH>;
        interrupt-parent = <&gpio>;
        interrupts = <32 IRQ_TYPE_EDGE_RISING>;
        pinctrl-names = "default";
        pinctrl-0 = <&bt_pins>;
    };
};

关键属性说明:

  • compatible:驱动匹配字符串,必须与内核蓝牙驱动(如hci_uart、bcm43xx)匹配。
  • max-speed:UART波特率,通常设置为3Mbps或4Mbps,需与蓝牙模块固件协商。
  • shutdown-gpios:蓝牙模块的硬件复位/使能引脚,驱动加载时拉高启动。
  • device-wakeup-gpios:主机唤醒蓝牙设备(如发送数据前唤醒)。
  • host-wakeup-gpios:蓝牙设备唤醒主机(如收到HID数据时触发中断)。
  • interrupts:通常绑定到host-wakeup引脚,用于蓝牙中断处理。
中断处理要点: UART蓝牙的中断路径分为两层:第一层是UART RX中断,负责接收HCI数据包;第二层是host-wakeup GPIO中断,用于蓝牙设备主动通知主机有数据待处理。在HID场景中,host-wakeup中断必须配置为边沿触发(IRQ_TYPE_EDGE_RISING或IRQ_TYPE_EDGE_FALLING),以确保低功耗模式下能及时唤醒系统。

4.3 USB蓝牙DTS配置详解

USB蓝牙通常不需要复杂的DTS节点,因为USB子系统通过VID/PID自动枚举设备。但在某些嵌入式平台(如i.MX、RK系列)中,可能需要为USB控制器配置电源域或为蓝牙设备指定复位GPIO。

/* USB蓝牙节点示例:通过usb-device绑定 */
&usb_host1 {
    status = "okay";
    #address-cells = <1>;
    #size-cells = <0>;

    bluetooth@1 {
        compatible = "usb,0a12,0001";  /* VID=0x0a12, PID=0x0001 */
        reg = <1>;
        reset-gpios = <&gpio 34 GPIO_ACTIVE_LOW>;
        max-speed = <2>;  /* USB_HIGH_SPEED */
    };
};

USB蓝牙DTS配置要点:

  • compatible:使用usb,VID,PID格式,USB核心在枚举时匹配该节点。
  • reg:USB端口号,对应USB控制器的端口地址。
  • reset-gpios:可选,用于硬件复位USB蓝牙设备。
  • max-speed:限制USB速度(1=全速,2=高速),避免兼容性问题。
注意: 大多数USB蓝牙适配器(如CSR8510、RTL8761)在标准Linux内核中无需DTS节点即可工作。只有在需要控制专用复位引脚、电源使能或配置特定USB控制器属性时,才需要添加DTS节点。对于HID场景,USB蓝牙的中断处理完全由USB核心的URB机制管理,DTS中无需额外中断配置。

4.4 SDIO蓝牙DTS配置详解

SDIO蓝牙通常与Wi-Fi共享SDIO总线,DTS配置最为复杂。需要同时管理MMC控制器、电源序列(pwrseq)、时钟和中断。

/* SDIO蓝牙节点示例:基于BCM43455(Raspberry Pi 4) */
&mmc1 {
    pinctrl-names = "default";
    pinctrl-0 = &sdio_pins;
    non-removable;
    bus-width = <4>;
    status = "okay";

    bluetooth {
        compatible = "brcm,bcm43455-bt";
        reg = <1>;  /* SDIO function 1 */
        max-speed = <200000000>;
        clocks = <&clk_out_bluetooth>;
        clock-names = "lpo";
        interrupt-parent = <&gpio>;
        interrupts = <35 IRQ_TYPE_EDGE_FALLING>;
        reset-gpios = <&gpio 36 GPIO_ACTIVE_LOW>;
        vdd-supply = <&vcc_sdio>;
        vddio-supply = <&vcc_sdio_io>;
    };
};

/* 电源序列节点(pwrseq) */
&mmc1_pwrseq {
    compatible = "mmc-pwrseq-simple";
    reset-gpios = <&gpio 37 GPIO_ACTIVE_LOW>;
    clocks = <&clk_out_bluetooth>;
    clock-names = "ext_clock";
};

SDIO蓝牙DTS配置关键点:

  • reg:SDIO功能号,蓝牙通常使用function 1(function 0为SDIO卡控制)。
  • max-speed:SDIO时钟频率,通常为100MHz~200MHz。
  • non-removable:蓝牙模块不可移除,避免MMC核心发送移除检测。
  • bus-width:SDIO数据线宽度,4-bit模式提供更高吞吐量。
  • vdd-supply / vddio-supply:核心电压和I/O电压,由稳压器提供。
  • mmc-pwrseq:电源序列节点,控制蓝牙模块的上电时序和复位。
中断处理差异: SDIO蓝牙的中断有两种模式:一是通过SDIO协议内置的DAT[1]线中断,由MMC控制器处理;二是通过独立的GPIO中断线(如上例中的interrupts = <35 IRQ_TYPE_EDGE_FALLING>)。在HID场景中,推荐使用GPIO中断模式,因为它不依赖SDIO时钟,在系统休眠时仍能唤醒主机。

4.5 三种接口DTS中断路径对比

下图展示了UART、USB、SDIO三种蓝牙接口的中断传递路径,重点体现中断源到HCI核心的流程差异:

三种蓝牙接口中断路径对比 三种蓝牙接口中断路径对比 UART 蓝牙 蓝牙设备(BCM43438) host-wakeup GPIO中断 UART RX中断 hci_uart驱动 HCI核心 蓝牙HID协议层 USB 蓝牙 蓝牙设备(USB适配器) USB中断端点 USB URB机制 btusb驱动 HCI核心 蓝牙HID协议层 SDIO 蓝牙 蓝牙设备(SDIO模块) GPIO中断 / DAT[1]中断 MMC/SDIO控制器 hci_sdio驱动 HCI核心 蓝牙HID协议层 说明:UART和SDIO蓝牙的中断路径包含专用GPIO中断线,适合低功耗HID场景;USB蓝牙的中断完全由USB协议栈管理,无需DTS中断配置。

4.6 实战配置检查清单

在编写蓝牙控制器DTS节点时,请对照以下清单逐项确认:

  1. 接口匹配:确认蓝牙模块的物理接口类型(UART/USB/SDIO),选择对应的DTS绑定方式。
  2. 电源控制:检查蓝牙使能(BT_EN)或复位(reset)GPIO是否在DTS中正确声明,并确认上电时序。
  3. 时钟源:对于需要外部低速时钟(如32.768kHz LPO)的模块,确保clocks属性指向正确的时钟源。
  4. 中断配置:UART和SDIO蓝牙必须配置host-wakeup中断,并确认中断触发类型(边沿/电平)与模块规格一致。
  5. 流控配置:UART蓝牙必须启用硬件流控(CTS/RTS),在DTS中通过uart-has-rtscts或rts-gpios属性配置。
  6. 速度协商:UART的max-speed和SDIO的max-speed必须与蓝牙模块固件支持的速率匹配,过高可能导致初始化失败。
  7. 电源域:SDIO蓝牙需要明确vdd-supply和vddio-supply,确保电压范围在模块规格内(通常1.8V或3.3V)。
常见错误: 在UART蓝牙DTS中遗漏host-wakeup-gpios或interrupts属性,会导致蓝牙设备无法主动唤醒主机,HID设备在休眠后无法恢复连接。另一个常见问题是SDIO蓝牙的non-removable属性缺失,导致MMC核心在系统运行时误判设备移除,触发不必要的重枚举。

4.7 本章小结