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引脚功能错误,蓝牙芯片无法通信。
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>;
};
};
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>;
};
};
4.4 电源管理属性配置要点
关键配置原则:
- 电源轨顺序:vbat-supply必须在vddio-supply之前稳定,否则IO引脚可能漏电。设备树中电源节点的
regulator-boot-on属性可确保早期供电。 - 时钟精度:低功耗时钟(lpo)通常为32.768kHz,精度需在±250ppm以内,否则蓝牙休眠唤醒后可能出现时钟漂移导致连接断开。
- GPIO电平匹配:shutdown、device-wakeup、host-wakeup的GPIO电平必须与蓝牙芯片数据手册一致,错误电平可能导致芯片无法启动或误唤醒。
- 唤醒延迟:从深度休眠到恢复UART通信通常需要5~15ms,设备树中的
brcm,wakeup-time-us可调整驱动等待时间,过短可能导致初始化失败。 - 电源域隔离:如果蓝牙芯片与主控使用不同电源域,需在设备树中通过
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列表的顺序依次尝试匹配驱动,第一个匹配成功的驱动将被加载。这种方式允许同一设备树镜像支持多种蓝牙模块,降低固件维护成本。