天天看點

cc2640學習筆記

檔案目錄結構

cc2650iot

1.x        基本入門例程

2.x        外設教程

3.x        RTOS系統例程

4.x        協處理器例程

5.x        進階例程

common        通用檔案

target        不同的晶片封裝和不同開發闆之間存在差異的檔案

說明:RGZ表示7*7封裝;RSM表示4*4封裝

    字尾為RGZ或RSM的檔案夾        裡面包含了闆級差異檔案,代表一種闆子,開發中需為自己的闆子添加改檔案夾

        board.h        檔案中定義了工程中會用到的IO等資源資訊以及外設操作接口函數等

        xxx_cc26xx_RGZ.h        上面的board.h檔案會包含該頭檔案,該檔案是更加底層的闆級和晶片級的資源的聲明和定義。

        xxx_cc26xx_RGZ.c        各種外設資源的結構體定義

    board.c        根據宏定義進行不同封裝和開發闆的頭檔案的包含,用于決定使用該目錄下的哪個闆級方案。

1.1_simple_peripheral

iar

    app        包含app工程相關的檔案

        FlashROM

            Exe        包含hex檔案等

            List        map檔案

            Obj            .o等檔案

    config

    settings

    stack        包含stack工程相關的檔案

        FlashROM        各種編譯連結後得到的檔案

            Exe        包含hex檔案等

            List        map檔案

            Obj            .o等檔案

        settings

    xxx.eww        IAR IDE Workspace

source

    app

        main.c

        simple_peripheral.c

        simple_peripheral.h

    driver

    profile

        simple_gatt_profile.c

        simple_gatt_profile.h

    stack

        osal_icall_ble.c

通用屬性配置檔案(GATT)

正如GAP層負責連接配接相關的功能,GATT主要是負責在兩個已經連接配接的裝置互動資料。

GAP層把BLE裝置區分為主機Master(Central)和從機Slave(Perpherial)。

GATT層則區分為Server和Client。資料以特征值的形式傳輸和存儲。用戶端讀取和寫入存儲在服務端的特征值(Characteristics )。

Server:該裝置包含由GATT用戶端讀取或寫入的characteristic。

Client:從GATT伺服器讀取或寫入資料的藍牙裝置。

注意:對于GATT分層的Server/Client角色和GAP分層的Master(Central)/Slave(Perpherial)并沒有直接關系。

