TI低功耗藍牙(BLE)介紹

一、概述

 

1、BLE藍牙協議棧結構

附圖6 BLE藍牙協議棧結構圖

分爲兩部分:控制器和主機。對於4.0以前的藍牙,這兩部分是分開的。所有profile(姑且稱爲劇本吧,用來定義設備或組件的角色)和應用都建構在GAP或GATT之上。下面由結構圖的底層組件開始介紹。 

·        PHY層,工作車間,1Mbps自適應跳頻GFSK(高斯頻移鍵控),運行在免證的2.4GHz

·        LL層爲RF控制器,控制室,控制設備處於準備(standby)、廣播、監聽/掃描(scan)、初始化、連接,這五種狀態中一種。五種狀態切換描述爲:未連接時,設備廣播信息(向周圍鄰居講“我來了”),另外一個設備一直監聽或按需掃描(看看有沒有街坊鄰居家常裏短可聊,打招呼“哈,你來啦”),兩個設備連接初始化(搬幾把椅子到院子),設備連接上了(開聊)。發起聊天的設備爲主設備,接受聊天的設備爲從設備,同一次聊天只能有一個意見領袖,即主設備和從設備不能切換。

·        HCI層,爲接口層,通信部,向上爲主機提供軟件應用程序接口(API),對外爲外部硬件控制接口,可以通過串口、SPI、USB來實現設備控制。

·        L2CAP層,物流部,行李打包盒拆封處,提供數據封裝服務

·        SM層,保衛處,提供配對和密匙分發,實現安全連接和數據交換

·        ATT層,庫房,負責數據檢索

·        GATT層,出納/庫房前臺,出納負責處理向上與應用打交道,而庫房前臺負責向下把檢索任務子進程交給ATT庫房去做,其關鍵工作是把爲檢索工作提供合適的profile結構,而profile由檢索關鍵詞(characteristics)組成。

·        GAP層,祕書處,對上級,提供應用程序接口,對下級,管理各級職能部門,尤其是指示LL層控制室五種狀態切換,指導保衛處做好機要工作。

TI的這款CC2540器件可以單芯片實現BLE藍牙協議棧結構圖的所有組件,包括應用程序。

 

2、任務調度---OSAL操作系統抽象層

正如一個公司爲了實現擴大產能和產品多樣化,建立了多個辦公室和工廠一樣,藍牙爲了實現同多個設備相連,或實現多功能,也實現了功能擴充,這就產生了調度問題。因爲,雖然軟件和協議棧可擴充,但終究最底層的執行部門只有一個。

爲了實現多事件和多任務切換,需要把事件和任務對應的應用,以及其相關的提供支撐“辦公室”和“工廠”打包起來,並起一個名字OSAL操作系統抽象層,類似於集團公司以下的子公司

 

3、設備改造---HAL硬件抽象層

如果實現軟件和硬件的低耦合,使軟件不經改動或很少改動即可應用在另外的硬件上,這樣就方便硬件改造、升級、遷移後,軟件的移植。HAL硬件抽象層正是用來抽象各種硬件的資源,告知給軟件。其作用類似於嵌入式系統設備驅動的定義硬件資源的h頭文件。其角色類似於現代工廠的設備管理部

 

4、BLE低功耗藍牙系統架構

附圖7 BLE低功耗藍牙系統架構圖,圖中的Task用附圖6BLE藍牙協議棧結構圖來描述

BLE低功耗藍牙軟件有2個主要組成: OSAL操作系統抽象層和 HAL硬件抽象層,多個Task任務和事件在OSAL管理下工作,而每個任務和事件又包括3個組成:BLE 協議棧,profiles和應用程序。

附圖7同樣可以用現代工廠模式來類比,如附圖8。

附圖8 BLE低功耗藍牙軟件5個主要組成用現代工廠架構來類比。

有了上面的簡介,下面對OSAL、HAL和BLE進行稍微深入的介紹。

 

二、OSAL操作系統抽象層

 

1、軟件功能由OSAL管理下的事件來實現

OSAL作爲調度核心,BLE協議棧、profile定義、所有的應用都圍繞它來實現。OSAL不是傳統大家使用的操作系統,而是一個允許軟件建立和執行事件的循環。

軟件功能是由任務事件來實現的,創建一個任務事件需要以下工作:

·        創建task identifier任務ID;

·        編寫任務初始化(task initialization routine)進程,並需要添加到OSAL初始化進程中,這就是說系統啓動後不能動態添加功能;

·        編寫任務處理程序;

·        如有需要提供消息服務。

BLE協議棧的各層都是以OSAL任務方式實現,由於LL控制室的時間要求最爲迫切,所以其任務優先級最高。爲了實現任務管理,OSAL通過消息處理(messageprocess),存儲管理,計時器定時等附加服務實現。

 

2、系統啓動流程

