Quantcast
Channel: Forums - Recent Threads
Viewing all articles
Browse latest Browse all 262198

CC2650MODA: BLE Multirole Android Connection Loss after ~30 Seconds

$
0
0

Part Number:CC2650MODA

I'm currently working on a Firmware for the CC2650MODA which enables me to connect from an Android Phone to the device and the device itself to another device (Phone <-> Device <-> Device).

I started with project_zero for a single connection. The phone can connect to the device, enable notifications for several characteristics and runs until the link is terminated by the user.

For multiple connections I used the multirole example. The firmware itself works as intended when using a CC2650-LaunchPad with the host_test and the "BLE Device Monitor". I can connect to the device, change characteristics as wanted and also make the device connect to another peripheral (LaunchPad <-> CC2650MODA<-> CC2650MODA). When using an android phone, the connection can be established, characteristics can be written to or read from, everything works fine. But after around 30 seconds, the device disconnects with reason 0x13 or 0x08.

I tried to setup the multirole peripheral as identical to project_zero as possible, but it did not help. Also tried disabling boding as discribed here, but it didnt work for me.

Project Zero:
TI v18.12.1LTS
XDCtools 3.32.0.06_core
TI-RTOS 2.20.1.08
BLE SDK 2_02_01_18

Multirole:
TI v18.12.1LTS
XDCtools 3.32.0.06_core
TI-RTOS 2.20.1.08
BLE SDK 2_02_01_18

Source Snippet project_zero:


void task_project_zero_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 via ICall to Stack.
    ICall_registerApp(&[projectName]_entity, &[projectName]_sem);

    // ******************************************************************
     // BLE Stack initialization
     // ******************************************************************

     // Setup the GAP Peripheral Role Profile
     uint8_t initialAdvertEnable = TRUE;  // Advertise on power-up

     // By setting this to zero, the device will go into the waiting state after
     // being discoverable. Otherwise wait this long [ms] before advertising again.
     uint16_t advertOffTime = 0; // miliseconds

     // Set advertisement enabled.
     GAPRole_SetParameter(GAPROLE_ADVERT_ENABLED, sizeof(uint8_t),
                          &initialAdvertEnable);

     // Configure the wait-time before restarting advertisement automatically
     GAPRole_SetParameter(GAPROLE_ADVERT_OFF_TIME, sizeof(uint16_t),
                          &advertOffTime);

     // Initialize Scan Response data
     GAPRole_SetParameter(GAPROLE_SCAN_RSP_DATA, sizeof(scanRspData), scanRspData);

     // Initialize Advertisement data
     GAPRole_SetParameter(GAPROLE_ADVERT_DATA, sizeof(advertData), advertData);

    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;


     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);

   //  Log_info1("Name in advertData array: \x1b[33m%s\x1b[0m",
   //            (IArg)Util_getLocalNameStr(advertData));

     // 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);

     // Set duration of advertisement before stopping in Limited adv mode.
     GAP_SetParamValue(TGAP_LIM_ADV_TIMEOUT, 30); // Seconds




     // ******************************************************************
     // BLE Bond Manager initialization
     // ******************************************************************
     uint32_t passkey = 0; // passkey "000000"
     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;

     GAPBondMgr_SetParameter(GAPBOND_DEFAULT_PASSCODE, sizeof(uint32_t),
                             &passkey);
     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);

     // ******************************************************************
     // BLE Service initialization
     // ******************************************************************

     // Add services to GATT server
     GGS_AddService(GATT_ALL_SERVICES);           // GAP
     GATTServApp_AddService(GATT_ALL_SERVICES);   // GATT attributes
     DevInfo_AddService();                        // Device Information Service

     // Set the device name characteristic in the GAP Profile
     GGS_SetParameter(GGS_DEVICE_NAME_ATT, GAP_DEVICE_NAME_LEN, attDeviceName);

     // User service
     // ... [Cut out] ...

     // Start the stack in Peripheral mode.
     VOID GAPRole_StartDevice(&[projectName]_gapRoleCBs);

     // Start Bond Manager
     VOID GAPBondMgr_Register(&[projectName]_bondMgrCBs);

     // Register with GAP for HCI/Host messages
     GAP_RegisterForMsgs([projectName]_entity);

     // Register for GATT local events and ATT Responses pending for transmission
     GATT_RegisterForMsgs([projectName]_entity);

     // User inits
     // ... [Cut out] ...
}

 

