This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

cc2640r2的蓝牙界面怎么修改Rawdata数据?



cc2640r2的蓝牙界面怎么修改Rawdata数据?用哪个文件(.c或.h)?

  • 在simple_peripheral.c中修改

    // Advertisement data
    static uint8_t advertData[] =
    {
      0x02,   // length of this data
      GAP_ADTYPE_FLAGS,
      DEFAULT_DISCOVERABLE_MODE | GAP_ADTYPE_FLAGS_BREDR_NOT_SUPPORTED,
    
      // service UUID, to notify central devices what services are included
      // in this peripheral
      0x03,   // length of this data
      GAP_ADTYPE_16BIT_MORE,      // some of the UUID's, but not all
      LO_UINT16(SIMPLEPROFILE_SERV_UUID),
      HI_UINT16(SIMPLEPROFILE_SERV_UUID)
    };
    
    // Scan Response Data
    static uint8_t scanRspData[] =
    {
      // complete name
      17,   // length of this data
      GAP_ADTYPE_LOCAL_NAME_COMPLETE,
      'S',
      'i',
      'm',
      'p',
      'l',
      'e',
      'P',
      'e',
      'r',
      'i',
      'p',
      'h',
      'e',
      'r',
      'a',
      'l',
    
      // connection interval range
      5,   // length of this data
      GAP_ADTYPE_SLAVE_CONN_INTERVAL_RANGE,
      LO_UINT16(DEFAULT_DESIRED_MIN_CONN_INTERVAL),   // 100ms
      HI_UINT16(DEFAULT_DESIRED_MIN_CONN_INTERVAL),
      LO_UINT16(DEFAULT_DESIRED_MAX_CONN_INTERVAL),   // 1s
      HI_UINT16(DEFAULT_DESIRED_MAX_CONN_INTERVAL),
    
      // Tx power level
      2,   // length of this data
      GAP_ADTYPE_POWER_LEVEL,
      0       // 0dBm
    };
    

  • 好的,谢谢,我试验了下是可以的。另外我想问下另一个问题,我使用simple_peripheral_oad_onchip项目,修改MAC地址,然后手机app进不了OAD界面。但是用普通的蓝牙调试串口(nRF Connect软件)可以进行连接

    SDK:simplelink_cc2640r2_sdk_4_20_00_04

    手机app:SimpleLink Starter,SensorTag

    修改MAC地址代码如下图:

    手机进不了的界面如下图:

  • 我测试后可以正常连接
  • 你好,我重新实验了下,发现MAC地址改为上面显示的{0x42, 0x97, 0x6a, 0xf3, 0x7b, 0x98},就会进不去OAD界面,然后改为{0x42, 0x97, 0x6a, 0xf3, 0x7b, 0x05}就正常,改为{0x00, 0x01, 0x02, 0x03, 0x04, 0x98}也正常,唯独我一开始设置的那个地址就一定会出问题。
  • user6454664 说:
    发现MAC地址改为上面显示的{0x42, 0x97, 0x6a, 0xf3, 0x7b, 0x98},就会进不去OAD界面

    上面显示的地址是什么意思,哪个地址

  • 我测试此地址是正常的,没有出现问题
  • 这就很奇怪了,我再查找下原因,谢谢
  • 你好,我后面试了下这个情况,还是有问题,不知道什么原因会导致进不了OAD界面,有时修改了MAC地址,有时修改了蓝牙名字,都有可能会导致进不了。下面是用simple_peripheral_oad_onchip例子修改的一点信息然后进不去OAD界面的.c文件,路径是C:\ti\simplelink_cc2640r2_sdk_4_30_00_08\examples\rtos\CC2640R2_LAUNCHXL\blestack\simple_peripheral_oad_onchip\src\app  ,麻烦帮我看下为什么会出现这个问题。

    SDA:simplelink_cc2640r2_sdk_4_30_00_08

    手机Android版本:10             

    使用的软件:simplelink starter /sensortag

    /******************************************************************************
    
     @file  simple_peripheral_oad_onchip.c
    
     @brief This file contains the OAD sample application based on
            simple_peripheral for use with the CC2650 Bluetooth Low Energy
            Protocol Stack.
    
     Group: WCS, BTS
     Target Device: cc2640r2
    
     ******************************************************************************
     
     Copyright (c) 2017-2020, Texas Instruments Incorporated
     All rights reserved.
    
     Redistribution and use in source and binary forms, with or without
     modification, are permitted provided that the following conditions
     are met:
    
     *  Redistributions of source code must retain the above copyright
        notice, this list of conditions and the following disclaimer.
    
     *  Redistributions in binary form must reproduce the above copyright
        notice, this list of conditions and the following disclaimer in the
        documentation and/or other materials provided with the distribution.
    
     *  Neither the name of Texas Instruments Incorporated nor the names of
        its contributors may be used to endorse or promote products derived
        from this software without specific prior written permission.
    
     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
     AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
     THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
     OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    
     ******************************************************************************
     
     
     *****************************************************************************/
    
    /*********************************************************************
     * INCLUDES
     */
    #include <string.h>
    
    #include <ti/sysbios/knl/Task.h>
    #include <ti/sysbios/knl/Clock.h>
    #include <ti/sysbios/knl/Event.h>
    #include <ti/sysbios/knl/Queue.h>
    
    #ifdef LED_DEBUG
    #include <ti/drivers/PIN.h>
    #endif //LED_DEBUG
    
    #include <ti/display/Display.h>
    
    #include <icall.h>
    #include "util.h"
    /* This Header file contains all BLE API and icall structure definition */
    #include "icall_ble_api.h"
    
    #include "devinfoservice.h"
    #include "simple_gatt_profile.h"
    #include "ll_common.h"
    
    // Used for imgHdr_t structure
    #include "oad_image_header.h"
    // Used for OAD Reset Service APIs
    #include "oad_reset_service.h"
    
    // Pull in common OAD structs
    #include <profiles/oad/cc26xx/oad.h>
    #include <profiles/oad/cc26xx/oad_util.h>
    
    // Needed for ECC constants
    #include <common/cc26xx/ecc/ECCROMCC26XX.h>
    
    // Needed for HAL_SYSTEM_RESET()
    #include "hal_mcu.h"
    
    #include "peripheral.h"
    
    #ifdef USE_RCOSC
    #include "rcosc_calibration.h"
    #endif //USE_RCOSC
    
    #include "board.h"
    
    #include "simple_peripheral_oad_onchip.h"
    
    #include "ble_user_config.h"
    
    
    /*********************************************************************
     * CONSTANTS
     */
    
    // Advertising interval when device is discoverable (units of 625us, 160=100ms)
    #define DEFAULT_ADVERTISING_INTERVAL          160
    
    // Limited discoverable mode advertises for 30.72s, and then stops
    // General discoverable mode advertises indefinitely
    #define DEFAULT_DISCOVERABLE_MODE             GAP_ADTYPE_FLAGS_GENERAL
    
    // Minimum connection interval (units of 1.25ms, 8=10ms) if automatic
    // parameter update request is enabled
    #define DEFAULT_DESIRED_MIN_CONN_INTERVAL     8
    
    // Maximum connection interval (units of 1.25ms, 8=10ms) if automatic
    // parameter update request is enabled
    #define DEFAULT_DESIRED_MAX_CONN_INTERVAL     8
    
    // Slave latency to use if automatic parameter update request is enabled
    #define DEFAULT_DESIRED_SLAVE_LATENCY         0
    
    // Supervision timeout value (units of 10ms, 1000=10s) if automatic parameter
    // update request is enabled
    #define DEFAULT_DESIRED_CONN_TIMEOUT          1000
    
    // Whether to enable automatic parameter update request when a connection is
    // formed
    #define DEFAULT_ENABLE_UPDATE_REQUEST         GAPROLE_LINK_PARAM_UPDATE_WAIT_REMOTE_PARAMS
    
    // Connection Pause Peripheral time value (in seconds)
    #define DEFAULT_CONN_PAUSE_PERIPHERAL         6
    
    // Define the default pairing behavior
    #define DEFAULT_PAIRING_MODE                  GAPBOND_PAIRING_MODE_WAIT_FOR_REQ
    
    // How often to perform periodic event (in msec)
    #define SBP_PERIODIC_EVT_PERIOD               5000
    
    // Offset into the scanRspData string the software version info is stored
    #define OAD_SOFT_VER_OFFSET                   15
    
    
    // Use UART display
    #define SBP_DISPLAY_TYPE Display_Type_UART
    
    // Task configuration
    #define SBP_TASK_PRIORITY                     1
    
    // Warning! To optimize RAM, task stack size must be a multiple of 8 bytes
    #ifndef SBP_TASK_STACK_SIZE
      #if defined (__IAR_SYSTEMS_ICC__)
        #define SBP_TASK_STACK_SIZE                   1000
      #elif defined __TI_COMPILER_VERSION || defined __TI_COMPILER_VERSION__
        #define SBP_TASK_STACK_SIZE                   800
      #else
        #error "Unknown Compiler"
       #endif
    #endif
    
    // Application events used with app queue (appEvtHdr_t)
    // These are not related to RTOS evts, but instead enqueued via state change CBs
    #define SBP_STATE_CHANGE_EVT                  0x0001
    #define SBP_CHAR_CHANGE_EVT                   0x0002
    #define SBP_OAD_RESET_EVT                     0x0003
    #define SBP_PASSCODE_NEEDED_EVT               0x0004
    // Application specific event ID for Connection Event End Events
    #define SBP_CONN_EVT                          0x0005
    
    // Internal Events for RTOS application
    #define SBP_ICALL_EVT                         ICALL_MSG_EVENT_ID // Event_Id_31
    #define SBP_QUEUE_EVT                         UTIL_QUEUE_EVENT_ID // Event_Id_30
    #define SBP_PERIODIC_EVT                      Event_Id_00
    #define SBP_ALL_EVENTS                        (SBP_ICALL_EVT        | \
                                                   SBP_QUEUE_EVT        | \
                                                   SBP_PERIODIC_EVT)
    
    // Set the register cause to the registration bit-mask
    #define CONNECTION_EVENT_REGISTER_BIT_SET(RegisterCause) (connectionEventRegisterCauseBitMap |= RegisterCause )
    // Remove the register cause from the registration bit-mask
    #define CONNECTION_EVENT_REGISTER_BIT_REMOVE(RegisterCause) (connectionEventRegisterCauseBitMap &= (~RegisterCause) )
    // Gets whether the current App is registered to the receive connection events
    #define CONNECTION_EVENT_IS_REGISTERED (connectionEventRegisterCauseBitMap > 0)
    // Gets whether the RegisterCause was registered to recieve connection event
    #define CONNECTION_EVENT_REGISTRATION_CAUSE(RegisterCause) (connectionEventRegisterCauseBitMap & RegisterCause )
    
    /*********************************************************************
     * TYPEDEFS
     */
    
    // App event passed from profiles.
    typedef struct
    {
      appEvtHdr_t hdr;  // event header.
      uint8_t *pData;   // Event payload
    } sbpEvt_t;
    
    /*********************************************************************
     * GLOBAL VARIABLES
     */
    
    // Display Interface
    Display_Handle dispHandle = NULL;
    
    extern const imgHdr_t _imageHdr;
    
    // BIM variable
    #ifdef __TI_COMPILER_VERSION__
      #pragma location = BIM_VAR_ADDR
      #pragma NOINIT(_bim_var)
      uint32_t _bim_var;
    #elif __IAR_SYSTEMS_ICC__
      __no_init uint32_t _bim_var @ BIM_VAR_ADDR;
    #endif
    
    /*********************************************************************
     * LOCAL VARIABLES
     */
    
    // Entity ID globally used to check for source and/or destination of messages
    static ICall_EntityID selfEntity;
    
    // Event globally used to post local events and pend on system and
    // local events.
    static ICall_SyncHandle syncEvent;
    
    // Clock instances for internal periodic events.
    static Clock_Struct periodicClock;
    
    // Queue object used for app messages
    static Queue_Struct appMsg;
    static Queue_Handle appMsgQueue;
    
    // Task configuration
    Task_Struct sbpTask;
    
    #if defined __TI_COMPILER_VERSION__
    #pragma DATA_ALIGN(sbpTaskStack, 8)
    #elif __IAR_SYSTEMS_ICC__
    #pragma data_alignment=8
    #endif    //__TI_COMPILER_VERSION__
    uint8_t sbpTaskStack[SBP_TASK_STACK_SIZE];
    
    
    // GAP - SCAN RSP data (max size = 31 bytes)
    static uint8_t scanRspData[] =
    {
      // complete name
      0x0a,   // length of this data
      GAP_ADTYPE_LOCAL_NAME_COMPLETE,
      'T',
      'i',
      ' ',
      'l',
      'a',
      'n',
      ' ',
      'y',
      'a',
    //  'g',
    //  'e',
    //  ' ',
    //  'j',
    //  'i', // These 4 octets are placeholders for the SOFTVER field
    //  ' ', // which will be updated at init time
    //  ' ',
    //  ' ',
    
      // connection interval range
    //  0x05,   // length of this data
    //  GAP_ADTYPE_SLAVE_CONN_INTERVAL_RANGE,
    //  LO_UINT16(DEFAULT_DESIRED_MIN_CONN_INTERVAL),   // 10ms
    //  HI_UINT16(DEFAULT_DESIRED_MIN_CONN_INTERVAL),
    //  LO_UINT16(DEFAULT_DESIRED_MAX_CONN_INTERVAL),   // 10ms
    //  HI_UINT16(DEFAULT_DESIRED_MAX_CONN_INTERVAL),
    //
    //  // Tx power level
    //  0x02,   // length of this data
    //  GAP_ADTYPE_POWER_LEVEL,
    //  0       // 0dBm
    };
    
    // GAP - Advertisement data (max size = 31 bytes, though this is
    // best kept short to conserve power while advertising)
    static uint8_t advertData[] =
    {
      // Flags; this sets the device to use limited discoverable
      // mode (advertises for 30 seconds at a time) instead of general
      // discoverable mode (advertises indefinitely)
    //  0x02,   // length of this data
    //  GAP_ADTYPE_FLAGS,
    //  DEFAULT_DISCOVERABLE_MODE | GAP_ADTYPE_FLAGS_BREDR_NOT_SUPPORTED,
      
      0x1A, // length of this data including the data type byte
      GAP_ADTYPE_MANUFACTURER_SPECIFIC, // manufacturer specific adv data type
      0x0D, // Company ID - Fixed
      0x00, // Company ID - Fixed
      0x00, // Data Type - Fixed
      0x00, // Data Length - Fixed
      0x90, // UUID - Variable based on different use cases/applications
      0x00, // UUID
      0x00, // UUID
      0x00, // UUID
      0x00, // UUID
      0x00, // UUID
      0x07, // UUID
      0x00, // UUID
      0x07, // UUID
      0x00, // UUID
      0x07, // UUID
      0x00, // UUID
      0x07, // UUID
      0x00, // UUID
      0x07, // UUID
      0x00, // UUID
      0x07, // Major
      0x00, // Major
      0x6A, // Minor
      0x97, // Minor
      0x42,  //
      // service UUID, to notify central devices what services are included
      // in this peripheral
      0x03,  // length of this data
      GAP_ADTYPE_16BIT_MORE,      // some of the UUID's, but not all
    //  LO_UINT16(OAD_RESET_SERVICE_UUID),
    //  HI_UINT16(OAD_RESET_SERVICE_UUID),
      LO_UINT16(0xADA0),
      HI_UINT16(0xADA0),
    };
    
    // GAP GATT Attributes
    static uint8_t attDeviceName[GAP_DEVICE_NAME_LEN] = "SBP OAD on-chip";
    
    // Globals used for ATT Response retransmission
    static gattMsgEvent_t *pAttRsp = NULL;
    static uint8_t rspTxRetry = 0;
    static uint8_t verifyStatus = OAD_INCOMPATIBLE_IMAGE;
    
    
    #if defined(GAP_BOND_MGR) && !defined(GATT_NO_SERVICE_CHANGED)
    // Flag to be stored in NV that tracks whether service changed
    // indications needs to be sent out
    static uint32_t  sendSvcChngdOnNextBoot = FALSE;
    #endif // ( defined(GAP_BOND_MGR) && !defined(GATT_NO_SERVICE_CHANGED) )
    
    // Variable used to store the number of messages pending once OAD completes
    // The application cannot reboot until all pending messages are sent
    static uint8_t numPendingMsgs = 0;
    
    #ifdef LED_DEBUG
    // Pin table for LED debug pins
    static const PIN_Config sbpLedPins[] = {
        Board_LED0 | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL | PIN_DRVSTR_MAX,
        Board_LED1 | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL | PIN_DRVSTR_MAX,
        PIN_TERMINATE
    };
    #endif //LED_DEBUG
    
    // State variable for debugging LEDs
    PIN_State  sbpLedState;
    
    /*********************************************************************
     * LOCAL FUNCTIONS
     */
    
    static void SimplePeripheral_init( void );
    static void SimplePeripheral_taskFxn(UArg a0, UArg a1);
    
    static uint8_t SimplePeripheral_processStackMsg(ICall_Hdr *pMsg);
    static uint8_t SimplePeripheral_processGATTMsg(gattMsgEvent_t *pMsg);
    static void SimplePeripheral_processAppMsg(sbpEvt_t *pMsg);
    static void SimplePeripheral_processStateChangeEvt(gaprole_States_t newState);
    static void SimplePeripheral_processCharValueChangeEvt(uint8_t paramID);
    static void SimplePeripheral_performPeriodicTask(void);
    static void SimplePeripheral_clockHandler(UArg arg);
    static void SimplePeripheral_sendAttRsp(void);
    static void SimplePeripheral_freeAttRsp(uint8_t status);
    static void SimplePeripheral_stateChangeCB(gaprole_States_t newState);
    static void SimplePeripheral_charValueChangeCB(uint8_t paramID);
    static uint8_t SimplePeripheral_enqueueMsg(uint8_t event, uint8_t state, uint8_t *pData);
    
    static void SimplePeripheral_connEvtCB(Gap_ConnEventRpt_t *pReport);
    static void SimplePeripheral_processOadResetEvt(oadResetWrite_t *resetEvt);
    static uint8_t SimplePeripheral_processL2CAPMsg(l2capSignalEvent_t *pMsg);
    void SimplePeripheral_processOadResetWriteCB(uint16_t connHandle,
                                                    uint8_t *payload,
                                                    uint16_t len);
    static void SimplePeripheral_processPasscode(gapPasskeyNeededEvent_t *pData);
    static void SimplePeripheral_passcodeCB(uint8_t *deviceAddr,
                                            uint16_t connHandle,
                                            uint8_t uiInputs, uint8_t uiOutputs,
                                            uint32_t numComparison);
    
    
    /*********************************************************************
     * EXTERN FUNCTIONS
     */
    extern void AssertHandler(uint8_t assertCause, uint8_t assertSubcause);
    
    /*********************************************************************
     * PROFILE CALLBACKS
     */
    
    // GAP Role Callbacks
    static gapRolesCBs_t SimplePeripheral_gapRoleCBs =
    {
      SimplePeripheral_stateChangeCB     // Profile State Change Callbacks
    };
    
    // GAP Bond Manager Callbacks
    static gapBondCBs_t SimplePeripheral_BondMgrCBs =
    {
      SimplePeripheral_passcodeCB, // Passcode callback,
      NULL                         // Pairing / Bonding state Callback (not used by application)
    };
    
    // Simple GATT Profile Callbacks
    static simpleProfileCBs_t SimplePeripheral_simpleProfileCBs =
    {
      SimplePeripheral_charValueChangeCB // Characteristic value change callback
    };
    
    static oadResetWriteCB_t SimplePeripheral_oadResetCBs =
    {
      SimplePeripheral_processOadResetWriteCB // Write Callback.
    };
    
    /*********************************************************************
     * PUBLIC FUNCTIONS
     */
    /*********************************************************************
     * The following typedef and global handle the registration to connection event
     */
    typedef enum
    {
       NOT_REGISTER       = 0,
       FOR_AOA_SCAN       = 1,
       FOR_ATT_RSP        = 2,
       FOR_AOA_SEND       = 4,
       FOR_TOF_SEND       = 8,
       FOR_OAD_SEND       = 0x10,
    }connectionEventRegisterCause_u;
    
    // Handle the registration and un-registration for the connection event, since only one can be registered.
    uint32_t       connectionEventRegisterCauseBitMap = NOT_REGISTER; //see connectionEventRegisterCause_u
    
    /*********************************************************************
     * @fn      SimplePeripheral_RegistertToAllConnectionEvent()
     *
     * @brief   register to receive connection events for all the connection
     *
     * @param connectionEventRegisterCause represents the reason for registration
     *
     * @return @ref SUCCESS
     *
     */
    bStatus_t SimplePeripheral_RegistertToAllConnectionEvent (connectionEventRegisterCause_u connectionEventRegisterCause)
    {
      bStatus_t status = SUCCESS;
    
      // in case  there is no registration for the connection event, make the registration
      if (!CONNECTION_EVENT_IS_REGISTERED)
      {
        status = GAP_RegisterConnEventCb(SimplePeripheral_connEvtCB, GAP_CB_REGISTER, LINKDB_CONNHANDLE_ALL);
      }
      if(status == SUCCESS)
      {
        //add the reason bit to the bitamap.
        CONNECTION_EVENT_REGISTER_BIT_SET(connectionEventRegisterCause);
      }
    
      return(status);
    }
    
    /*********************************************************************
     * @fn      SimplePeripheral_UnRegistertToAllConnectionEvent()
     *
     * @brief   Unregister connection events
     *
     * @param connectionEventRegisterCause represents the reason for registration
     *
     * @return @ref SUCCESS
     *
     */
    bStatus_t SimplePeripheral_UnRegistertToAllConnectionEvent (connectionEventRegisterCause_u connectionEventRegisterCause)
    {
      bStatus_t status = SUCCESS;
    
      CONNECTION_EVENT_REGISTER_BIT_REMOVE(connectionEventRegisterCause);
      // in case  there is no more registration for the connection event than unregister
      if (!CONNECTION_EVENT_IS_REGISTERED)
      {
        GAP_RegisterConnEventCb(SimplePeripheral_connEvtCB, GAP_CB_UNREGISTER, LINKDB_CONNHANDLE_ALL);
      }
    
      return(status);
    }
    
    /*********************************************************************
     * @fn      SimplePeripheral_createTask
     *
     * @brief   Task creation function for the OAD User App.
     *
     * @param   None.
     *
     * @return  None.
     */
    void SimplePeripheral_createTask(void)
    {
      Task_Params taskParams;
    
      // Configure task
      Task_Params_init(&taskParams);
      taskParams.stack = sbpTaskStack;
      taskParams.stackSize = SBP_TASK_STACK_SIZE;
      taskParams.priority = SBP_TASK_PRIORITY;
    
      Task_construct(&sbpTask, SimplePeripheral_taskFxn, &taskParams, NULL);
    }
    
    /*********************************************************************
     * @fn      SimplePeripheral_init
     *
     * @brief   Called during initialization and contains application
     *          specific initialization (ie. hardware initialization/setup,
     *          table initialization, power up notification, etc), and
     *          profile initialization/setup.
     *
     * @param   None.
     *
     * @return  None.
     */
    static void SimplePeripheral_init(void)
    {
      // ******************************************************************
      // NO STACK API CALLS CAN OCCUR BEFORE THIS CALL TO ICall_registerApp
      // ******************************************************************
      // Register the current thread as an ICall dispatcher application
      // so that the application can send and receive messages.
      ICall_registerApp(&selfEntity, &syncEvent);
    // Hard code the BD Address till CC2650 board gets its own IEEE address
      //uint8 bdAddress[B_ADDR_LEN] = { 0x35, 0x97, 0x6a, 0x0e, 0x6c, 0x54 };
      uint8 bdAddress[B_ADDR_LEN] = { 0x42, 0x97, 0x6A, 0x22, 0x66, 0x9b };
      HCI_EXT_SetBDADDRCmd(bdAddress);
      HCI_EXT_SetSCACmd(40);
    
    #ifdef USE_RCOSC
      RCOSC_enableCalibration();
    #endif // USE_RCOSC
    
      // Create an RTOS queue for message from profile to be sent to app.
      appMsgQueue = Util_constructQueue(&appMsg);
    
      // Create one-shot clocks for internal periodic events.
      Util_constructClock(&periodicClock, SimplePeripheral_clockHandler,
                          SBP_PERIODIC_EVT_PERIOD, 0, FALSE, SBP_PERIODIC_EVT);
    
      dispHandle = Display_open(SBP_DISPLAY_TYPE, NULL);
    
      // For on-chip OAD stack-only download must be followed by app-only
      // So the current app must always be linked to the right stack
      // use this info to read in the stack version
      imgHdr_t *stackImageHeader = (imgHdr_t *)(_imageHdr.boundarySeg.stackStartAddr);
    
      // Read in the OAD Software version
      uint8_t swVer[OAD_SW_VER_LEN] = {stackImageHeader->fixedHdr.softVer[0],
                                        stackImageHeader->fixedHdr.softVer[1],
                                        _imageHdr.fixedHdr.softVer[2],
                                        _imageHdr.fixedHdr.softVer[3]};
    
      // Setup the GAP
      GAP_SetParamValue(TGAP_CONN_PAUSE_PERIPHERAL, DEFAULT_CONN_PAUSE_PERIPHERAL);
    
      // Setup the GAP Peripheral Role Profile
      {
        // For all hardware platforms, device starts advertising upon initialization
        uint8_t initialAdvertEnable = TRUE;
    
        // By setting this to zero, the device will go into the waiting state after
        // being discoverable for 30.72 second, and will not being advertising again
        // until the enabler is set back to TRUE
        uint16_t advertOffTime = 0;
    
        uint8_t enableUpdateRequest = DEFAULT_ENABLE_UPDATE_REQUEST;
        uint16_t desiredMinInterval = DEFAULT_DESIRED_MIN_CONN_INTERVAL;
        uint16_t desiredMaxInterval = DEFAULT_DESIRED_MAX_CONN_INTERVAL;
        uint16_t desiredSlaveLatency = DEFAULT_DESIRED_SLAVE_LATENCY;
        uint16_t desiredConnTimeout = DEFAULT_DESIRED_CONN_TIMEOUT;
    
        // Set the GAP Role Parameters
        GAPRole_SetParameter(GAPROLE_ADVERT_ENABLED, sizeof(uint8_t),
                             &initialAdvertEnable);
        GAPRole_SetParameter(GAPROLE_ADVERT_OFF_TIME, sizeof(uint16_t),
                             &advertOffTime);
    
        // Setup the dyanmic portion of the scanRspData
    //    scanRspData[OAD_SOFT_VER_OFFSET] = swVer[0];
    //    scanRspData[OAD_SOFT_VER_OFFSET + 1] = swVer[1];
    //    scanRspData[OAD_SOFT_VER_OFFSET + 2] = swVer[2];
    //    scanRspData[OAD_SOFT_VER_OFFSET + 3] = swVer[3];
    
        // Set scanRspData
        GAPRole_SetParameter(GAPROLE_SCAN_RSP_DATA, sizeof(scanRspData),
                             scanRspData);
        GAPRole_SetParameter(GAPROLE_ADVERT_DATA, sizeof(advertData), advertData);
    
        GAPRole_SetParameter(GAPROLE_PARAM_UPDATE_ENABLE, sizeof(uint8_t),
                             &enableUpdateRequest);
        GAPRole_SetParameter(GAPROLE_MIN_CONN_INTERVAL, sizeof(uint16_t),
                             &desiredMinInterval);
        GAPRole_SetParameter(GAPROLE_MAX_CONN_INTERVAL, sizeof(uint16_t),
                             &desiredMaxInterval);
        GAPRole_SetParameter(GAPROLE_SLAVE_LATENCY, sizeof(uint16_t),
                             &desiredSlaveLatency);
        GAPRole_SetParameter(GAPROLE_TIMEOUT_MULTIPLIER, sizeof(uint16_t),
                             &desiredConnTimeout);
      }
    
      // Set the GAP Characteristics
      GGS_SetParameter(GGS_DEVICE_NAME_ATT, GAP_DEVICE_NAME_LEN, attDeviceName);
    
      // Set advertising interval
      {
        uint16_t advInt = DEFAULT_ADVERTISING_INTERVAL;
    
        GAP_SetParamValue(TGAP_LIM_DISC_ADV_INT_MIN, advInt);
        GAP_SetParamValue(TGAP_LIM_DISC_ADV_INT_MAX, advInt);
        GAP_SetParamValue(TGAP_GEN_DISC_ADV_INT_MIN, advInt);
        GAP_SetParamValue(TGAP_GEN_DISC_ADV_INT_MAX, advInt);
      }
    
      // Setup the GAP Bond Manager
      {
        uint8_t pairMode = GAPBOND_PAIRING_MODE_WAIT_FOR_REQ;
        uint8_t mitm = TRUE;
        uint8_t ioCap = GAPBOND_IO_CAP_DISPLAY_ONLY;
        uint8_t bonding = TRUE;
        uint8_t scMode = GAPBOND_SECURE_CONNECTION_ALLOW;
    
        GAPBondMgr_SetParameter(GAPBOND_PAIRING_MODE, sizeof(uint8_t), &pairMode);
        GAPBondMgr_SetParameter(GAPBOND_MITM_PROTECTION, sizeof(uint8_t), &mitm);
        GAPBondMgr_SetParameter(GAPBOND_IO_CAPABILITIES, sizeof(uint8_t), &ioCap);
        GAPBondMgr_SetParameter(GAPBOND_BONDING_ENABLED, sizeof(uint8_t), &bonding);
        GAPBondMgr_SetParameter(GAPBOND_SECURE_CONNECTION, sizeof(uint8_t), &scMode);
      }
    
       // Initialize GATT attributes
      GGS_AddService(GATT_ALL_SERVICES);           // GAP
      GATTServApp_AddService(GATT_ALL_SERVICES);   // GATT attributes
      DevInfo_AddService();                        // Device Information Service
    
      SimpleProfile_AddService(GATT_ALL_SERVICES); // Simple GATT Profile
    
    
      Reset_addService((oadUsrAppCBs_t *)&SimplePeripheral_oadResetCBs);
    
      // Setup the SimpleProfile Characteristic Values
      {
        uint8_t charValue1 = 1;
        uint8_t charValue2 = 2;
        uint8_t charValue3 = 3;
        uint8_t charValue4 = 4;
        uint8_t charValue5[SIMPLEPROFILE_CHAR5_LEN] = { 1, 2, 3, 4, 5 };
    
        SimpleProfile_SetParameter(SIMPLEPROFILE_CHAR1, sizeof(uint8_t),
                                   &charValue1);
        SimpleProfile_SetParameter(SIMPLEPROFILE_CHAR2, sizeof(uint8_t),
                                   &charValue2);
        SimpleProfile_SetParameter(SIMPLEPROFILE_CHAR3, sizeof(uint8_t),
                                   &charValue3);
        SimpleProfile_SetParameter(SIMPLEPROFILE_CHAR4, sizeof(uint8_t),
                                   &charValue4);
        SimpleProfile_SetParameter(SIMPLEPROFILE_CHAR5, SIMPLEPROFILE_CHAR5_LEN,
                                   charValue5);
      }
    
      // Register callback with SimpleGATTprofile
      SimpleProfile_RegisterAppCBs(&SimplePeripheral_simpleProfileCBs);
    
      // Start the Device
      VOID GAPRole_StartDevice(&SimplePeripheral_gapRoleCBs);
    
      // Start Bond Manager
      VOID GAPBondMgr_Register(&SimplePeripheral_BondMgrCBs);
    
      // Register with GAP for HCI/Host messages
      GAP_RegisterForMsgs(selfEntity);
    
      // Register for GATT local events and ATT Responses pending for transmission
      GATT_RegisterForMsgs(selfEntity);
    
      uint8_t versionStr[OAD_SW_VER_LEN + 1];
    
      memcpy(versionStr, swVer, OAD_SW_VER_LEN);
    
      // Add in Null terminator
      versionStr[OAD_SW_VER_LEN] = NULL;
    
      // Display Image version
      Display_print1(dispHandle, 0, 0, "SBP On-chip OAD v%s",
                     versionStr);
    
    
    #ifdef LED_DEBUG
      // Open the LED debug pins
      if (!PIN_open(&sbpLedState, sbpLedPins))
      {
        Display_print0(dispHandle, 0, 0, "Debug PINs failed to open");
      }
      else
      {
        PIN_Id activeLed;
        uint8_t numBlinks = 9;
        uint8_t cnt=0;
        for(; cnt < 10; ++cnt)
        {
          activeLed = Board_LED0;
    
          PIN_setOutputValue(&sbpLedState, activeLed, !PIN_getOutputValue(activeLed));
    
          // Sleep for 100ms, sys-tick for BLE-Stack is 10us,
          // Task sleep is in # of ticks
          Task_sleep(10000);
    
        }
        for(; cnt<numBlinks; ++cnt)
        {
          activeLed = Board_LED1;
    
          PIN_setOutputValue(&sbpLedState, activeLed, !PIN_getOutputValue(activeLed));
    
          // Sleep for 100ms, sys-tick for BLE-Stack is 10us,
          // Task sleep is in # of ticks
          Task_sleep(10000);
    
        }
    
        // Close the pins after using
        PIN_close(&sbpLedState);
      }
    #endif //LED_DEBUG
    
    #if defined(GAP_BOND_MGR) && !defined(GATT_NO_SERVICE_CHANGED)
      /*
       * When switching from persistent app back to the user application for the
       * for the first time after an OAD the device must send a service changed
       * indication. This will cause any peers to rediscover services.
       *
       * To prevent sending a service changed IND on every boot, a flag is stored
       * in NV to determine whether or not the service changed IND needs to be
       * sent
       */
      uint8_t status = osal_snv_read(BLE_NVID_CUST_START,
                                      sizeof(sendSvcChngdOnNextBoot),
                                      (uint8 *)&sendSvcChngdOnNextBoot);
      if(status != SUCCESS)
      {
        /*
         * On first boot the NV item will not have yet been initialzed, and the read
         * will fail. Do a write to set the initial value of the flash in NV
         */
         osal_snv_write(BLE_NVID_CUST_START, sizeof(sendSvcChngdOnNextBoot),
                        (uint8 *)&sendSvcChngdOnNextBoot);
      }
    #endif // ( defined(GAP_BOND_MGR) && !defined(GATT_NO_SERVICE_CHANGED) )
    }
    
    /*********************************************************************
     * @fn      SimplePeripheral_taskFxn
     *
     * @brief   Application task entry point for the OAD User App.
     *
     * @param   a0, a1 - not used.
     *
     * @return  None.
     */
    static void SimplePeripheral_taskFxn(UArg a0, UArg a1)
    {
      // Initialize application
      SimplePeripheral_init();
    
      // Application main loop
      for (;;)
      {
        uint32_t events;
    
        // Waits for an event to be posted associated with the calling thread.
        // Note that an event associated with a thread is posted when a
        // message is queued to the message receive queue of the thread
        events = Event_pend(syncEvent, Event_Id_NONE, SBP_ALL_EVENTS,
                            ICALL_TIMEOUT_FOREVER);
    
        if (events)
        {
          ICall_EntityID dest;
          ICall_ServiceEnum src;
          ICall_HciExtEvt *pMsg = NULL;
    
          if (ICall_fetchServiceMsg(&src, &dest,
                                    (void **)&pMsg) == ICALL_ERRNO_SUCCESS)
          {
            uint8_t safeToDealloc = TRUE;
    
            if ((src == ICALL_SERVICE_CLASS_BLE) && (dest == selfEntity))
            {
              ICall_Stack_Event *pEvt = (ICall_Stack_Event *)pMsg;
              if (pEvt->signature != 0xffff)
              {
                // Process inter-task message
                safeToDealloc = SimplePeripheral_processStackMsg((ICall_Hdr *)pMsg);
              }
            }
    
            if (pMsg && safeToDealloc)
            {
              ICall_freeMsg(pMsg);
            }
          }
    
          // If RTOS queue is not empty, process app message.
          if (events & SBP_QUEUE_EVT)
          {
            while (!Queue_empty(appMsgQueue))
            {
    
              // Get the first message from the Queue
              sbpEvt_t *pMsg = (sbpEvt_t *)Util_dequeueMsg(appMsgQueue);
    
              if (pMsg)
              {
                // Process message.
                SimplePeripheral_processAppMsg(pMsg);
    
                if (pMsg->pData != NULL)
                {
                  // Free the Queue payload if there is one
                  ICall_free(pMsg->pData);
                }
    
                // Free the space from the message.
                ICall_free(pMsg);
              }
    
            }
          }
    
          if (events & SBP_PERIODIC_EVT)
          {
            Util_startClock(&periodicClock);
    
            // Perform periodic application task
            SimplePeripheral_performPeriodicTask();
          }
        }
      }
    }
    
    /*********************************************************************
     * @fn      SimplePeripheral_performPeriodicTask
     *
     * @brief   Perform a periodic application task. This function gets called
     *          every five seconds (SBP_PERIODIC_EVT_PERIOD). In this example,
     *          the value of the third characteristic in the SimpleGATTProfile
     *          service is retrieved from the profile, and then copied into the
     *          value of the the fourth characteristic.
     *
     * @param   None.
     *
     * @return  None.
     */
    static void SimplePeripheral_performPeriodicTask(void)
    {
      uint8_t valueToCopy;
    
      // Call to retrieve the value of the third characteristic in the profile
      if (SimpleProfile_GetParameter(SIMPLEPROFILE_CHAR3, &valueToCopy) == SUCCESS)
      {
        // Call to set that value of the fourth characteristic in the profile.
        // Note that if notifications of the fourth characteristic have been
        // enabled by a GATT client device, then a notification will be sent
        // every time this function is called.
        SimpleProfile_SetParameter(SIMPLEPROFILE_CHAR4, sizeof(uint8_t),
                                   &valueToCopy);
      }
    }
    
    /*********************************************************************
     * @fn      SimplePeripheral_processStackMsg
     *
     * @brief   Process an incoming stack message.
     *
     * @param   pMsg - message to process
     *
     * @return  TRUE if safe to deallocate incoming message, FALSE otherwise.
     */
    static uint8_t SimplePeripheral_processStackMsg(ICall_Hdr *pMsg)
    {
      uint8_t safeToDealloc = TRUE;
    
      switch (pMsg->event)
      {
        case GATT_MSG_EVENT:
          // Process GATT message
          safeToDealloc = SimplePeripheral_processGATTMsg((gattMsgEvent_t *)pMsg);
          break;
    
        case HCI_GAP_EVENT_EVENT:
          {
    
            // Process HCI message
            switch(pMsg->status)
            {
              case HCI_COMMAND_COMPLETE_EVENT_CODE:
                // Process HCI Command Complete Event
                break;
    
              case HCI_BLE_HARDWARE_ERROR_EVENT_CODE:
                AssertHandler(HAL_ASSERT_CAUSE_HARDWARE_ERROR,0);
                break;
    
              default:
                break;
            }
          }
          break;
    
          case L2CAP_SIGNAL_EVENT:
            // Process L2CAP signal
            safeToDealloc = SimplePeripheral_processL2CAPMsg((l2capSignalEvent_t *)pMsg);
            break;
    
          default:
            // do nothing
            break;
    
        }
    
      return (safeToDealloc);
    }
    
    /*********************************************************************
     * @fn      SimplePeripheral_processL2CAPMsg
     *
     * @brief   Process L2CAP messages and events.
     *
     * @return  TRUE if safe to deallocate incoming message, FALSE otherwise.
     */
    static uint8_t SimplePeripheral_processL2CAPMsg(l2capSignalEvent_t *pMsg)
    {
      uint8_t safeToDealloc = TRUE;
    
      static bool firstRun = TRUE;
    
      switch (pMsg->opcode)
      {
        case L2CAP_NUM_CTRL_DATA_PKT_EVT:
        {
          /*
           * We cannot reboot the device immediately after receiving
           * the enable command, we must allow the stack enough time
           * to process and respond to the OAD_EXT_CTRL_ENABLE_IMG
           * command. This command will determine the number of
           * packets currently queued up by the LE controller.
           * BIM var is already set via OadPersistApp_processOadWriteCB
           */
          if(firstRun)
          {
            firstRun = false;
    
            // We only want to set the numPendingMsgs once
            numPendingMsgs = MAX_NUM_PDU - pMsg->cmd.numCtrlDataPktEvt.numDataPkt;
    
            // Wait the number of connection events
            SimplePeripheral_RegistertToAllConnectionEvent (FOR_OAD_SEND);
          }
    
          break;
        }
        default:
          break;
      }
    
      // It's safe to free the incoming message
      return (safeToDealloc);
    }
    
    /*********************************************************************
     * @fn      SimplePeripheral_processGATTMsg
     *
     * @brief   Process GATT messages and events.
     *
     * @return  TRUE if safe to deallocate incoming message, FALSE otherwise.
     */
    static uint8_t SimplePeripheral_processGATTMsg(gattMsgEvent_t *pMsg)
    {
      // See if GATT server was unable to transmit an ATT response
      if (pMsg->hdr.status == blePending)
      {
        // No HCI buffer was available. Let's try to retransmit the response
        // on the next connection event.
        if( SimplePeripheral_RegistertToAllConnectionEvent(FOR_ATT_RSP) == SUCCESS)
        {
          // First free any pending response
          SimplePeripheral_freeAttRsp(FAILURE);
    
          // Hold on to the response message for retransmission
          pAttRsp = pMsg;
    
          // Don't free the response message yet
          return (FALSE);
        }
      }
      else if (pMsg->method == ATT_FLOW_CTRL_VIOLATED_EVENT)
      {
        // ATT request-response or indication-confirmation flow control is
        // violated. All subsequent ATT requests or indications will be dropped.
        // The app is informed in case it wants to drop the connection.
    
        // Display the opcode of the message that caused the violation.
        Display_print1(dispHandle, 5, 0, "FC Violated: %d", pMsg->msg.flowCtrlEvt.opcode);
      }
      else if (pMsg->method == ATT_MTU_UPDATED_EVENT)
      {
        // MTU size updated
        Display_print1(dispHandle, 5, 0, "MTU Size: %d", pMsg->msg.mtuEvt.MTU);
      }
    
      // Free message payload. Needed only for ATT Protocol messages
      GATT_bm_free(&pMsg->msg, pMsg->method);
    
      // It's safe to free the incoming message
      return (TRUE);
    }
    
    /*********************************************************************
     * @fn      SimplePeripheral_processConnEvt
     *
     * @brief   Process connection event.
     *
     * @param pReport pointer to connection event report
     */
    static void SimplePeripheral_processConnEvt(Gap_ConnEventRpt_t *pReport)
    {
    
      if( CONNECTION_EVENT_REGISTRATION_CAUSE(FOR_ATT_RSP))
      {
        // The GATT server might have returned a blePending as it was trying
        // to process an ATT Response. Now that we finished with this
        // connection event, let's try sending any remaining ATT Responses
        // on the next connection event.
        // Try to retransmit pending ATT Response (if any)
        SimplePeripheral_sendAttRsp();
      }
      if( CONNECTION_EVENT_REGISTRATION_CAUSE(FOR_OAD_SEND))
      {
        // Wait until all pending messages are sent
        if((verifyStatus == OAD_SUCCESS) && (numPendingMsgs == 0))
        {
    #if defined(GAP_BOND_MGR) && !defined(GATT_NO_SERVICE_CHANGED)
          uint8_t status ;
          // Store the flag to indicate that a service changed IND will
          // be sent at the next boot
          sendSvcChngdOnNextBoot = TRUE;
    
          status = osal_snv_write(BLE_NVID_CUST_START,
                                          sizeof(sendSvcChngdOnNextBoot),
                                          (uint8 *)&sendSvcChngdOnNextBoot);
          if(status != SUCCESS)
          {
            Display_print1(dispHandle, 5, 0, "SNV WRITE FAIL: %d", status);
          }
    #endif // ( defined(GAP_BOND_MGR) && !defined(GATT_NO_SERVICE_CHANGED) )
    
          // Reset the system
          HAL_SYSTEM_RESET();
        }
        numPendingMsgs--;
      }
    }
    /*********************************************************************
     * @fn      SimplePeripheral_sendAttRsp
     *
     * @brief   Send a pending ATT response message.
     *
     * @param   none
     *
     * @return  none
     */
    static void SimplePeripheral_sendAttRsp(void)
    {
      // See if there's a pending ATT Response to be transmitted
      if (pAttRsp != NULL)
      {
        uint8_t status;
    
        // Increment retransmission count
        rspTxRetry++;
    
        // Try to retransmit ATT response till either we're successful or
        // the ATT Client times out (after 30s) and drops the connection.
        status = GATT_SendRsp(pAttRsp->connHandle, pAttRsp->method, &(pAttRsp->msg));
        if ((status != blePending) && (status != MSG_BUFFER_NOT_AVAIL))
        {
          // Disable connection event end notice
          SimplePeripheral_UnRegistertToAllConnectionEvent (FOR_ATT_RSP);
          // We're done with the response message
          SimplePeripheral_freeAttRsp(status);
        }
        else
        {
          // Continue retrying
          Display_print1(dispHandle, 5, 0, "Rsp send retry: %d", rspTxRetry);
        }
      }
    }
    
    /*********************************************************************
     * @fn      SimplePeripheral_freeAttRsp
     *
     * @brief   Free ATT response message.
     *
     * @param   status - response transmit status
     *
     * @return  none
     */
    static void SimplePeripheral_freeAttRsp(uint8_t status)
    {
      // See if there's a pending ATT response message
      if (pAttRsp != NULL)
      {
        // See if the response was sent out successfully
        if (status == SUCCESS)
        {
          Display_print1(dispHandle, 5, 0, "Rsp sent retry: %d", rspTxRetry);
        }
        else
        {
          // Free response payload
          GATT_bm_free(&pAttRsp->msg, pAttRsp->method);
    
          Display_print1(dispHandle, 5, 0, "Rsp retry failed: %d", rspTxRetry);
        }
    
        // Free response message
        ICall_freeMsg(pAttRsp);
    
        // Reset our globals
        pAttRsp = NULL;
        rspTxRetry = 0;
      }
    }
    
    /*********************************************************************
     * @fn      SimplePeripheral_processAppMsg
     *
     * @brief   Process an incoming callback from a profile.
     *
     * @param   pMsg - message to process
     *
     * @return  None.
     */
    static void SimplePeripheral_processAppMsg(sbpEvt_t *pMsg)
    {
      switch (pMsg->hdr.event)
      {
        case SBP_STATE_CHANGE_EVT:
        {
          SimplePeripheral_processStateChangeEvt((gaprole_States_t)pMsg->
                                                    hdr.state);
          break;
        }
    
        case SBP_CHAR_CHANGE_EVT:
        {
          SimplePeripheral_processCharValueChangeEvt(pMsg->hdr.state);
    
          break;
        }
    
        case SBP_OAD_RESET_EVT:
        {
          // Convert generic pData pointer to oadResetWrite_t
          oadResetWrite_t *oadResetEvt  = (oadResetWrite_t *)(pMsg->pData);
    
          // Process the reset event
          SimplePeripheral_processOadResetEvt(oadResetEvt);
          break;
        }
    
        case SBP_PASSCODE_NEEDED_EVT:
        {
          SimplePeripheral_processPasscode((gapPasskeyNeededEvent_t*)pMsg->pData);
          // Free the app data
          break;
        }
        case SBP_CONN_EVT:
        {
            SimplePeripheral_processConnEvt((Gap_ConnEventRpt_t *)(pMsg->pData));
    
            break;
        }
    
        default:
          // Do nothing.
          break;
      }
    }
    
    /*********************************************************************
     * @fn      SimplePeripheral_processStateChangeEvt
     *
     * @brief   Process a pending GAP Role state change event.
     *
     * @param   newState - new state
     *
     * @return  None.
     */
    static void SimplePeripheral_processStateChangeEvt(gaprole_States_t newState)
    {
      switch ( newState )
      {
        case GAPROLE_STARTED:
          {
            uint8_t ownAddress[B_ADDR_LEN];
            uint8_t systemId[DEVINFO_SYSTEM_ID_LEN];
    
            GAPRole_GetParameter(GAPROLE_BD_ADDR, ownAddress);
    
            // use 6 bytes of device address for 8 bytes of system ID value
            systemId[0] = ownAddress[0];
            systemId[1] = ownAddress[1];
            systemId[2] = ownAddress[2];
    
            // set middle bytes to zero
            systemId[4] = 0x00;
            systemId[3] = 0x00;
    
            // shift three bytes up
            systemId[7] = ownAddress[5];
            systemId[6] = ownAddress[4];
            systemId[5] = ownAddress[3];
    
            DevInfo_SetParameter(DEVINFO_SYSTEM_ID, DEVINFO_SYSTEM_ID_LEN, systemId);
    
            // Display device address
            Display_print0(dispHandle, 1, 0, Util_convertBdAddr2Str(ownAddress));
            Display_print0(dispHandle, 2, 0, "Initialized");
          }
          break;
    
        case GAPROLE_ADVERTISING:
          Display_print0(dispHandle, 2, 0, "Advertising");
          break;
    
        case GAPROLE_CONNECTED:
          {
            linkDBInfo_t linkInfo;
            uint8_t numActive = 0;
            uint16_t connHandle = 0;
    
            GAPRole_GetParameter(GAPROLE_CONNHANDLE, &connHandle);
    
            Util_startClock(&periodicClock);
    
            numActive = linkDB_NumActive();
    
            // Use numActive to determine the connection handle of the last
            // connection
            if ( linkDB_GetInfo( numActive - 1, &linkInfo ) == SUCCESS )
            {
              Display_print1(dispHandle, 2, 0, "Num Conns: %d", (uint16_t)numActive);
              Display_print0(dispHandle, 3, 0, Util_convertBdAddr2Str(linkInfo.addr));
            }
            else
            {
              uint8_t peerAddress[B_ADDR_LEN];
    
              GAPRole_GetParameter(GAPROLE_CONN_BD_ADDR, peerAddress);
    
              Display_print0(dispHandle, 2, 0, "Connected");
              Display_print0(dispHandle, 3, 0, Util_convertBdAddr2Str(peerAddress));
            }
    
    #if defined(GAP_BOND_MGR) && !defined(GATT_NO_SERVICE_CHANGED)
            if(sendSvcChngdOnNextBoot == TRUE)
            {
              GAPBondMgr_ServiceChangeInd( connHandle, TRUE);
    
              sendSvcChngdOnNextBoot = FALSE;
            }
    #endif // ( defined(GAP_BOND_MGR) && !defined(GATT_NO_SERVICE_CHANGED) )
          }
          break;
    
        case GAPROLE_CONNECTED_ADV:
          Display_print0(dispHandle, 2, 0, "Connected Advertising");
          break;
    
        case GAPROLE_WAITING:
          Util_stopClock(&periodicClock);
          SimplePeripheral_freeAttRsp(bleNotConnected);
    
          Display_print0(dispHandle, 2, 0, "Disconnected");
    
          // Clear remaining lines
          Display_clearLines(dispHandle, 3, 5);
          break;
    
        case GAPROLE_WAITING_AFTER_TIMEOUT:
          SimplePeripheral_freeAttRsp(bleNotConnected);
    
          Display_print0(dispHandle, 2, 0, "Timed Out");
    
          // Clear remaining lines
          Display_clearLines(dispHandle, 3, 5);
    
          break;
    
        case GAPROLE_ERROR:
          Display_print0(dispHandle, 2, 0, "Error");
          break;
    
        default:
          Display_clearLine(dispHandle, 2);
          break;
      }
    }
    
    /*********************************************************************
    * @fn      SimplePeripheral_processPasscode
    *
    * @brief   Process the Passcode request.
    *
    * @return  none
    */
    static void SimplePeripheral_processPasscode(gapPasskeyNeededEvent_t *pData)
    {
      // Use static passcode
      uint32_t passcode = 123456;
      Display_print1(dispHandle, 5, 0, "Passcode: %d", passcode);
      // Send passcode to GAPBondMgr
      GAPBondMgr_PasscodeRsp(pData->connectionHandle, SUCCESS, passcode);
    }
    
    /*********************************************************************
     * @fn      SimplePeripheral_processCharValueChangeEvt
     *
     * @brief   Process a pending Simple Profile characteristic value change
     *          event.
     *
     * @param   paramID - parameter ID of the value that was changed.
     *
     * @return  None.
     */
    static void SimplePeripheral_processCharValueChangeEvt(uint8_t paramID)
    {
      uint8_t newValue;
    
      switch(paramID)
      {
        case SIMPLEPROFILE_CHAR1:
          SimpleProfile_GetParameter(SIMPLEPROFILE_CHAR1, &newValue);
    
          Display_print1(dispHandle, 4, 0, "Char 1: %d", (uint16_t)newValue);
          break;
    
        case SIMPLEPROFILE_CHAR3:
          SimpleProfile_GetParameter(SIMPLEPROFILE_CHAR3, &newValue);
    
          Display_print1(dispHandle, 4, 0, "Char 3: %d", (uint16_t)newValue);
          break;
    
        default:
          // should not reach here!
          break;
      }
    }
    
    /*********************************************************************
     * @fn      SimplePeripheral_processOadResetEvt
     *
     * @brief   Process a write request to the OAD reset service
     *
     * @param   resetEvt - The oadResetWrite_t struct containing reset data
     *
     * @return  None.
     */
    static void SimplePeripheral_processOadResetEvt(oadResetWrite_t *resetEvt)
    {
      /* We cannot reboot the device immediately after receiving
       * the enable command, we must allow the stack enough time
       * to process and responsd to the OAD_EXT_CTRL_ENABLE_IMG
       * command. The current implementation will wait one cxn evt
       */
      // Register for L2CAP Flow Control Events
      L2CAP_RegisterFlowCtrlTask(selfEntity);
    
      /* First, disable pairing for the duration of the sign/verify procedure
       * This is done because the BLE-stack may use the ECC code during pairing for
       * ECC key generation
       */
      uint8_t pairingMode = GAPBOND_PAIRING_MODE_NO_PAIRING;
      GAPBondMgr_SetParameter(GAPBOND_PAIRING_MODE, sizeof(pairingMode),
                              &pairingMode);
      uint8_t cmdID = resetEvt->payload[0];
      
      verifyStatus = OAD_SUCCESS; /* fake verify status */
      
      // Set the bim_var based on the command ID
      if(cmdID == OAD_RESET_CMD_START_OAD)
      {
        // Set the BIM variable to jump to persistent application
        _bim_var = 0x00000001;
      }
      else
      {
        // Set BIM variable to jump back to user application
        _bim_var = 0x00000101;
      }
    
      // re-enable paring
      pairingMode = DEFAULT_PAIRING_MODE;
      GAPBondMgr_SetParameter(GAPBOND_PAIRING_MODE, sizeof(pairingMode),
                              &pairingMode);
    }
    
    /*********************************************************************
     * Callback Functions - These run in the calling thread's context
     *********************************************************************/
    
     /*********************************************************************
    * @fn      SimplePeripheral_passcodeCB
    *
    * @brief   Passcode callback.
    *
    * @param   deviceAddr - pointer to device address
    *
    * @param   connHandle - the connection handle
    *
    * @param   uiInputs - pairing User Interface Inputs
    *
    * @param   uiOutputs - pairing User Interface Outputs
    *
    * @param   numComparison - numeric Comparison 20 bits
    *
    * @return  none
    */
    static void SimplePeripheral_passcodeCB(uint8_t *deviceAddr,
                                            uint16_t connHandle,
                                            uint8_t uiInputs, uint8_t uiOutputs,
                                            uint32_t numComparison)
    {
      gapPasskeyNeededEvent_t *pData;
    
      // Allocate space for the passcode event.
      if ((pData = ICall_malloc(sizeof(gapPasskeyNeededEvent_t))))
      {
        memcpy(pData->deviceAddr, deviceAddr, B_ADDR_LEN);
        pData->connectionHandle = connHandle;
        pData->uiInputs = uiInputs;
        pData->uiOutputs = uiOutputs;
        pData->numComparison = numComparison;
    
        // Enqueue the event.
        SimplePeripheral_enqueueMsg(SBP_PASSCODE_NEEDED_EVT, NULL,
                                        (uint8_t *) pData);
      }
    }
    
    /*********************************************************************
     * @fn      SimplePeripheral_stateChangeCB
     *
     * @brief   Callback from GAP Role indicating a role state change.
     *
     * @param   newState - new state
     *
     * @return  None.
     */
    static void SimplePeripheral_stateChangeCB(gaprole_States_t newState)
    {
      SimplePeripheral_enqueueMsg(SBP_STATE_CHANGE_EVT, newState, NULL);
    }
    
    /*********************************************************************
     * @fn      SimplePeripheral_charValueChangeCB
     *
     * @brief   Callback from Simple Profile indicating a characteristic
     *          value change.
     *
     * @param   paramID - parameter ID of the value that was changed.
     *
     * @return  None.
     */
    static void SimplePeripheral_charValueChangeCB(uint8_t paramID)
    {
      SimplePeripheral_enqueueMsg(SBP_CHAR_CHANGE_EVT, paramID, NULL);
    }
    
    /*********************************************************************
     * @fn      SimplePeripheral_processOadResetWriteCB
     *
     * @brief   Process a write request to the OAD reset service
     *
     * @param   connHandle - the connection Handle this request is from.
     * @param   bim_var    - bim_var to set before resetting.
     *
     * @return  None.
     */
    void SimplePeripheral_processOadResetWriteCB(uint16_t connHandle,
                                                    uint8_t *payload,
                                                    uint16_t len)
    {
        // Allocate memory for OAD EVT payload, the app task must free this later
        oadResetWrite_t *oadResetWriteEvt = ICall_malloc(sizeof(oadResetWrite_t));
        if(oadResetWriteEvt)
        {
            oadResetWriteEvt->connHandle = connHandle;
            oadResetWriteEvt->payload = payload;
            oadResetWriteEvt->len = len;
    
            // This function will enqueue the messsage and wake the application
            SimplePeripheral_enqueueMsg(SBP_OAD_RESET_EVT, 0, (uint8_t *)oadResetWriteEvt);
        }
    }
    
    /*********************************************************************
     * SWI Functions - These functions run at higher priority than any task
     *********************************************************************/
    
    /*********************************************************************
     * @fn      SimplePeripheral_clockHandler
     *
     * @brief   Handler function for clock timeouts.
     *
     * @param   arg - event type
     *
     * @return  None.
     */
    static void SimplePeripheral_clockHandler(UArg arg)
    {
      // Wake up the application.
      Event_post(syncEvent, arg);
    }
    
    /*********************************************************************
     * @fn      SimplePeripheral_connEvtCB
     *
     * @brief   Connection event callback.
     *
     * @param pReport pointer to connection event report
     */
    static void SimplePeripheral_connEvtCB(Gap_ConnEventRpt_t *pReport)
    {
      // Enqueue the event for processing in the app context.
      if( SimplePeripheral_enqueueMsg(SBP_CONN_EVT, 0 ,(uint8_t *) pReport) == FALSE)
      {
        ICall_free(pReport);
      }
    
    }
    /*********************************************************************
     *
     * @brief   Creates a message and puts the message in RTOS queue.
     *
     * @param   event - message event.
     * @param   state - message state.
     * @param   pData - message data pointer.
     *
     * @return  TRUE or FALSE
     */
    static uint8_t SimplePeripheral_enqueueMsg(uint8_t event, uint8_t state,
                                               uint8_t *pData)
    {
      sbpEvt_t *pMsg = ICall_malloc(sizeof(sbpEvt_t));
    
      // Create dynamic pointer to message.
      if (pMsg)
      {
        pMsg->hdr.event = event;
        pMsg->hdr.state = state;
        pMsg->pData = pData;
    
        // Enqueue the message.
        return Util_enqueueMsg(appMsgQueue, syncEvent, (uint8_t *)pMsg);
      }
    
      return FALSE;
    }
    /*********************************************************************/