爲了使用OSAL,在main函數的最後要啓動一個名叫osal_start_system的進程,該進程會調用由特定應用決定的啓動函數osalInitTasks(來啓動系統)。osalInitTasks逐個調用BLE協議棧各層的啓動進程來初始化協議棧。隨後,設置一個任務的8bit任務ID(task ID),跳入循環等待執行任務,系統啓動完成。

 

3、任務事件與事件處理

進程優先級和任務ID

·        任務優先級決定於任務ID,任務ID越小,優先級越高

·        BLE協議棧各層的任務優先級比應用程序的高

·        初始化協議棧後,越早調入的任務,任務ID越高,優先級越低,即系統傾向於處理新到的任務

事件變量和旗語

每個事件任務由對應的16bit事件變量來標示,事件狀態由旗號(taskflag)來標示。如果事件處理程序已經完成,但其旗號並沒有移除,OSAL會認爲事情還沒有完成而繼續在該程序中不返回。比如,在SimpleBLEPeripheral實例工程中,當事件START_DEVICE_EVT發生,其處理函數SimpleBLEPeripheral_ProcessEvent就運行,結束後返回16bit事件變量,並清除旗語SBP_START_DEVICE_EVT。

事件處理表單

每當OSAL事件檢測到了有任務事件,其相應的處理進程將被添加到由處理進程指針構成的事件處理表單中,該表單名叫taskArr(taskarray)。taskArr中各個事件進程的順序和osalInitTasks初始化函數中任務ID的順序是對應的。

事件調度的方法

有兩種,最簡單的方法是使用osal_set_event函數(函數原型在OSAL.h文件中),在這個函數中,用戶可以像定義函數參數一樣設置任務ID和事件旗語。第二種方法是使用osal_start_timerEx函數(函數原型在OSAL_Timers.h文件中),使用方法同osal_set_event函數,而第三個以毫秒爲單位的參數osal_start_timerEx則指示該事件處理必須要在這個限定時間內,通過定時器來爲事件處理計時。

 

4、存儲管理

類似於Linux嵌入式系統內存分配C函數mem_alloc,OSAL利用osal_mem_alloc提供基本的存儲管理,但osal_mem_alloc只有一個用於定義byte數的參數。對應的內存釋放函數爲osal_mem_free。

 

5、進程間通信—通過消息機制實現

不同的子系統通過OSAL的消息機制通信。消息即爲數據,數據種類和長度都不限定。

消息收發過程描述如下:

接收信息,調用函數osal_msg_allocate創建消息佔用內存空間(已經包含了osal_mem_alloc函數功能),需要爲該函數指定空間大小,該函數返回內存空間地址指針,利用該指針就可把所需數據拷貝到該空間。

發送數據,調用函數osal_msg_send,需爲該函數指定發送目標任務,OSAL通過旗語SYS_EVENT_MSG告知目標任務,目標任務的處理函數調用osal_msg_receive來接收發來的數據。建議每個OSAL任務都有一個消息處理函數,每當任務收到一個消息後,通過消息的種類來確定需要本任務做相應處理。消息接收並處理完成,調用函數osal_msg_deallocate來釋放內存(已經包含了osal_mem_free函數功能)。

 

三、硬件抽象層HAL

 

當新的硬件平臺做好後,只需修改HAL,而不需修改HAL之上的協議棧的其他組件和應用程序。

 

四、BLE低功耗藍牙協議棧

 

1、BLE庫文件

TI藍牙協議棧是以單獨一個庫文件提供的,並沒有提供源代碼,因此不做深入說明。對於TI的BLE實例應用,這個單獨庫文件已經夠用,列出了所有的庫文件。

附圖9 BLE庫文件

由於GAP和GATT與用戶程序直接交互,因此下文對庫文件中GAP和GATT一一講解。

 

2、GAP祕書處

2.1角色(即服務,功能)

GAP運行在如下四種角色的一種:

·        Broadcaster        廣播員—我在,但只可遠觀,不可連接。

·        Observer             觀察員—看看誰在,但我只遠觀,不連接。

·        Peripheral           外設(從機)—我在,誰要我就跟誰走,協議棧單層連接。

·        Central                 核心(主機)—看看誰在,並且願意跟我走我就帶她/他走,協議棧單層或多層連接,目前最多支持3個同時連接。

雖然指標顯示BLE可以同時扮演多個角色,但是在TI提供的BLE實例應用中缺省只支持外設角色。每一種角色都由一個劇本(roleprofile)來定義。

2.2連接

主從機連接過程

一個典型的低功耗藍牙系統同時包含外設和核心(主機),兩者的連接過程如下:

外設角色向外發送自己的信息(設備地址、名字等),主機收到外設廣播信息後,發送掃描請求(scanrequest)給外設,外設響應主機的請求,連接建立完成。

連接參數