Source Snippet Multirole

static void multi_role_init(void)
{  
  // ******************************************************************
  // N0 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, &sem);
  
  // Create an RTOS queue for message from profile to be sent to app.
  appMsgQueue = Util_constructQueue(&appMsg);
  
  //init keys and LCD
  Board_initKeys(multi_role_keyChangeHandler);
  // Open Display.
  dispHandle = Display_open(SBC_DISPLAY_TYPE, NULL);
  
  // Setup the GAP
  {
    /*-------------------PERIPHERAL-------------------*/
    // set advertising interval the same for all scenarios
    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);
#warning modified
//    GAP_SetParamValue(TGAP_CONN_ADV_INT_MIN, advInt);
//    GAP_SetParamValue(TGAP_CONN_ADV_INT_MAX, advInt);
    // Set duration of advertisement before stopping in Limited adv mode.
    GAP_SetParamValue(TGAP_LIM_ADV_TIMEOUT, 30); // Seconds
    /*-------------------CENTRAL-------------------*/
    // set scan duration
    GAP_SetParamValue(TGAP_GEN_DISC_SCAN, DEFAULT_SCAN_DURATION);
    // scan interval and window the same for all scenarios
    GAP_SetParamValue(TGAP_CONN_SCAN_INT, DEFAULT_SCAN_INT);
    GAP_SetParamValue(TGAP_CONN_SCAN_WIND, DEFAULT_SCAN_WIND);
    GAP_SetParamValue(TGAP_CONN_HIGH_SCAN_INT, DEFAULT_SCAN_INT);
    GAP_SetParamValue(TGAP_CONN_HIGH_SCAN_WIND, DEFAULT_SCAN_WIND);
    GAP_SetParamValue(TGAP_GEN_DISC_SCAN_INT, DEFAULT_SCAN_INT);
    GAP_SetParamValue(TGAP_GEN_DISC_SCAN_WIND, DEFAULT_SCAN_WIND);
    GAP_SetParamValue(TGAP_LIM_DISC_SCAN_INT, DEFAULT_SCAN_INT);
    GAP_SetParamValue(TGAP_LIM_DISC_SCAN_WIND, DEFAULT_SCAN_WIND);
    GAP_SetParamValue(TGAP_CONN_EST_SCAN_INT, DEFAULT_SCAN_INT);
    GAP_SetParamValue(TGAP_CONN_EST_SCAN_WIND, DEFAULT_SCAN_WIND);
    // set connection parameters
    GAP_SetParamValue(TGAP_CONN_EST_INT_MIN, DEFAULT_CONN_INT);
    GAP_SetParamValue(TGAP_CONN_EST_INT_MAX, DEFAULT_CONN_INT);
    GAP_SetParamValue(TGAP_CONN_EST_SUPERV_TIMEOUT, DEFAULT_CONN_TIMEOUT);
    GAP_SetParamValue(TGAP_CONN_EST_LATENCY, DEFAULT_CONN_LATENCY);

    //register to receive GAP and HCI messages
    GAP_RegisterForMsgs(selfEntity);
  }
  
  // Setup the GAP Role Profile
  {
    /*--------PERIPHERAL-------------*/
    uint8_t initialAdvertEnable = TRUE;
    uint16_t advertOffTime = 0;
    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;

    // device starts advertising upon initialization
    GAPRole_SetParameter(GAPROLE_ADVERT_ENABLED, sizeof(uint8_t),
                         &initialAdvertEnable, NULL);
    // 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
    GAPRole_SetParameter(GAPROLE_ADVERT_OFF_TIME, sizeof(uint16_t),
                         &advertOffTime, NULL);
    // set scan response data
    GAPRole_SetParameter(GAPROLE_SCAN_RSP_DATA, sizeof(scanRspData),
                         scanRspData, NULL);
    // set advertising data
    GAPRole_SetParameter(GAPROLE_ADVERT_DATA, sizeof(advertData), advertData, NULL);

    // set connection parameters
    GAPRole_SetParameter(GAPROLE_MIN_CONN_INTERVAL, sizeof(uint16_t),
                         &desiredMinInterval, NULL);
    GAPRole_SetParameter(GAPROLE_MAX_CONN_INTERVAL, sizeof(uint16_t),
                         &desiredMaxInterval, NULL);
    GAPRole_SetParameter(GAPROLE_SLAVE_LATENCY, sizeof(uint16_t),
                         &desiredSlaveLatency, NULL);
    GAPRole_SetParameter(GAPROLE_TIMEOUT_MULTIPLIER, sizeof(uint16_t),
                         &desiredConnTimeout, NULL);

    /*--------------CENTRAL-----------------*/
    uint8_t scanRes = DEFAULT_MAX_SCAN_RES;
    //set the max amount of scan responses
    GAPRole_SetParameter(GAPROLE_MAX_SCAN_RES, sizeof(uint8_t),
                         &scanRes, NULL);

    // Start the GAPRole and negotiate max number of connections
    VOID GAPRole_StartDevice(&multi_role_gapRoleCBs, &maxNumBleConns);

    //allocate memory for index to connection handle map
    if (connHandleMap = ICall_malloc(sizeof(uint16_t) * maxNumBleConns))
    {
      // init index to connection handle map to 0's
      for (uint8_t i = 0; i < maxNumBleConns; i++)
      {
        connHandleMap[i] = INVALID_CONNHANDLE;
      }
    }

    //allocate memory for per connection discovery information
    if (discInfo = ICall_malloc(sizeof(discInfo_t) * maxNumBleConns))
    {
      // init index to connection handle map to 0's
      for (uint8_t i = 0; i < maxNumBleConns; i++)
      {
        discInfo[i].charHdl = 0;
        discInfo[i].discState = BLE_DISC_STATE_IDLE;
        discInfo[i].svcEndHdl = 0;
        discInfo[i].svcStartHdl = 0;
      }
    }
  }

  // Setup the GAP Bond Manager
    {
  #warning modification
      uint32_t passkey = DEFAULT_PASSCODE;
      //uint8_t pairMode = GAPBOND_PAIRING_MODE_INITIATE;
      //uint8_t pairMode = GAPBOND_PAIRING_MODE_WAIT_FOR_REQ;
      uint8_t pairMode = GAPBOND_PAIRING_MODE_NO_PAIRING;
      uint8_t mitm = TRUE;
      uint8_t ioCap = GAPBOND_IO_CAP_DISPLAY_ONLY;
      uint8_t bonding = TRUE;

      // set passcode
      GAPBondMgr_SetParameter(GAPBOND_DEFAULT_PASSCODE, sizeof(uint32_t),
                              &passkey);
      // set pairing mode
      GAPBondMgr_SetParameter(GAPBOND_PAIRING_MODE, sizeof(uint8_t), &pairMode);
      // set authentication requirements
      GAPBondMgr_SetParameter(GAPBOND_MITM_PROTECTION, sizeof(uint8_t), &mitm);
      // set i/o capabilities
      GAPBondMgr_SetParameter(GAPBOND_IO_CAPABILITIES, sizeof(uint8_t), &ioCap);
      // set bonding requirements
      GAPBondMgr_SetParameter(GAPBOND_BONDING_ENABLED, sizeof(uint8_t), &bonding);

      // Register and start Bond Manager
      VOID GAPBondMgr_Register(&multi_role_BondMgrCBs);
    }
  
  //GATT
  {
    /*---------------------SERVER------------------------*/
    // Set the GAP Characteristics
    GGS_SetParameter(GGS_DEVICE_NAME_ATT, GAP_DEVICE_NAME_LEN, attDeviceName);

    // Initialize GATT Server Services
    GGS_AddService(GATT_ALL_SERVICES);           // GAP
    GATTServApp_AddService(GATT_ALL_SERVICES);   // GATT attributes
    DevInfo_AddService();

    /**************************************************************************
     * Services
     *************************************************************************/

    // Custom service here
    // ... [Cut out] ...



//

    /*-----------------CLIENT------------------*/
    // Initialize GATT Client
    VOID GATT_InitClient();

    // Register for GATT local events and ATT Responses pending for transmission
    GATT_RegisterForMsgs(selfEntity);
    
    // Register to receive incoming ATT Indications/Notifications
    GATT_RegisterForInd(selfEntity);    
  }
  
  // Additional user inits
  // ... [Cut out] ...
}


Viewing all articles
Browse latest Browse all 262198

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>