藍芽協議分析_BLE連線有關的技術分析
1. 前言
瞭解藍芽的人都知道,在經典藍芽中,保持連線(Connection)是一個相當消耗資源(power和頻寬)的過程。特別是當沒有資料傳輸的時候,所消耗的資源完全被浪費了。因而,對很多藍芽裝置來說(特別是功耗敏感的裝置),希望在無數可傳的時候,能夠斷開連線。但是,由於跳頻(hopping)以及物理通道(Physical Channel)劃分的緣故,經典藍芽連線建立的速度實在難以忍受(要好幾秒)。對那些突發的資料傳輸來說,幾秒鐘的連線延遲,簡直是災難。
因此,藍芽SIG制訂BLE規範的時候,充分考慮了這方面的需求,極大的簡化了連線的建立過程,使連線速度可以達到毫秒級(最快3.75ms就可以搞定)。與此同時,為了節省功耗,也調整了跳頻的策略。至此,相比廣播通訊而言,BLE面向連線的通訊,幾乎沒有額外的代價。
在“藍芽協議分析(5)_BLE廣播通訊相關的技術分析”中,我們對BLE的廣播通訊有了比較全面的瞭解,本文將接著分析和麵向連線的通訊有關的技術,包括連線的建立和斷開、BLE跳頻(Hopping)技術、Link Layer的應答、重傳、流控、等等。
2. 怎樣才算是建立了連線?
開始之前,我們先回答一個問題,對通訊的雙方而言,怎樣才算建立了連線呢?
從字面上理解,建立了連線,就是指:
二者之間,建立了一條專用的通道,它們可以隨時隨地的通訊。
當然,在藍芽這種資源有限的通訊系統中,通道無法獨佔,退而求其次,分時也Okay。因此,在BLE中建立了連線,是這樣定義的:
在約定的時間段內,雙方都到一個指定的物理Channel上通訊。
其中,“約定好的時間段”,是時分的概念。而“到指定的物理Channel上”,是跳頻的概念。後面的分析,將會圍繞這兩個概念進行。
另外,和“藍芽協議分析(5)_BLE廣播通訊相關的技術分析”類似,我們也將從Link Layer、HCI、GAP三個層次,分別介紹。
3. Link Layer
3.1 角色的定義
和經典藍芽一樣,協議為處於連線狀態的BLE裝置,定義了兩種Link Layer角色:Master和Slave。Master是連線的發起方(Initiator),可以決定和連線有關的引數(很重要,後面會詳細介紹)。Slave是連線的接受方(Advertiser),可以請求(或建議)連線引數,但無法決定。
注1:兩個BLE裝置之間,只能建立一條連線。
3.2 PDU的定義
和廣播通訊不同,面向連線的通訊使用特定的PDU,稱作Data Channel PDU,格式如下(LSB---->MSB):
Header(16 bits) | Payload(Variable size) | MIC(32 bits) |
16bits的Header的格式如下:
LLID(2 bits) | NESN (1bit) | SN(1 bit) | MD(1 bit) | RFU(3 bits) | Length(8 bits) |
Data Channel傳輸的PDU有兩類,一類是資料,稱作LL Data PDU,另一類中控制資訊,稱作LL Control PDU。LLID用於區分PDU的型別,具體可參考後面3.2.1和3.2.2的描述。
NESN(Next Expected Sequence Number)和SN(Sequence Number),用於資料傳輸過程中的應答(Acknowledgement)和流控(Flow Control),具體可參考後面3.7的介紹。
MD(More Data),用於連線的關閉(或者說保持),具體可參考後面3.5的介紹。
RFU(Reserved for Future Use)。
Length,有效資料的長度(Payload+MIC),只有8-bits,因此Link Layer所能傳輸的最大資料是255 bytes(有MIC的話是251bytes),如果L2CAP需要傳輸更多的資料,需要分包之後傳輸(這也是L2CAP的主要功能之一,具體可參考“藍芽協議分析(3)_藍芽低功耗(BLE)協議棧介紹”)。
Payload是有效資料(SDU,L2CAP的PDU),長度由Header中的Length欄位覺得,有效範圍是0~255。
3.2.1 LL Data PDU
LL Data PDU有兩種:
Header中的LLID=01b時,Continuation fragment of an L2CAP message, or an Empty PDU。這種型別的PDU,要麼是一個未傳輸完成L2CAP message(長度超過255,被拆包,此時不是第一個),要麼是一個空包(Header中的Length為0)。
Header中的LLID=10b時,Start of an L2CAP message or a complete L2CAP message with no fragmentation。這種型別的PDU,要麼是L2CAP message的第一個包,要麼是不需要拆包的完整的L2CAP message,無論哪種情況,Header中的Length均不能為0。
3.2.2 LL Control PDU
Header中的LLID=11b時,表示這個資料包是用於控制、管理LL連線的LL control PDU。LL control PDU的payload的格式如下:
Opcode(1 octet) | CtrlData(0 ~ 26 octets) |
其中Opcode指示控制&管理packet的型別,包括:
LL_CONNECTION_UPDATE_REQ,連線引數的更新; LL_CHANNEL_MAP_REQ,Channel map的更新; LL_TERMINATE_IND,連線即將被關閉的通知(可以通知被關閉的原因); LL_ENC_REQ、LL_ENC_RSP、LL_START_ENC_REQ、LL_START_ENC_RSP,加密有關的請求;等等,具體可參考“BLUETOOTH SPECIFICATION Version 4.2 [Vol 6, Part B]”。
3.3 連線的建立
對BLE來說,連線建立的過程很簡單,包括:
1)處於connectable狀態裝置(Advertiser),按照一定的週期廣播ADV_IND或者ADV_DIRECT_IND包(可參考“藍芽協議分析(5)_BLE廣播通訊相關的技術分析”)。
2)主動連線的裝置(Initiator),在收到廣播包之後,會迴應一個CONNECT_REQ請求,該請求攜帶了可決定後續“通訊時序”的引數,例如雙方在哪一個時間點、哪一個Physical Channel收發資料,等等,後面會詳細描述。
3)Initiator在發出CONNECT_REQ資料包之後,自動轉變為Connection狀態,成為Master角色(注意:這是“自動”的,不需要等待另一方的迴應)。同樣,Advertiser在收到CONNECT_REQ請求之後,也自動轉變為Connection狀態,成為Slave角色。
4)此後,雙方按照CONNECT_REQ引數所給出的約定,定時到切換到某一個Physical Channel上,按照Master->Slave然後Slave->Master的順序,收發資料,直至連線斷開。
master在發出連線請求的時候,需要在CONNECT_REQ PDU的payload中,定義和連線有關的引數。payload的格式如下:
InitA (6 octets) | AdvA (6 octets) | LL Data (22 octets) |
其中InitA和AdvA分別是Master和Slave的藍芽地址,LL data則包含了所有的連線引數,包括:
AA (4 octets) | CRCInit (3 octets) | WinSize (1 octet) | WinOffset (2 octets) | Interval (2 octets) | Latency (2 octets) | Timeout (2 octets) | ChM (5 octets) | Hop (5 bits) | SCA (3 bits) |
AA,LL Connection的Access Address,在不同裝置組合之間,需要唯一,並遵守一些原則,具體可參考“BLUETOOTH SPECIFICATION Version 4.2 [Vol 6, Part B]”。
CRCInit,用於CRC計算的一個初始值,由Link Layer隨機生成。
WinSize和WinOffset,全稱是transmitWindowSize和transmitWindowOffset,用於決定連線雙方收發資料的時間視窗(第2章提到的時分的概念)。下面3.4小節會詳細介紹。
connInterval,全稱是connInterval,連線雙方收發資料的週期。由於一個Master可能會和多個Slave建立連線,因此藍芽的通道資源不能被某一個LL Connection所獨佔,所以一個收發週期中,可能有多個連線進行收發資料(具體的時間視窗,由transmitWindowOffset決定)。下面3.4小節會詳細介紹。
Latency和Timeout,全稱是connSlaveLatency和connSupervisionTimeout,和連線超時、自動斷開有關,具體可參考3.4小節的描述。
ChM的全稱是Channel map,用於標識當前使用和未使用的Physical Channel。Hop的全稱是hopIncrement,它和ChM一起決定了資料傳輸過程中的跳頻演算法,具體可參考3.6小節的描述。
SCA(sleep clock accuracy),用於定義最差的Master睡眠時鐘精度,具體可參考“BLUETOOTH SPECIFICATION Version 4.2 [Vol 6, Part B]”,本文不再詳細介紹。
3.4 連線建立後的通訊過程
3.3小節提到,當Master發出/Slave收到CONNECT_REQ後,就自動進入連線狀態,那雙方在收發資料的時間視窗怎麼確定呢?可參考下面圖片1和圖片2:
圖片1 BLE連線時序---Master視角
圖片2 BLE連線時序---Slave視角
1)從Master的視角看,當它發出CONNECT_REQ後,會在1.25 ms + transmitWindowOffset到1.25ms + transmitWindowOffset + transmitWindowSize之間,傳送第一個packet(M->S)。同理,Slave在收到CONNECT_REQ之後,也會在相應的時間區間去接收packet(M->S)。
a)transmitWindowOffset可以控制這個LL Connection使用哪一段時間進行通訊,從而保證了同一個Master和多個Slave之間的多個連線,可以互不影響的通訊(時分)。transmitWindowOffset的取值範圍是:0 ms到connInterval(後面會介紹connInterval)。
b)從Master發出CONNECT_REQ,到Slave接收到CONNECT_REQ,是有一定的時間延遲的,因此需要一定的時間視窗(transmitWindowSize),才能保證第一個packet能否正確的傳送並被接收。transmitWindowSize必須是1.25ms的倍數,最小值是1.25 ms,最大值是(connInterval - 1.25 ms),但不能超過10ms。
c)正常情況下,所有“M->S”資料包的傳送,不能超過transmitWindowSize,以便留出S->M的時間。但第一個packet例外(參考上面圖片1)。
2)Master發出第一個packet之後,將以此為起始點(稱作anchor point),以connInterval為週期,接著傳送後續的packet(M->S),以及接收Slave的packet(S->M),具體可參考上面圖片1。
a)這樣以connInterval為週期的傳送(M->S)、接收(S->M)組合(可能有多個),稱作Connection Event。因此BLE面向連線的通訊的基礎,就是Connection Event。
b)connInterval的大小,決定了資料傳輸的週期。對一個連線來說,每個週期只能有一次的收發,因此connInterval的選擇,直接決定了資料傳輸的速度。BLE協議規定,connInterval必須是1.25ms的倍數,範圍是7.5ms~4s。
3)Slave如果沒有收到第一個packet(M->S),則會以1.25 ms + transmitWindowOffset為起點,等待connInterval之後,再次嘗試接收,直到接收到為止。Slave接收到packet之後,則以收到該packet的時間點為起始點(anchor point),以connInterval為週期,接著接收後續的packet(M->S),以及傳送packet給Master(S->M),具體可參考上面圖片2。
注2,關於資料傳輸的速率: 由上面的通訊過程可知,BLE面向連線的通訊速率,是由connInterval以及每個Connection Event中所傳輸的資料量決定的。 由上面3.2的描述可知,LL Data PDU的有效負荷不能超過255(251)bytes,不過考慮到一次傳輸的效率、錯誤處理等因素,具體的Link Layer不會使用這麼大的packet。相應地,為了提高傳輸速度,一般會在一個Connection Event中,傳輸多個packet。以iOS為例,它可能會在一個Connection Event中,傳輸6個packets,每個packet的長度是20bytes。 另外,很多平臺為了保證自身作為Master的效能,會限制connInterval的最小值,以iOS為例,最小值是30ms。因此,可估算得到相應的傳輸速率為20B * 6 / 30ms = 32kbps,是相當緩慢的。
注3:BLE的面向連線通訊是使用跳頻技術的,即每次Connection Event,都會使用不同Physical Channel收發資料,具體的跳頻機制,可參考3.6小節的介紹。
3.5 連線的控制與管理
連線建立之後,Master或者Slave可以藉助Link Layer Control Protocol (LLCP),通過LL Control PDU,對連線進行管理控制,包括:
Connection Update Procedure,連線引數(包括connInterval,connSlaveLatency,connSupervisionTimeout)更新的通知。只能由Master發起。
Channel Map Update Procedure,更新Channel map。只能由Master發起。
Encryption Procedure,對連線進行加密,可由master或者slave發起。
Termination Procedure,斷開連線。
Connection Parameters Request Procedure,請求更新連線引數(connInterval,connSlaveLatency,connSupervisionTimeout),Slave或者Master都可以發起,和Connection Update Procedure不同是,這是一個協商的過程,不是一定能夠成功。
LE Ping Procedure,類似於網路協議中ping操作。
等等。不再詳細介紹,具體可參考“BLUETOOTH SPECIFICATION Version 4.2 [Vol 6, Part B]”。
3.6 連線超時及斷開
BLE連線斷開的原因有兩種:一種是預期內的、主動斷開,此時會走3.4小節提到的Termination Procedure過程;第二種是一些非預期的原因導致的超時斷開,如距離超出、遭受嚴重的干擾、突然斷電等。
對於第一種,是協議內的正常流程,沒有什麼好說的。而對於第二種,則需要一些timeout機制,檢測這寫異常情況,具體如下。
1)Master和Slave的Link Layer,都會啟動一個名稱為TLLconnSupervision的timer,每接收到一個有效的資料包時,該timer都會重置。
2)連線建立的過程中,如果TLLconnSupervision超過6 * connInterval(沒有接收到第一個資料包),則認為連線建立失敗。
3)在連線成功之後,如果TLLconnSupervision超過connSupervisionTimeout,則說明link loss,則執行超時斷開。connSupervisionTimeout是一個可配置的引數,範圍是100ms~32s,並且不能大於(1 + connSlaveLatency) * connInterval * 2。
4)BLE協議允許slave忽略掉“connSlaveLatency”個Connection Event,在被忽略的這段時間內,Slave不需要收發資料包,也不會增加TLLconnSupervision,從而引發超時斷開。connSlaveLatency是一個整數,有效範圍應該在0到((connSupervisionTimeout / (connInterval*2)) - 1)之間,並且不能大於500。
注4:connSlaveLatency是一個非常有用的引數,它允許Slave在資料通訊不頻繁的時候,忽略掉一些Connection Event,進而可以睡得更久,更加省電。
3.7 跳頻(Hopping)策略
BLE的跳頻策略是非常簡單的,即:每一個Connection Event,更換一次Physical Channel,當然,master和slave需要按照相同的約定更換,不然就無法通訊。這個約定如下:
圖片3 BLE跳頻策略
1)首先,使用一個Basic的演算法,利用lastUnmappedChannel和hopIncrement,計算出unmappedChannel。
a)lastUnmappedChannel在連線建立之初的值是0,每一次Connection Event計算出新的unmappedChannel之後,會更新lastUnmappedChannel。
b)hopIncrement是由Master在連線建立時隨機指定的,範圍是5到16(可參考3.3中的Hop)。
c)確定unmappedChannel的演算法為:unmappedChannel = (lastUnmappedChannel + hopIncrement) mod 37,本質上就是每隔“hopIncrement”個Channel取一次,相當直白和簡單。
2)計算出unmappedChannel之後,查詢當前的Channel map,檢查unmappedChannel所代表的Channel是否為used channel。如果是,恭喜,找到了。
Channel map也是由master,在連線建立時,或者後來的Channel map update的時候指定的。
3)如果不是,將所有的used Channel以升序的方式見一個表,表的長度是numUsedChannels,用unmappedChannel和numUsedChannels做模運算,得到一個index,從按照該index,從表中取出對應的channel即可。
3.8 應答(Acknowledgement)和流控(Flow Control)
由3.2小節的描述可知,LL Data PDU的Header中,有NESN(Next Expected Sequence Number)和SN(Sequence Number)兩個標記,利用它們,可以很輕鬆的在Link Layer實現應答、重傳、流控等機制。
為了實現這些功能,Link Layer會為每個連線建立兩個變數,transmitSeqNum和nextExpectedSeqNum(為了和packet的SN/NESN bit區分,我們將它們簡稱為sn和nesn),並在連線建立的時候,它們都被初始化為0。
sn用於標識本地裝置(Link Layer)傳送出去的packets。
nesn是對端裝置(Link Layer)用來應答本地裝置傳送的packet,或者請求本地裝置重發packet。
Link Layer在收發packet時,會遵循如下的原則(可結合下面圖片4理解):
注5:下面圖片4是從“BLUETOOTH SPECIFICATION Version 4.2 [Vol 6, Part B]”中截的一張圖,不過spec中畫的有問題,我用紅色字型改正了。另外,這個圖片非常有歧義、難以理解,我會在下面解釋。
1)無論是Master還是Slave,傳送packet的時候,都會將當前的sn和nesn copy到packet的SN和NESN bit中。
2)無論是Master還是Slave,當接收到一個packet的時候,會將該packet的NESN bit和本地的sn比較:如果相同,說明該packet是對端裝置發來的NAK packet(請求重發),則需要將舊的packet重新發送出去;如果不同,說明是對端裝置發來的ACK packet(資料被正確接收),則需要將本地的sn加1,接著傳送新的packet。
a)以上過程可參考下面圖片4中的左邊部分。
b)本地的sn,代表本地裝置已經發送出去的packet,而packet中的NESN bit,代表對端裝置期望本地裝置傳送的packet。如果二者相同,說明對方期望下次傳送的packet,和我們已經發送的packet相同,因此是NAK訊號,要求重發。如果二者不同,說明對方裝置期望傳送一個新的packet,也說明我們上次傳送的packet已經成功接收,因此可以將本地的sn加1了。
3)無論是Master還是Slave,當接收到一個packet的時候,會將該packet的SN bit和本地的nesn比較:如果相同,則說明是一個新的packet,接收即可,同時將本地的nesn加1;如果不同,則說明是一箇舊的packet,什麼都不需要處理。
a)以上過程可參考下面圖片4中的右邊部分。
b)packet中的SN bit,代表對端裝置正在傳送的packet,而本地裝置的nesn,代表本地裝置期望對端裝置傳送的packet。如果二者相同,則說明是一個期望的packet(新的),就可以收下該packet,並將期望值加1(nesn加1)。如果二者不同,說明不是本地裝置期望的packet,什麼都不做就可以了。
4)上面2)和3)兩個步驟,是相互獨立的,因此一個NAK packet,也可能攜帶新的資料,反之亦然。
5)當一個裝置無法接收新的packet的時候(例如RX buffer已滿),它可以採取不增加nesn的方式,傳送NAK packet。對端裝置收到該型別的packet之後,會發送舊的packet(圖片4左邊部分的“TX old data, sn”分支)。該裝置收到這樣舊的packet的時候,不會做任何處理(圖片4右邊部分的“Ignore RX data”分支)。這就是Link Layer的流控機制(Flow control)
圖片4 BLE應答和流控機制
4. HCI
HCI(Host Control Interface)的功能就簡單多了,就是要封裝Link Layer所提供的功能,包括兩類。
1)連線的建立、關閉、引數設定、管理等,這一類是通過HCI command/event(其格式可參考“藍芽協議分析(5)_BLE廣播通訊相關的技術分析”中的介紹)完成的,包括:
LE Create Connection Command,建立連線的命令,需要提供連線有關的引數,包括connInterval(Conn_Interval_Min和Conn_Interval_Max)、connSlaveLatency(Conn_Latency)和connSupervisionTimeout(Supervision_Timeout)。
LE Create Connection Cancel Command,取消或者斷開連線。
LE Connection Update Command,更新連線引數,包括connInterval(Conn_Interval_Min和Conn_Interval_Max)、connSlaveLatency(Conn_Latency)和connSupervisionTimeout(Supervision_Timeout)。
LE Set Host Channel Classification Command,配置Channel map。
LE Read Channel Map Command,讀取Channel map。
等等。
有關這些命令的具體描述,可參考“BLUETOOTH SPECIFICATION Version 4.2 [Vol 2, Part E] Host Controller Interface Functional Specification”。
2)對ACL data的封裝和轉發,不再詳細說明。
6. GAP
GAP(Generic Access Profile)的主要功能,是定義BLE裝置所具備的能力,以實現互聯互通的功能。
對BEL基於連線的通訊來說,GAP定義了4種連線有關的模式(不同的產品形態,可以選擇是否支援這些模式,具體可參考“BLUETOOTH SPECIFICATION Version 4.2 [Vol 3, Part C] 9.3 CONNECTION MODES AND PROCEDURES”):
Non-connectable mode,不可被連線。
Directed connectable mode,可以被“直連”(在知道對方藍芽地址的情況下的快速連線)。
Undirected connectable mode,可以被“盲連”(不知道對方藍芽地址)。
Auto connection establishment procedure,可以被自動連線(不需要host干預)。
相應地,GAP定義了5中和這些模式有關的過程(不同的產品形態,可以選擇是否支援這些過程):
General connection establishment procedure,通用的連線建立過程,搜尋、發現、連線,都需要Host參與。
Selective connection establishment procedure,有選擇的連線建立過程,Host需要告訴Controller,自己只希望於特定的裝置建立連線。
Direct Connection Establishment Procedure,直接和某一個已知裝置建立連線(對方也知道我們)。
Connection Parameter Update Procedure,連線引數的更新過程。
Terminate Connection Procedure,斷開連線。
這些mode和procedure的具體描述,可參考藍芽spec[1]。
7. 參考文件
[1] Core_v4.2.pdf