主要有通信間隙(connectioninterval)、外設鄙視(slavelatency)、最大耐心等待時間(supervisiontimeout)等,下面簡單說明。

·        通信間隙—藍牙通信是間斷的、跳頻的,每次連接都可能選擇不同的子頻帶。跳頻的好處是避免頻道擁塞,間斷連接的好處是節省功耗,通信間隙就是指兩次連接之間的時間間隔。這個間隔以1.25ms爲基本單位,最小6單位最大3200單位,間隙越小通信越及時,間隙越大功耗越低。

·        外設鄙視—外設與主機建立連接以後,沒事的時候主機總會定期發送問候信息到外設,外設懶得搭理,這些主機發送的信息就浮雲般飄過。可以忽略的連接事件個數從0到499個,最多不超過32秒。有效連接間隙= 連接間隙x (1+ 外設鄙視).

·        最大耐心等待時間—指的是爲了創建一個連接,主機允許的最大等候時間,在這個時間內,不停的嘗試連接。範圍是10個~3200個通信間隙基本單位(1.25ms)。

以上三參數大小設置優劣是顯而易見的,在此也飄過。連接參數的設置請參看後文“5.1GAP外設劇本”小節。

連接異常處理

舉例說明連接異常,如主機採用從機並不舒坦的參數來請求連接,有如主從機已經連接了,但從機有想法了,要改參數條約。通過“連接參數更新請求(ConnectionParameter Update Request)”來解決問題,交由L2CAP“收發室物流處”處理。連接參數上文已經說了,不再敘述。

加密處理

利用配對實現,利用密匙來加密授權連接。典型的過程是:外設向主機請求口令一個(passkey)以便進行配對,待主機發送了正確的口令之後,連接通信通過主從機互換密碼來校驗。由於藍牙通信是間斷通信,如果一個應用需要經常通信,而每次通信都要重新申請連接,那將是勞神費力的,爲此GAP安全衛士(SM,security profile)提供了一種長期簽證(long-termset of keys),叫做綁定(bonding),這樣每次建立連接通關流程就簡便快捷了。

 

3、出納GATT

GATT負責兩個設備間通信的數據交互。共有兩種角色:出納員(GATTClient)和銀行(GATTServer),銀行提供資金,出納從銀行存取款。銀行可以同時面對多個出納員。這兩種角色和主從機等角色是無關的。

GATT把工作拆分成幾部分來實現:讀關鍵詞(CharacteristicValue)和描述符(CharacteristicDescriptor),用來去庫房查找提取數據。寫讀關鍵詞和描述符。

GATT銀行(GATTServer)的業務部門(API)主要提供兩個主要的功能:一是服務功能,註冊或銷燬服務(serviceattribute),並作爲回調函數(callbackfunction);二是管理功能,添加或刪除GATT銀行業務。

一個角色定義的劇本可以同時定義多個角色,每個角色的服務、關鍵詞、關鍵值、描述符(service,characteristic, characteristic value and descriptors)都以句柄(attributes)形式保存在角色提供的服務上。所有的服務都是一個gattAttribute_t類型的array,在文件gatt.h.中定義。

 

4、調用GAP和GATT的一般過程

·        API調用

·        協議棧響應並返回

·        協議棧發送一個OSAL消息(數據)去調用相應任務事件

·        調用任務去接收和處理消息

·        消息清除

以設備初始化爲GAP外設角色來舉例說明,外設角色由其劇本(GAPperipheral role profile)來決定,實例程序在文件peripheral.c內。

·        調用API函數GAP_DeviceInit。

·        GAP檢查了一下說,好,可以初始化,返回值爲SUCCESS (0x00),並通知BLE幹活。

·        BLE協議棧發送OSAL消息給外設角色劇本(peripheral roleprofile),消息內容包括要幹什麼(eventvalue)GAP_MSG_EVENT和指標是什麼(opcodevalue,參數)。

·        角色劇本的服務任務就收到了事件請求SYS_EVENT_MSG,表示有消息來了。

·        角色劇本接收消息,並拆看到底是什麼事,接着把消息數據轉換(cast)成具體要幹事情,並完成相應的工作(這裏爲gapDeviceInitDoneEvent_t)。

·        角色劇本清除消息並返回。

再舉一個例子:GATT客戶端設備想從GATT服務器端讀取數據,即GATT出納想從GATT銀行那邊取點錢出來

·        應用程序調用GATT子進程API函數GATT_ReadCharValue,傳遞的參數爲連接句柄、關鍵詞句柄和自身任務的ID。

·        GATT答應了這個請求,返回值爲SUCCESS (0x00),向下告知BLE有活幹了。

·        BLE協議棧在下次建立藍牙連接時,發送取錢的指令給銀行,當銀行說好,我們正好有櫃員沒事在幹剪指甲,於是把錢取出來交給了BLE。

