蓝牙驱动移植适配与DMA优化工程案例 - 第1节
1.1 蓝牙协议栈概述:经典蓝牙与低功耗蓝牙架构对比
蓝牙无线通信技术自 1994 年诞生以来,已演化为两大核心分支:经典蓝牙(BR/EDR)与低功耗蓝牙(BLE)。两者在协议栈架构、功耗模型、数据传输模式及应用场景上存在显著差异。理解这些差异是进行蓝牙驱动移植与 DMA 优化的前提。
1.1.1 经典蓝牙(BR/EDR)协议栈架构
经典蓝牙(Basic Rate / Enhanced Data Rate)面向持续连接、中等速率的数据流场景,如音频耳机、文件传输。其协议栈采用分层紧耦合设计,核心层次如下:
| 层次 | 功能描述 | 典型协议/组件 |
|---|---|---|
| 应用层 | 用户直接交互的蓝牙服务 | HFP、A2DP、AVRCP、SPP |
| 主机协议栈 | 逻辑链路控制、服务发现、安全管理 | L2CAP、SDP、RFCOMM、GAP |
| HCI 层 | 主机与控制器之间的命令/事件/数据接口 | HCI 命令、事件、ACL 数据 |
| 链路层/基带 | 物理连接建立、跳频、数据包调度 | Link Manager、Baseband |
| 射频层 | 2.4GHz 模拟收发、调制解调 | BR/EDR RF |
关键特征:经典蓝牙使用 79 个信道(1 MHz 间隔),跳频速率 1600 hops/s,支持 SCO/eSCO 同步语音链路,适合实时音频流。
1.1.2 低功耗蓝牙(BLE)协议栈架构
BLE(Bluetooth Low Energy)从 Bluetooth 4.0 开始引入,专为低功耗、低延迟、小数据包的物联网场景设计。其协议栈采用分层松耦合,核心层次如下:
| 层次 | 功能描述 | 典型协议/组件 |
|---|---|---|
| 应用层 | GATT 配置文件、服务/特征值定义 | GATT、GAP 角色 |
| 主机协议栈 | 属性协议、安全管理、逻辑链路控制 | ATT、SMP、L2CAP |
| HCI 层 | 主机与控制器之间的标准化接口 | HCI 命令/事件/数据 |
| 链路层 | 广播、扫描、连接、数据信道管理 | Link Layer (LL) |
| 物理层 | 2.4GHz 收发、GFSK 调制 | BLE PHY |
BLE 核心优势:使用 40 个信道(2 MHz 间隔),其中 3 个广播信道、37 个数据信道。广播时无需建立连接即可发送数据,峰值电流仅 15 mA 左右,待机功耗可低至 1 µA 以下。
1.1.3 经典蓝牙 vs BLE 架构对比
| 对比维度 | 经典蓝牙 (BR/EDR) | 低功耗蓝牙 (BLE) |
|---|---|---|
| 信道数量 | 79 个 (1 MHz) | 40 个 (2 MHz) |
| 跳频速率 | 1600 hops/s | 自适应跳频,连接后固定 |
| 数据速率 | 1-3 Mbps (EDR) | 1 Mbps (LE 1M), 2 Mbps (LE 2M) |
| 功耗模型 | 持续连接,中等功耗 | 短时突发,极低功耗 |
| 拓扑结构 | 微微网 (Piconet) | 广播/连接,支持 Mesh |
| 典型应用 | 音频流、文件传输 | 传感器、信标、可穿戴 |
| 主机协议栈复杂度 | 高 (RFCOMM, SDP, AVDTP) | 低 (ATT, GATT) |
驱动移植注意:经典蓝牙与 BLE 的 HCI 命令集、事件格式、数据包类型完全不同。在 Linux 内核中,
hci_uart 驱动需要根据芯片类型(如 CSR、Broadcom、TI CC256x)分别配置 HCI 传输层(H4、H5、BCSP 等),不可混用。
1.1.4 蓝牙协议栈分层架构总览(SVG)
下图展示了经典蓝牙与 BLE 协议栈的完整分层结构,以及 HCI 接口在主机与控制器之间的桥梁位置:
1.2 HCI 接口定义与驱动适配要点
1.2.1 HCI 接口的角色与分层
HCI(Host Controller Interface)是蓝牙协议栈中主机(Host)与控制器(Controller)之间的标准化通信接口。在 Linux 内核中,HCI 层由 bluetooth 子系统统一管理,驱动开发者主要关注 HCI 传输层的适配。
HCI 接口定义了三种基本数据包类型:
- 命令包(Command Packet):主机下发至控制器,用于配置、扫描、连接等操作。
- 事件包(Event Packet):控制器上报至主机,用于响应命令、通知状态变化。
- 数据包(Data Packet):分为 ACL(异步无连接)和 SCO(同步面向连接)两种,承载用户数据。
1.2.2 HCI 传输层标准
| 传输层标准 | 物理接口 | 典型速率 | Linux 驱动 | 适用场景 |
|---|---|---|---|---|
| H4 (UART) | UART (TX/RX/CTS/RTS) | 115200 bps - 4 Mbps | hci_uart + h4 协议 |
嵌入式设备、低成本模块 |
| H5 (3-Wire) | UART (TX/RX 无流控) | 115200 bps - 921600 bps | hci_uart + h5 协议 |
无硬件流控的 UART 场景 |
| BCSP | UART (BlueCore 串行协议) | 115200 bps - 3 Mbps | hci_uart + bcsp 协议 |
CSR 芯片专用 |
| USB | USB 全速/高速 | 12 Mbps - 480 Mbps | btusb |
PC、开发板 USB 蓝牙适配器 |
| SDIO | SDIO 1-bit/4-bit | 25 MB/s - 100 MB/s | btintel, btsdio |
WiFi+蓝牙组合芯片 (如 Intel 8260) |
驱动移植核心任务:在 Linux 内核中注册一个新的 HCI 传输驱动,实现
struct hci_uart_proto 或 struct h4_recv_buf 回调,完成数据包的封装/解封装、流控管理、以及 DMA 缓冲区的分配与回收。
1.2.3 HCI 数据包格式(SVG)
下图展示了 HCI 数据包在 UART 传输层上的封装格式,以及主机与控制器之间的交互流程:
1.2.4 Linux 内核 HCI 驱动注册示例
在 Linux 内核中,HCI UART 驱动的注册通过 hci_uart_register_proto() 完成。以下是一个简化的 H4 协议注册示例:
/* hci_h4.c - H4 UART 协议驱动片段 */
#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h>
#include <net/bluetooth/hci_uart.h>
static struct hci_uart_proto h4_proto = {
.id = HCI_UART_H4,
.name = "H4",
.open = h4_open,
.close = h4_close,
.recv = h4_recv,
.enqueue = h4_enqueue,
.dequeue = h4_dequeue,
.flush = h4_flush,
};
int __init h4_init(void)
{
int err;
err = hci_uart_register_proto(&h4_proto);
if (err < 0)
pr_err("H4 protocol registration failed\n");
return err;
}
void __exit h4_exit(void)
{
hci_uart_unregister_proto(&h4_proto);
}
module_init(h4_init);
module_exit(h4_exit);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Bluetooth H4 UART protocol driver");
DMA 优化切入点:在
h4_recv() 回调中,数据从 UART FIFO 搬运到内核缓冲区时,应使用 dma_alloc_coherent() 分配 DMA 安全的接收缓冲区,避免 CPU 逐字节拷贝。后续章节将详细讲解 DMA 环形缓冲区的设计与实现。
1.3 本章小结
- 经典蓝牙(BR/EDR)与低功耗蓝牙(BLE)在协议栈层次、信道数量、功耗模型上存在本质差异,驱动移植时需分别适配不同的 HCI 命令集。
- HCI 接口是主机与控制器之间的标准化桥梁,支持 UART、USB、SDIO 等多种物理传输层。
- Linux 内核中,HCI 传输驱动通过
struct hci_uart_proto注册,核心回调包括recv、enqueue、dequeue。 - DMA 优化应从 HCI 数据接收路径入手,使用一致性 DMA 缓冲区减少 CPU 干预,提升吞吐量。