1. 程式人生 > >藍芽協議分析_BLE連線有關的技術分析

藍芽協議分析_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:

BLE連線時序---Master視角

圖片1 BLE連線時序---Master視角

BLE連線時序---Slave視角

圖片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需要按照相同的約定更換,不然就無法通訊。這個約定如下:

BLE跳頻策略

圖片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)

BLE應答和流控機制

圖片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