GATT服務{Profile{Service{Characteristic{Attributes

以下我們着重了解Characteristic,也是我們資料互動的最終實體,每個特征包含以下4個Attributes

    1.Characteristic Value(特征值)

        特征的資料值

    2.Characteristic Declaration(特征聲明)

        存儲特征值的屬性,位置和類型的描述符

    3.Client Characteristic Configuration(用戶端特征配置)

        GATT伺服器特征是notify屬性還是indicate屬性。

    4.Characteristic User Description(特征使用者描述)

        描述特征的ASCII字元串

這些屬性存儲在屬性表中的GATT伺服器中。除了該值之外,以下特性與每個屬性相關聯        

以上的每個Attributes又由以下元素組成

    1.Handle(句柄)

        表中屬性的索引(每個屬性都有一個唯一的句柄)

    2.Type(類型)

        訓示屬性資料表示什麼(稱為 UUID,有些是藍牙組織規定的,有些則是自定義)

    3.Permissions(權限)

        強制GATT用戶端裝置如何通路屬性的值

像GAP層一樣,GATT層也是抽象的,這種抽象取決于裝置是作為GATT用戶端還是GATT伺服器。根據藍牙規範的定義,GATT層是ATT層的抽象GATT用戶端沒有屬性表或Profile檔案,因為它們是收集方,而不是提供方。GATT層的功能在庫中實作,但頭檔案功能可在gatt.h檔案中找到。

GATT用戶端抽象層

1.在GATT用戶端應用程式大部分是直接使用GATT的API(少部分直接使用ATT層API),沒有profile檔案,因為GATT客戶是得到資料,不需要建立屬性表和配置檔案。

            Application->GATT->ATT

                    |-----------^

2.在應用程式中直接使用GATT層

    1.初始化GATT用戶端

        VOID GATT_InitClient();

    2.注冊接收傳入的ATT訓示和通知

        GATT_RegisterForInd(selfEntity);

    3.執行GATT用戶端過程

        1.應用程式調用GATT功能函數。

            status = GATT_WriteCharValue(connHandle, &req, selfEntity);

        2.GATT功能函數調用ATT功能函數并且發送到協定棧任務。

        3.BLE Stack接收ICall指令,通過無線方式發送到伺服器,後将狀态傳回給應用程式。(此部分在庫中實作)

    4.接收并處理應用程式中GATT用戶端過程的響應

        1.BLE Stack通過無線方式接收GATT伺服器的寫響應,并向應用程式任務發送GATT消息。(此部分在庫中實作)

        2.應用程式任務接收來自BLE Stack的GATT消息

            if (ICall_fetchServiceMsg(&src, &dest,(void **)&pMsg) == ICALL_ERRNO_SUCCESS)

             {

                if ((src == ICALL_SERVICE_CLASS_BLE) && (dest == selfEntity))

                {

                  // Process inter-task message

                  SimpleBLECentral_processStackMsg((ICall_Hdr *)pMsg);

                }

                if (pMsg)

                {

                  ICall_freeMsg(pMsg);

                }

             }

        3.應用程式處理堆棧消息以處理寫響應

    5.GATT用戶端也可以直接從GATT伺服器接收異步訓示或通知資料。要接收GATT服務端的通知或訓示,如步驟2.這些通知和訓示也将作為ATT事件在GATT消息中發送給應用程式。

GATT服務端抽象層

1.在GATT服務端,GATT層的大部分功能由獨立的profiles處理,這些profiles又使用GattservApp子產品。

            Application->Profiles->GattServApp->GATT->ATT

                |            |--------------------^     ^

                |---------------------------------^       |

                |--------------------------------------|

2.在建立GATT服務端的時候首先需要建立profiles檔案,配置GATTServApp子產品。profiles檔案調用GattServApp子產品并使用其API與GATT層互動。在這種情況下應用程式不需要直接調用GATT層API,應用程式直接和Profiles檔案通信。

3.GattServApp子產品

    1.GattServApp存儲和管理應用程式範圍的屬性表。各種Profile檔案使用此子產品将其特性添加到屬性表中。低功耗藍牙協定棧使用此子產品來響應GATT用戶端的請求。例如GATT用戶端可以發送“發現所有主要特征”消息。GATT伺服器上的低功耗藍牙協定棧收到此消息,并使用GATTServApp查找并發送存儲在屬性表中的所有主要特性。從Profile檔案通路的GATTServApp功能在gattservapp_util.c中定義。

    2.建立屬性表

        1.應用程式使用GattServApp來建立GATT表來添加服務。每個服務都包含具有UUID,值、權限以及讀取和寫入回調的屬性清單。

        2.屬性表初始化必須在應用程式初始化函數中調用,也就是simple_peripheral_init()。

            // Initialize GATT attributes

            GGS_AddService(GATT_ALL_SERVICES); // GAP

            GATTServApp_AddService(GATT_ALL_SERVICES); // GATT attributes

            DevInfo_AddService(); // Device Information Service

            #ifndef FEATURE_OAD_ONCHIP

            SimpleProfile_AddService(GATT_ALL_SERVICES); // Simple GATT Profile

            #endif //!FEATURE_OAD_ONCHIP

    3.Profile架構

在simple_peripheral示例應用程式項目中定義了四個GATT服務

1.GAP GATT服務(GGS)

    此服務包含裝置和通路資訊,例如裝置名稱,供應商辨別和産品辨別。該服務是實作主機和從機所必需的,它的目的是在裝置發現和連接配接啟動過程中進行輔助。

    為此服務定義了以下特征:

        裝置名稱

        表現

        外圍首選連接配接參數

    使用GGS

        GGS以lib庫的形式在協定棧中提供。

        API接口可以在gapgattserver.h中檢視。

        初始化GGS參數

            // GAP GATT Attributes

            static uint8_t attDeviceName[GAP_DEVICE_NAME_LEN] = "Simple BLE Peripheral";

            GGS_SetParameter(GGS_DEVICE_NAME_ATT, GAP_DEVICE_NAME_LEN, attDeviceName);

        使用GGS初始化應用程式回調(可選)。當GGS中任何特征發生變化時,都會通知應用程式。

            GGS_RegisterAppCBs (&appGGSCBs);

        将GGS添加到GATT伺服器

            GGS_AddService(GATT_ALL_SERVICES);           // GAP

2.通用屬性服務

    GATTServApp_AddService(GATT_ALL_SERVICES);   // GATT attributes

    該服務包含有關GATT伺服器的資訊,是藍牙低功耗協定棧的一部分,每個GATT伺服器裝置都需要根據藍牙版本核心規範。

3.裝置資訊服務

    DevInfo_AddService();                        // Device Information Service

    此服務公開了有關裝置的資訊,入硬體,軟體版本,固件版本,規範資訊,合規性資訊和制造商名稱。裝置資訊服務是藍牙低功耗協定棧的一部分,由應用程式配置。

4.simple_gatt_profile服務

    SimpleProfile_AddService(GATT_ALL_SERVICES); // Simple GATT Profile

    此服務是用于測試和示範的執行個體配置檔案,完整的源代碼在simple_gatt_profile.c和simple_gatt_profile.h檔案中提供。

    預設的simple_gatt_profile包含以下特性:

        SIMPLEPROFILE_CHAR1:可以從GATT用戶端裝置讀取或寫入的1位元組值。

        SIMPLEPROFILE_CHAR2:可以從GATT用戶端裝置讀取但不能寫入的1位元組值。

        SIMPLEPROFILE_CHAR3:可以從GATT用戶端裝置寫入但不能讀取的1位元組值。

        SIMPLEPROFILE_CHAR4:不能從GATT用戶端裝置直接讀取或寫入的1位元組值(該值是通知屬性,該值是必須的)。

        SIMPLEPROFILE_CHAR5:可從GATT用戶端裝置讀取(但不寫入)的5位元組值。

屬性表可以看成一列火車,裡面有17個屬性可以看成17個車廂,每個車廂中都有一個屬性權限,将這個屬性權限看做一把鑰匙,這個鑰匙的權限值代表這個車廂可以打開任何一個車廂(即該屬性具有屬性表中所有屬性的讀/寫權限)。而屬性表檔案上部的simpleProfileChar1Props隻代表這把鑰匙對于char1的操作權限。作用對象不同。

GATT安全

    GATT伺服器可以針對每個特征獨立地定義權限。伺服器可能允許任何用戶端通路某些特性,同時将通路其他特性僅限于認證或授權的用戶端。這些權限通常被定義為更進階别的配置檔案規範的一部分。對于自定義配置檔案,使用者可以選擇他們認為合适的權限。

    1.認證

        在用戶端通過認證配對方法之前,無法通路需要身份驗證的特性。此驗證在協定棧内執行,無需應用程式處理。唯一的要求是使GATT伺服器正确注冊該特性。例如,simple_gatt_profile的特征5允許經過認證的讀取。當未經身份驗證的用戶端嘗試讀取此值時,GATT 伺服器使用ERROR_INSUFFICIENT_AUTHEN(0x41)自動拒絕其請求,而不會調用simpleProfile_ReadAttrCB()。用戶端成功認證後,讀/寫請求将轉發到配置檔案讀/寫回調。

    2.授權

        授權是BLE已經實作的一個安全層。由于應用程式需要定義自己的授權要求,是以協定棧将這些特性的讀/寫請求轉發到配置檔案的應用程式層。要從配置檔案注冊GATT伺服器的授權資訊,它必須使用協定棧定義一個授權回調。simple_gatt_profile預設情況下不執行此操作,但下面是如何修改此操作的示例。

            1.注冊授權回調

                在simpleProfileCBs中加入回調函數名simpleProfile_authorizationCB

            2.調用回調函數

                static bStatus_t simpleProfile_authorizationCB( uint16 connHandle,gattAttribute_t *pAttr,uint8 opcode )

                {

                    //This is just an example implementation, normal use cases would require

                    //more complex logic to determine that the device is authorized

                    if(clientIsAuthorized)

                        return SUCCESS;

                    else

                        return ATT_ERR_INSUFFICIENT_AUTHOR;

                }

                授權回調在協定棧上下文中執行;是以,不應在此功能中執行複雜的處理。具體實施由開發人員決定;上述回調應該被視為一個shell。如果用戶端被授權通路該特性,傳回值應為“SUCCESS”,否則傳回值應為“ATT_ERR_INSUFFICIENT_AUTHOR”,如果尚未獲得正确的授權。授權要求事先通過連接配接進行身份驗證,否則将作為錯誤響應發送ATT_ERR_INSUFFICIENT_AUTHEN。

SDK結構

simple_central.c

    SimpleBLECentral_startGapDiscovery    開始發現裝置

    SimpleBLECentral_createTask    簡單BLE外圍裝置的任務建立函數

    SimpleBLECentral_init    初始化函數為簡單的BLE中央應用任務

    SimpleBLECentral_taskFxn    簡單的BLE Central的應用程式任務入口點

    SimpleBLECentral_processStackMsg    處理協定棧消息

    SimpleBLECentral_processAppMsg    處理APP消息

    SimpleBLECentral_processRoleEvent    主機角色事件處理函數

    SimpleBLECentral_handleKeys    處理此裝置的所有按鍵事件

    SimpleBLECentral_processGATTMsg    處理GATT消息和事件

    SimpleBLECentral_processCmdCompleteEvt    處理一個傳入的OSAL HCI指令完成事件

    SimpleBLECentral_startDiscovery    開始服務發現

    SimpleBLECentral_findSvcUuid    在廣告客戶的服務UUID清單中查找給定的UUID

    SimpleBLECentral_addDeviceInfo    将裝置添加到裝置發現結果清單中

調用關系

    SimpleBLECentral_taskFxn

        SimpleBLECentral_init

        SimpleBLECentral_processStackMsg

            GAP_MSG_EVENT:SimpleBLECentral_processRoleEvent

                GAP_DEVICE_INIT_DONE_EVENT:初始化時可以用于列印以及掃描(如果對應的宏定義滿足)

                GAP_DEVICE_INFO_EVENT:    SimpleBLECentral_findSvcUuid

                                        SimpleBLECentral_addDeviceInfo

                GAP_DEVICE_DISCOVERY_EVENT:裝置發現過程完成時可用于選擇裝置并建立連接配接

                GAP_LINK_ESTABLISHED_EVENT:建立連結請求完成時可用于列印

                GAP_LINK_TERMINATED_EVENT:連接配接終止時可用于列印

                GAP_LINK_PARAM_UPDATE_EVENT:接收到更新參數事件時可用于列印

            GATT_MSG_EVENT:SimpleBLECentral_processGATTMsg

            HCI_GAP_EVENT_EVENT:SimpleBLECentral_processCmdCompleteEvt

        SimpleBLECentral_processAppMsg    //此處主要處理消息隊列中的消息

            可以根據不同的事件進行不同的處理例如,案件觸發掃描,收發資料等

        SimpleBLECentral_startDiscovery

simple_peripheral.c

    SimpleBLEPeripheral_createTask    簡單BLE外圍裝置的任務建立函數

    SimpleBLEPeripheral_init

    SimpleBLEPeripheral_taskFxn    簡單BLE外圍裝置的應用程式任務入口點

    SimpleBLEPeripheral_processStackMsg    處理協定棧消息

    SimpleBLEPeripheral_processGATTMsg    處理GATT消息和事件

    SimpleBLEPeripheral_sendAttRsp    發送等待的ATT響應消息

    SimpleBLEPeripheral_freeAttRsp    自由ATT響應消息

    SimpleBLEPeripheral_processAppMsg    處理APP消息

    SimpleBLEPeripheral_stateChangeCB

    SimpleBLEPeripheral_processStateChangeEvt    藍牙狀态回調函數

    SimpleBLEPeripheral_charValueChangeCB    特征值改變回調函數

    SimpleBLEPeripheral_processCharValueChangeEvt    處理挂起的特征值改變事件

    SimpleBLEPeripheral_performPeriodicTask 處理自定義的定時EVENT事件

    SimpleBLEPeripheral_processOadWriteCB    處理對OAD配置檔案的寫請求

    SimpleBLEPeripheral_clockHandler    時鐘逾時的處理函數

    SimpleBLEPeripheral_enqueueMsg    建立一條消息并将該消息放入RTOS隊列中

調用關系

    SimpleBLEPeripheral_taskFxn

        SimpleBLEPeripheral_init

        SimpleBLEPeripheral_sendAttRsp

        SimpleBLEPeripheral_processStackMsg

            GATT_MSG_EVENT:SimpleBLEPeripheral_processGATTMsg

        SimpleBLEPeripheral_processAppMsg

            SBP_STATE_CHANGE_EVT:SimpleBLEPeripheral_processStateChangeEvt

            SBP_CHAR_CHANGE_EVT:SimpleBLEPeripheral_processCharValueChangeEvt//接收并處理對應通道的消息

            SBC_KEY_CHANGE_EVT:SimpleBLEPeripheral_handleKeys

        SimpleBLEPeripheral_performPeriodicTask

發送接收資料

主機發送:

    GATT_WriteCharValue

主機接收:

    1.第一步,注冊接收notify消息GATT_RegisterForInd(selfEntity);

    第二部,在GATT_MSG_EVENT消息處理函數SimpleBLECentral_processGATTMsg增加ATT_HANDLE_VALUE_NOTI 處理代碼:

        else if (pMsg->method == ATT_HANDLE_VALUE_NOTI)

        {

        //資料内容為:pMsg->msg.handleValueNoti.pValue

        //資料長度為:pMsg->msg.handleValueNoti.len

        UartWrite(pMsg->msg.handleValueNoti.pValue,

        pMsg->msg.handleValueNoti.len);

        }

    2.從機還可以使用函數SimpleProfile_SetParameter()修改特征值的值,然後主機中調用GATT_ReadCharValue()函數來讀取該特征值

從機發送:

    1.GATT_Notification不需要主機回應

    2.GATT_Indication需要主機回應

從機接收:

    第一步:注冊Profile回調函數,用來接收特征值事件。SimpleProfile_RegisterAppCBs(&SimpleBLEPeripheral_simpleProfileCBs);

    第二部:在回調函數SimpleBLEPeripheral_processCharValueChangeEvt中調用SimpleProfile_GetParameter讀取資料

藍牙profile

    藍牙profile可以了解為主從雙方通信過程中的格式化資料,并存儲在藍牙從機中,作為服務端,而主機作為用戶端,用戶端可以擷取服務端的資料或屬性,這個資料就稱之為特征值。

GATT(Generic Attribute profile)                    

    GATT服務是profile的一種集合,負責兩個裝置之間的資料通信,資料以特征值的形式傳輸和存儲。從GATT的角度看,主機和從機兩個裝置連接配接後,分别變成了兩種角色:GATT用戶端和GATT伺服器。

GAP(Generic Access Profile)通用通路配置檔案

    BLE協定棧的GAP層負責連接配接功能。該層處理裝置的Access模式和過程,包括裝置發現,鍊路建立,鍊路終止,安全特性的啟動和裝置配置。

ICall是一種軟體子產品,可為應用程式與協定棧提供通信服務,app中調用的協定棧API函數,大多來自ICall子產品,另外ICall還提供RTOS的一些線程同步、動态記憶體等服務。ICall使得app和stack在統一的RTOS環境中高效運作,共享資源。使用ICall之前必須:1、ICall_init();2、ICall_createRemoteTasks();3、ICall_registerApp(&selfEntity, &sem);

廣播的相關參數

Advertising_Type  (廣播類型)

廣播的類型一般分為4種,分别是:

    1.可連接配接的非定向廣播。

        這是一種用途最廣的廣播類型,包括廣播資料和掃描響應資料,它表示目前裝置可以接受其他任何裝置的連接配接請求。

    2.可連接配接的定向廣播。

        定向廣播類型是為了盡可能快的建立連接配接。這種封包包含兩個位址:廣播者的位址和發起者的位址。發起者收到發給自己的定向廣播封包之後,可以立即發送連接配接請求作為回應。

        定向廣播類型有特殊的時序要求。完整的廣播事件必須每3.75ms重複一次。這一要求使得掃描裝置隻需掃描3.75ms便可以收到定向廣播裝置的消息。當然,如此快的發送會讓封包充斥着廣播信道,進而導緻該區域内的其他裝置無法進行廣播。是以,定向廣播不可以持續1.28s以上的時間。如果主機沒有主動要求停止,或者連接配接沒有建立,控制器都會自動停止廣播。一旦到了1.28s,主機便隻能使用間隔長得多的可連接配接非定向廣播讓其他裝置來連接配接。

        當使用定向廣播時,裝置不能被主動掃描。此外,定向廣播封包的淨荷中也不能帶有其他附加資料。該淨荷隻能包含兩個必須的位址。

    3.不可連接配接的非定向廣播。

        僅僅發送廣播資料。

    4.可掃描的非定向廣播。

        這種廣播不能用于發起連接配接,但允許其他裝置掃描該廣播裝置。這意味着裝置可以被發現,既可以發送廣播資料,也可以響應掃描發送掃描回應資料,但不能建立連接配接。這是一種适用于廣播資料的廣播形式,動态資料可以包含于廣播資料之中,而靜态資料可以包含于掃描相應資料之中。

    注意:所謂的定向和非定向針對的是廣播的對象,如果是針對特定的對象進行廣播(在廣播包PDU中會包含目标對象的MAC)就是定向廣播,反之就是非定向。可連接配接和不可連接配接是指是否接受連接配接請求,如果是不可連接配接的廣播類型,它将不回應連接配接請求。可掃描廣播類型是指回應掃描請求。

設定廣播類型的方法

    cc2640預設應該是可連接配接非定向類型

    修改方法:GAPRole_SetParameter(GAPROLE_ADV_EVENT_TYPE, sizeof( uint8 ), &advType );

Advertising interval  (廣播間隔)

裝置每次廣播時,會在3個廣播信道上發送相同的封包。這些封包被稱為一個廣播事件。除了定向封包以外,其他廣播事件均可以選擇“20ms~10.28s”不等的間隔。通常,一個廣播中的裝置會每一秒廣播一次。兩個相鄰廣播事件之間的事件稱為廣播間隔。

    但是,裝置周期性的發送廣播會有一個問題:由于裝置間的時鐘會不同程度的漂移,兩個裝置可能在很長一段時間同時廣播而造成幹擾。為防止這一情況的發生,除定向廣播之外的其他廣播類型,發送時間均會被擾動。實作該擾動的方式為,在上一次廣播事件後加入“0 ~ 10ms”的随機延時。這意味着,即使兩個裝置廣播間隔相同,并在相同信道及時間點上發送造成了沖突,但它們發送下一個廣播事件時也會有很大可能不再沖突。是以,兩個相鄰的廣播事件的之間的時間間隔(T_advEvent)為:T_AdvEvent = advInterval + advDelay。

    其中,advInterval必須是“0.625ms”的整數倍,範圍是“20ms~10.24s”之間。其中,advInterval必須是“0.625ms”的整數倍,範圍是“20ms ~ 10.24s”之間。

    當然,實際設定過程中沒有廣播間隔參數,而是設定Advertising_Interval_Min(最小廣播間隔)和Advertising_Interval_Max(最大廣播間隔)這兩個參數來調整廣播間隔,它們都是以“0.625ms”為機關,如果要固定廣播間隔為某一個值,隻需要将這兩個參數設定為同一個有效數值即可。

設定廣播間隔的方法

    //普通可發現模式(在未連接配接情況下一直廣播下去)下修改廣播間隔的方法

    GAP_SetParamValue(TGAP_GEN_DISC_ADV_INT_MIN, advInt );//機關是0.625ms

    GAP_SetParamValue(TGAP_GEN_DISC_ADV_INT_MAX, advInt );//機關是0.625ms

    //有限可發現模式(廣播一定時間後停止廣播)下修改廣播間隔的方法

    GAP_SetParamValue( TGAP_LIM_DISC_ADV_INT_MIN, advInt );//機關是0.625ms

    GAP_SetParamValue( TGAP_LIM_DISC_ADV_INT_MAX, advInt );//機關是0.625ms

Own_Address_Type  (自身位址類型)

Direct_Address_Type  (定向位址類型)

Direct_Address  (定向位址)

Advertising_Channel_Map  (廣播信道)

Advertising_Filter_Policy  (廣播過濾政策)

Advertising And ScanReponse Data  (廣播和掃描回應資料)

過程跟蹤

無配對綁定過程

從機

1.BLE Peripheral

        SimpleBLEPeripheral_init

2.0xCC78AB7A7290 Initialized

    SimpleBLEPeripheral_processAppMsg

        case SBP_STATE_CHANGE_EVT:SimpleBLEPeripheral_processStateChangeEvt

            case GAPROLE_STARTED

3.Advertising

    SimpleBLEPeripheral_processAppMsg

        case SBP_STATE_CHANGE_EVT:SimpleBLEPeripheral_processStateChangeEvt

            case GAPROLE_ADVERTISING

4.Num Conns: 1

4.connected 0xCC78AB7A72FE

    SimpleBLEPeripheral_processAppMsg

        case SBP_STATE_CHANGE_EVT:SimpleBLEPeripheral_processStateChangeEvt

            case GAPROLE_CONNECTED

主機

1.BLE Central

    SimpleBLECentral_init

2.0xCC78AB7A72FE Initialized

    SimpleBLECentral_processStackMsg

        case GAP_MSG_EVENT:SimpleBLECentral_processRoleEvent

            case GAP_DEVICE_INIT_DONE_EVENT

3.Connected: 0xCC78AB7A7290

    SimpleBLECentral_processStackMsg

        case GAP_MSG_EVENT:SimpleBLECentral_processRoleEvent

            case GAP_LINK_ESTABLISHED_EVENT

4.MTU Size: 23

5.Simple Svc Found, charHdl: 46

    SimpleBLECentral_processStackMsg

        case GATT_MSG_EVENT:SimpleBLECentral_processGATTMsg

            BLE_DISC_STATE_IDLE:SimpleBLECentral_processGATTDiscEvent

                BLE_DISC_STATE_CHAR:SimpleBLECentral_processGATTDiscEvent

Param Update: 0

    SimpleBLECentral_processStackMsg

        case GAP_MSG_EVENT:SimpleBLECentral_processRoleEvent

            case GAP_LINK_PARAM_UPDATE_EVENT

配對綁定

GAP Bond Manager(GAP綁定管理器)

GAPBondMgr使用的一般過程如下

1.配對過程,即交換秘鑰

2.使用步驟1的秘鑰加密連接配接

3.綁定過程将秘鑰存儲在安全閃存(SNV)中

4.重新連接配接時,使用存儲在SNV中的秘鑰來加密連接配接

使用GAPBondMgr

GAPRole處理一些GAPBondMgr功能。GAPBondMgr在gapbondmgr.c和gapbondmgr.h中定義。

1.配置協定棧以支援GAPBondMgr功能,以及是否需要安全連接配接。在stack項目中的build_config.opt中定義以下内容:    

    DGAP_BOND_MGR

    DBLE_V42_FEATURES=SECURE_CONNS_CFG

2.協定棧還必須配置為使用1或2個SNV頁面,通過在stack項目中将OSAL_SNV=1或OSAL_SNV = 2。

3.如果使用安全連接配接,PDU大小必須>=69.這可以通過在應用程式項目中定義以下預處理器符号來設定:MAX_PDU_SIZE = 69。此外,可用于安全連接配接的最小堆空間大小為 3690。

4.通過根據需要初始化其參數來配置GAPBondMgr。

5.使用GAPBondMgr注冊應用程式回調,以便應用程式可以與GAPBondMgr通信并通知事件。

    GAPBondMgr_Register(&security_examples_central_bondCB);

6.一旦GAPBondMgr被配置,它主要從應用程式的角度自主運作。當建立連接配接時,根據初始化期間設定的配置參數啟動配對和綁定,并根據需要通過定義的回調與應用程式進行通信。

配對模式

Pairing Disabled禁用配對

    配對設定為FALSE時,BLE協定棧會自動拒絕任何配對嘗試。如下設定GAPBondMgr以禁用配對:

        uint8 pairMode = GAPBOND_PAIRING_MODE_NO_PAIRING;

        GAPBondMgr_SetParameter(GAPBOND_PAIRING_MODE, sizeof(uint8_t),&pairMode);

Just Works Pairing 隻配對

    Just Works 配對允許加密而不需要MITM(人在中間保護,就是指在配對過程中,有些認為的在中間的操作來進行保護)身份驗證,容易受到MITM攻擊。Just Works配對可以是LE Legacy或Secure Connections配對。GAPBondMgr不需要任何額外的輸入。配置GAPBondMgr為Just Works配對如下。

        uint8_t pairMode = GAPBOND_PAIRING_MODE_INITIATE;

        uint8_t mitm = FALSE;

        GAPBondMgr_SetParameter( GAPBOND_PAIRING_MODE, sizeof (uint8_t),&pairMode);

        GAPBondMgr_SetParameter( GAPBOND_MITM_PROTECTION, sizeof (uint8_t),&mitm);

一旦發送配對請求,應用程式将收到一個GAPBOND_PAIRING_STATE_STARTED事件,一旦配對過程完成,就會發生 GAPBOND_PAIRING_STATE_COMPLETE 事件。此時,連結被加密。

Passcode Entry密碼輸入

密碼輸入是一種可以防止MITM攻擊的身份驗證配對。它可以是LE Legacy配對或安全連接配接配對。在這種配對方法中,一個裝置顯示6位密碼,另一個裝置輸入密碼。GAPBondMgr在啟動時注冊的密碼回調用于輸入或顯示密碼。以下是啟動Passcode Entry配對的示例,其中顯示密碼。

    1.定義密碼回調

    2.配置GAPBondMgr

    3.處理密碼回調并向協定棧發送響應

        根據從GAPBondMgr傳回uiInputs和uiOutputs内容,必須顯示或輸入密碼。然後使用GAPBondMgr_PasscodeRsp()将密碼發送到GAPBondMgr,以便配對可以繼續。密碼很可能是随機生成的,裝置必須為使用者提供輸入密碼的方式,然後使用GAPBondMgr_PasscodeRsp()發送給GAPBondMgr。

Numeric Comparison數字比較

    數組比較是一種經過身份驗證的配對,可以防止MITM攻擊。隻能作為安全連接配接配對,兩個裝置都顯示6位數的代碼。每個裝置必須通過按鈕或其他一些輸入來訓示代碼是否比對。GAPBondMgr在啟動時注冊的密碼回調用于顯示 6 位數代碼。以下是啟動數字比較配對的示例。

    1.定義密碼回調來顯示代碼

    2.配置GAPBondMgr

    3.處理密碼回調和顯示代碼

    4.接受使用者輸入 YES-No,并發送回應 GAPBondMgr

        GAPBondMgr_PasscodeRsp(connHandle, SUCCESS, TRUE);

GAPBondMgr與應用程式之間的完全互動圖如下:(此處隻顯示應用層,詳情請參考cc2640低功耗藍牙入門教程)

>第一次連接配接

1.Pairing State Callback        GATBOND_PAIRING_STATE_STARTED

2.Passcode Callback

    顯示密碼

    發送回應

3.Pairing State Callback        GAPBOND_PAIRING_STATE_COMPLETE

>後續連接配接

從SNV中取出秘鑰

4.Pairing State Callback        GAPBOND_PAIRING_STATE_BONDED

啟用綁定後,GAPBondMgr将配對過程中傳輸的長期密鑰存儲到SNV。完成後,通過GAPBOND_PAIRING_STATE_COMPLETE事件通知應用程式。僅在初始連接配接時,配對和綁定傳遞給應用程式GAPBOND_PAIRING_STATE_COMPLETE回調。為了将來連接配接到綁定裝置,安全密鑰從閃存加載,進而跳過配對過程。在這種情況下,隻有PAIRING_STATE_BONDED被傳遞給應用程式對狀态回調。

GAPBondMgr各參數解析

1.passkey

    在xxx_init函數中該值表示預設密碼,當後續沒有重新修改密碼時該值就是最終密碼。

    在一些情況下我們會在密碼回調中重新設定該值,此時密碼就不是之前的預設密碼了

2.pairMode

該值有3個選項

GAPBOND_PAIRING_MODE_NO_PAIRING

    如果主從機中有一方配置為該模式則當雙發在連接配接後隻要另一發發起配對則連接配接就會斷開

GAPBOND_PAIRING_MODE_WAIT_FOR_REQ

    該模式是一種被動的模式,一般長用于主機上。若另一發不發起配對則直接連接配接成功,另一方若發起連接配接則本裝置進行相應配合。

GAPBOND_PAIRING_MODE_INITIATE

    如果要使能配對,主從機中至少要有一個配置為該模式。

    一般情況下我們傾向于将從機配置為該模式,因為一般主機都是發起連接配接的一方需要考慮連接配接不同裝置時的通用性,故将配對綁定等安全事務留給裝置來決定是否需要做,如果不需要則直接連接配接完成,如果需要則主機隻需要進行相應的配合即可。并且一般從機都是一些io很少的裝置不一定支援密碼的比較。

3.mitm

人在中間保護。

當該值被配置為FALSE時,說明不需要人在中間參與,後面的ioCap設定就會被忽略。

4.ioCap

該值表示本機是否具有顯示或者輸入的功能,比如GAPBOND_IO_CAP_DISPLAY_ONLY,表示可以将密碼顯示在螢幕上給操作人看,如果有I/O接口可以輸入密碼,也可以選擇GAPBOND_IO_CAP_KEYBOARD_ONLY。

5.bonding

該值的取值為TRUE或FALSE。表示是否需要綁定過程,需要注意隻有使能配對之後才可能有綁定,故若首次與别的裝置連接配接沒有配對過程則,該值就算為TRUE也不會執行綁定。