·        BLE接着就把取到的錢包成消息(OSAL message),通過出納GATT返回給了應用程序。消息內包含GATT_MSG_EVENT和修改了的ATT_READ_RSP。

·        應用程序接收到了從OSAL來的SYS_EVENT_MSG事件,表示錢可能到了

·        應用程序接收消息,拆包檢查,並把需要的錢拿走。

·        最後,應用程序把包裝袋銷燬,沒事了,返回。

 

5、GAP角色劇本profiles

在TI的BLE實例應用中提供了3中GAP角色劇本,保衛處角色,和幾種GATT出納/庫管示例程序服務角色。

5.1 GAP外設劇本

其API函數在peripheral.h中定義,包括:

·        GAPROLE_ADVERT_ENABLED—廣播使能。

·        GAPROLE_ADVERT_DATA—包含在廣播裏的信息。

·        GAPROLE_SCAN_RSP_DATA—外設用於回覆主機掃描請求的信息。

·        GAPROLE_ADVERT_OFF_TIME—表示外設關閉廣播持續時間,該值爲零表示無限期關閉廣播直到下一次廣播使能信號到來。

·        GAPROLE_PARAM_UPDATE_ENABLE—使能自動更新連接參數,可以讓外設連接失敗時自動調整連接參數以便重新連接。

·        GAPROLE_MIN_CONN_INTERVAL—設置最小連接間隙,缺省值爲80個單位(每單位1.25ms)。

·        GAPROLE_MIN_CONN_INTERVAL—設置最大連接間隙,缺省值爲3200個單位。

·        GAPROLE_SLAVE_LATENCY—外設鄙視參數,缺省爲零。

·        GAPROLE_TIMEOUT_MULTIPLIER--最大耐心等待時間,缺省爲1000個單位。

GAPRole_StartDevice函數用來初始化GAP外設角色,其唯一的參數是gapRolesCBs_t,這個參數是一個包含兩個函數指針的結構體,這兩函數是pfnStateChange和pfnRssiRead,前者標示狀態,後者標示RSSI已經被讀走了。

5.2 多角色同時扮演

前文5.1中設備配置爲外設,這裏以設備同時爲外設和廣播員兩種角色。方法爲:去除前文外設的定義劇本peripheral.c和peripheral.h,添加新的劇本peripheralBroadcaster.c和peripheralBroadcaster.h;定義處理器值(preprocessorvalue)PLUS_BROADCASTER。

5.3 GAP主機劇本

與外設劇本相似,主機劇本的API函數在central.h中定義,包括GAPCentralRole_GetParameter和GAPCentralRole_SetParameter以及其他。如GAPROLE_PARAM_UPDATE_ENABLE連接參數自動更新使能的功能,跟外設角色的一樣。

GAPCentralRole_StartDevice函數用來初始化GAP主機角色,其唯一的參數是gapCentralRolesCBs_t,,這個參數是一個包含兩個函數指針的結構體,這兩函數是eventCB和rssiCB,每次GAP時間發生,前者都會被調用,後者標示RSSI已經被讀走。

5.4 GAP綁定管理器劇本

用於保持長期的連接。同時支持外設配置和主機配置。當建立了配對連接後,如果綁定使能,綁定管理器就維護這個連接。主要參數有:GAPBOND_PAIRING_MODE,GAPBOND_MITM_PROTECTION,GAPBOND_IO_CAPABILITIES,GAPBOND_IO_CAP_DISPLAY_ONLY,GAPBOND_BONDING_ENABLED

GAPBondMgr_Register函數用來初始化GAP主機角色,其唯一的參數是gapBondCBs_t,,這個參數是一個包含兩個函數指針的結構體,這兩函數是pairStateCB和passcodeCB,前者返回狀態,後者用於配對時產生6爲數字口令(passcode)。

5.5怎樣編寫一個劇本來創建(定義)新的角色(功能、服務)

以SimpleGATT Profile爲劇本名稱,包含兩個文件simpleGATTProfile.c和simpleGATTProfile.h。包含如下主要API函數:

·        SimpleProfile_AddService—用於初始化的進程,作用是添加服務句柄(serviceattributes)到句柄組(attributetable)內,寄存器讀取和回寫。

·        SimpleProfile_SetParameter—設置劇本(profile)關鍵詞(characteristics)

·        SimpleProfile_GetParameter—獲取獲取設置劇本關鍵詞

·        SimpleProfile_RegisterAppCBs

·        simpleProfile_ReadAttrCB

·        simpleProfile_WriteAttrCB

·        simpleProfile_HandleConnStatusCB

這個實例劇本共有5個關鍵詞:

·        SIMPLEPROFILE_CHAR1

·        …

·        SIMPLEPROFILE_CHAR5

發佈了12 篇原創文章 · 獲贊 7 · 訪問量 9萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章