淺析低功耗藍牙(BLE)協議棧
1、 什么是BLE協議棧?
BLE協議棧就是低功耗藍牙協議的代碼實現,其主要組成部分如下:
Controller 控制器層 | PHY (Physical Layer):基帶物理層 LL (Link Layer):鏈路層 HCI (Host controller interface):主機控制接口 |
Host 主機層 | L2CAP (Logic link control and adaptation protocol):邏輯鏈路控制和適配協議 ATT (Attribute protocol):屬性協議 GATT (Generic attribute profile):屬性協議配置規范 SMP (Secure manager protocol):安全管理 GAP (Generic access profile):通用訪問規范 |
在藍牙芯片上實現一個藍牙應用,首先需要提供與此芯片配套的BEL協議棧(protocol stack),然后在此協議棧的基礎上完成應用開發。
2、 BLE協議棧框架
BLE協議棧基本框架如下:
可以看出BLE協議棧是連接芯片和應用的橋梁,是實現整個BLE應用的關鍵。BLE協議棧主要用來對應用數據進行層層封包,以生成一個滿足BLE協議的空中數據包,也就是說,把應用數據包裹在一系列的幀頭(header)和幀尾(tail)中。
3、 BLE協議棧分層
3.1 PHY層(Physical Layer物理層)
PHY層用來指定BLE所用的無線頻段(2.4GHz),調制解調方式(GFSK高斯頻移鍵控),發送功率等。PHY層做的好不好將直接決定該BLE芯片的功耗、靈敏度等等射頻指標。
3.2 LL層(Link Layer鏈路層)
LL層是整個BLE協議棧的核心,LL層定義了兩個設備如何利用無線電傳輸信息,包含了報文、廣播、數據通道的詳細定義,也規定了發現其他設備的流程、廣播的數據、連接建立、連接管理以及連接中的數據傳輸。比如具體選擇哪個射頻通道進行通信,怎么識別空中數據包,具體在哪個時間點把數據包發送出去,怎么保證數據的完整性,ACK如何接收,如何進行重傳,以及如何對鏈路進行管理和控制等等。LL層只負責把數據發出去或者收回來,對數據進行怎樣的解析則交給上面的GAP或者GATT。
3.2.1 鏈路層狀態機定義了五種狀態:
-
就緒態(Standby):准備狀態,不傳輸或接受數據包
-
廣播態(Advertising):發送廣播數據,回應scanner的響應
-
掃描態(Scanning):監聽/掃描,監聽廣播包,(主動掃描、被動掃描)
-
發起態(Initiating):初始化,監聽來自特殊設備的廣播包,並進行初始化連接
-
連接態(Connection):連接狀態,主機角色(從initiator進入)/從機角色(從advertiser進入)
3.2.2 狀態轉移過程
- 對於主機而言:standby -> scanning -> initiating -> connection/master
- 對於設備而言:standby -> advertising -> connection/slave
- 對於scanning狀態,主要用於如下場景:當一個設備在收到advertise消息后,如要獲取更多關於改advertise的消息,會進入scanning狀態
3.3 HCI(Host controller interface,主機控制接口)
HCI是可選的,主要用於2顆芯片實現BLE協議棧的場合,用來規范兩者之間的通信協議和通信命令等。
3.4 L2CAP(Logic link control and adaptation protocol,邏輯鏈路控制和適配協議)
L2CAP對LL層進行了一次簡單封裝,LL只關心傳輸數據的本身,L2CAP就要區分是加密通道還是普通通道,同時還要對連接間隔進行管理。
(1)信道,L2CAP的基本概念是信道(Signaling Channel)。信道是個抽象概念,表示兩個設備某個協議層之間的通道。每個信道分配一個2字節的信道ID-CID(Channel ID),每個信道功用不同,對於BLE協議,L2CAP共有三個信道ID:
- 0x0004 – 屬性協議
- 0x0005 – 低功耗信令信道
- 0x0006 – 安全管理協議
其他信道則用於經典藍牙。協議復用可以理解為不同的協議走不同的信道,互不干擾。
(2)數據格式與MTU
(3)更新連接參數
-
最小連接間隔(Min Connection Interval)
-
最大連接間隔(Max Connection Interval)
-
從設備延遲響應(Latency)
-
監控超時(Supervisor Timeout)
3.5 ATT(Attribute protocol,屬性協議)
ATT層用來定義用戶命令及命令操作的數據,比如讀取某個數據或者寫某個數據。BLE協議棧中,開發者接觸最多的就是ATT。BLE的數據存儲在屬性服務器的“屬性”里,供屬性客戶端執行讀寫操作,客戶端將請求發送至服務器,服務器回復響應。BLE引入了attribute概念,用來描述一條一條的數據。Attribute除了定義數據,同時定義該數據可以使用的ATT命令,及ATT PDU(Protocol Data Unit,協議數據交互單元),分為4類:讀(Read)、寫(write)、通知(notify)、指示(indicate)。
屬性協議定義了六種類型的信息:
- 從客戶端發送至服務器的請求
- 從服務器發送至客戶端的回復請求的響應
- 從客戶端發送至服務器的無需響應的命令
- 從服務器發送至客戶端的無需確認的通知
- 從服務器發送至客戶端的指示
- 從客戶端發送至服務器的回復指示的確認
3.6 GATT(Generic attribute profile,屬性協議配置規范)
GATT用來規范attribute中的數據內容,並運用group(分組)的概念對attribute進行分類管理。沒有GATT,BLE協議棧也能跑,但互聯互通就會出問題,也正是因為有了GATT和各種各樣的應用profile,BLE擺脫了ZigBee等無線協議的兼容性困境,成了出貨量最大的2.4G無線通信產品。
3.7 SMP (Secure manager protocol,安全管理)
SMP用來管理BLE連接的加密和安全的,如何保證連接的安全性,同時不影響用戶的體驗,這些都是SMP要考慮的工作。
3.8 GAP(Generic access profile,通用訪問規范)
GAP是對LL層payload(有效數據包)進行解析的兩種方式中的一種,而且是最簡單的那一種。GAP簡單的對LL payload進行一些規范和定義,因此GAP能實現的功能極其有限。GAP目前主要用來進行廣播,掃描和發起連接等。
4、 協議棧在數據無線發送中的作用?
其實協議棧的主要作用就是將用戶發送的數據打包成低功耗藍牙數據包的格式發送出去,並將接收的數據按照低功耗藍牙數據包的格式解析出來。
假設有設備A和設備B,設備A需要把自己的當前的電量狀態83%(0x53)發送給B。
作為BLE應用開發人員,理想狀態是調用API send(0x53)即可,剩下的交給藍牙協議棧。
4.1 廣播模式
(1) GAP層
引入LTV(Length-Type-Value)結構來定義數據,比如020104,02-長度,01-類型(強制字段,表示廣播flag,廣播包必須包含該字段),04-值。發送的電量數據0x53通過GAP層封裝成04FFD70753
,其中0xFF表示數據類型(自定義類型),0x07D7
是供應商ID(自定義數據中的強制字段)。
- 加上廣播必須的字段,經過GAP層的封裝,數據包變成:
02010404FFD70753
(2)LL層
-
在數據前加上設備A的地址0x84C2E43C3886,為了告訴其他設備,這組數據是由設備A發出的,
數據包變成:86383CE4C28402010404FFD70753
-
此時為了設備B能夠找到電量數據0x3C,增加LL header和長度字節,
數據包變成:020E86383CE4C28402010404FFD70753
-
為了確保數據的完整性,增加CRC24校驗,
數據包變成:020E86383CE4C28402010404FFD70753CAA024
-
此刻的數據發出去,設備B並不知道這個數據是發給自己的,為此引入access address概念,用來指明接收者身份。0x8E89BED6表示發送給周圍所有設備,即廣播,連接時會隨機生成一組地址。
D6BE898E020E86383CE4C28402010404FFD70753CAA024
-
最后加上前導包0xAA,完成的數據包為
AAD6BE898E020E86383CE4C28402010404FFD70753CAA024
- AA – 前導幀(preamble)
- D6BE898E – 訪問地址(access address)
- 60 – LL幀頭字段(LL header)
- 0E – 有效數據包長度(payload length)
- 86383CE4C284 – 廣播者設備地址(advertiser address)
- 02010404FFD70753 – 廣播數據
- CAA024 – CRC24值
有了PHY,LL和GAP,就可以發送廣播包了,但廣播包攜帶的信息極其有限,而且還有如下幾大限制:
- 無法進行一對一雙向通信 (廣播是一對多通信,而且是單方向的通信)
- 由於不支持組包和拆包,因此無法傳輸大數據
- 通信不可靠及效率低下。廣播信道不能太多,否則將導致掃描端效率低下。為此,BLE只使用37(2402MHz) /38(2426MHz) /39(2480MHz)三個信道進行廣播和掃描,因此廣播不支持跳頻。由於廣播是一對多的,所以廣播也無法支持ACK。這些都使廣播通信變得不可靠。
- 掃描端功耗高。由於掃描端不知道設備端何時廣播,也不知道設備端選用哪個頻道進行廣播,掃描端只能拉長掃描窗口時間,並同時對37/38/39三個通道進行掃描,這樣功耗就會比較高。
而連接則可以很好解決上述問題,下面我們就來看看連接是如何將0x53發送出去的。
4.2 連接模式
到底什么叫連接(connection)?像有線UART,很容易理解,就是用線(Rx和Tx等)把設備A和設備B相連,即為連接。用“線”把兩個設備相連,實際是讓2個設備有共同的通信媒介,並讓兩者時鍾同步起來。藍牙連接有何嘗不是這個道理,所謂設備A和設備B建立藍牙連接,就是指設備A和設備B兩者一對一“同步”成功,其具體包含以下幾方面:
- 設備A和設備B對接下來要使用的物理信道達成一致
- 設備A和設備B雙方建立一個共同的時間錨點,也就是說,把雙方的時間原點變成同一個點
- 設備A和設備B兩者時鍾同步成功,即雙方都知道對方什么時候發送數據包什么時候接收數據包
- 連接成功后,設備A和設備B通信流程如下所示:
如上圖所示,一旦設備A和設備B連接成功(此種情況下,我們把設備A稱為Master或者Central,把設備B稱為Slave或者Peripheral),設備A將周期性以CI(connection interval)為間隔向設備B發送數據包,而設備B也周期性地以CI為間隔打開射頻接收窗口以接收設備A的數據包。同時按照藍牙spec要求,設備B收到設備A數據包150us后,設備B切換到發送狀態,把自己的數據發給設備A;設備A則切換到接收狀態,接收設備B發過來的數據。由此可見,連接狀態下,設備A和設備B的射頻發送和接收窗口都是周期性地有計划地開和關,而且開的時間非常短,從而大大降低系統功耗並大大提高系統效率。
對開發者來說,很簡單,他只需要調用send(0x53)
-
GATT層定義數據的類型和分組,用0x0013表示電量這種數據類型,這樣GATT層把數據打包成130053
-
ATT層用來選擇具體的通信命令,比如讀/寫/notify/indicate等,選擇notify命令0x1B,這樣數據包變成了:1B130053
-
L2CAP用來指定connection interval(連接間隔),比如每10ms同步一次(CI不體現在數據包中),同時指定邏輯通道編號0004(表示ATT命令),最后把ATT數據長度0x0004加在包頭,這樣數據就變為:
040004001B130053
-
LL層分配一個Access address(0x50655DAB)以標識此連接只為設備A和設備B直連服務,然后加上LL header和payload length字段和最后加上CRC24字段,數據包最后變成:
55AB5D65501E08040004001B130053D550F6
- 55 – 前導幀(preamble)
- 0x50655DAB – 訪問地址(access address)
- 1E – LL幀頭字段(LL header)
- 08 – 有效數據包長度(payload length)
- 00040004 – ATT數據長度,以及L2CAP通道編號
- 1B – notify command
- 0x0013 – 電量數據handle
- 0x53 – 真正要發送的電量數據
- 0xF650D5 – CRC24值
參考鏈接: