• Resolved

CC2640R2F: Bonding fails

Expert 2700 points

Replies: 7

Views: 109

Part Number: CC2640R2F

Hy,

still I can't get it to work: I try to implement pairing / bonding to my BLE Peripheral OAD Offchip based project. I use the same hardware and run the original project: Everything works and my own project: Bonding fails.

For the current tests I use nRF connect from Android as generic BLE Central device. In the well working variant I observe the following:

The device advertises. I connect. It discovers services and displays them. Then I hit "Bond", I need to enter the passcode, afterwards it says "Bonded".

The Log from nRF Connect looks like this:

nRF Connect, 2019-03-07
SBP OAD APP v0001 (A4:34:F1:81:CF:37)
V	11:10:36.762	Connecting to A4:34:F1:81:CF:37...
D	11:10:36.763	gatt = device.connectGatt(autoConnect = false, TRANSPORT_LE)

D	11:10:36.971	[Callback] Connection state changed with status: 0 and new state: CONNECTED (2)
I	11:10:36.971	Connected to A4:34:F1:81:CF:37
D	11:10:36.976	[Broadcast] Action received: android.bluetooth.device.action.ACL_CONNECTED
...
V	11:10:47.011	Starting pairing...
D	11:10:47.011	device.createBond()
D	11:10:47.057	[Broadcast] Action received: android.bluetooth.device.action.BOND_STATE_CHANGED, bond state changed to: BOND_BONDING (11)
D	11:10:47.397	[Broadcast] Action received: android.bluetooth.device.action.PAIRING_REQUEST, pairing variant: PAIRING_VARIANT_PIN (0)
D	11:11:01.099	[Broadcast] Action received: android.bluetooth.device.action.BOND_STATE_CHANGED, bond state changed to: BOND_BONDED (12)
I	11:11:01.099	Device bonded

Now when I use my device:

It advertises, I connect. Immediately, the Android device vibrates as if I need to enter a passcode, but no mask appears. It discovers services and displays them.When I hit "Bond" a mask to enter passcode appears, I enter the passcode but the device disconnects immediately. The nRF Connect log looks like this:

nRF Connect, 2019-03-07
MYDEVICE  (A4:34:F1:81:CF:37)
V	14:04:02.196	Connecting to A4:34:F1:81:CF:37...
D	14:04:02.196	gatt = device.connectGatt(autoConnect = false, TRANSPORT_LE)
D	14:04:02.369	[Broadcast] Action received:  android.bluetooth.device.action.BOND_STATE_CHANGED, bond state changed to: BOND_BONDING (11)
D	14:04:02.397	[Callback] Connection state changed with status: 0 and new state: CONNECTED (2)
I	14:04:02.397	Connected to A4:34:F1:81:CF:37
D	14:04:02.411	[Broadcast] Action received: android.bluetooth.device.action.ACL_CONNECTED
D	14:04:02.667	[Broadcast] Action received: android.bluetooth.device.action.PAIRING_REQUEST, pairing variant: PAIRING_VARIANT_PIN (0)
D	14:04:02.701	[Broadcast] Action received: android.bluetooth.device.action.BOND_STATE_CHANGED, bond state changed to: BOND_NONE (10)
I	14:04:02.701	Bonding failed
...
V	14:04:24.311	Starting pairing...
D	14:04:24.311	device.createBond()
D	14:04:24.339	[Broadcast] Action received: android.bluetooth.device.action.BOND_STATE_CHANGED, bond state changed to: BOND_BONDING (11)
D	14:04:24.693	[Broadcast] Action received: android.bluetooth.device.action.PAIRING_REQUEST, pairing variant: PAIRING_VARIANT_PIN (0)
D	14:04:24.693	[Broadcast] Action received: android.bluetooth.device.action.BOND_STATE_CHANGED, bond state changed to: BOND_NONE (10)
I	14:04:24.693	Bonding failed
D	14:04:27.703	[Callback] Connection state changed with status: 22 and new state: DISCONNECTED (0)
E	14:04:27.705	Error 22 (0x16): GATT CONN TERMINATE LOCAL HOST
I	14:04:27.705	Disconnected
D	14:04:28.081	[Broadcast] Action received: android.bluetooth.device.action.ACL_DISCONNECTED

So apparently the device requests a bond right after connection?

I compared the code and it looks totally identical: From project_oad_offchip.c:

// 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 SYSPROFILE_CHAR_CHANGE_EVT            0x0002
//#define SBP_PAIRING_STATE_EVT                 0x0004
#define SBP_PASSCODE_NEEDED_EVT               0x0008
#define DATAPROFILE_CHAR_CHANGE_EVT           0x0010
// Application specific event ID for Connection Event End Events
#define SBP_CONN_EVT                          0x0020

// GAP Bond Manager Callbacks
static gapBondCBs_t SimplePeripheral_BondMgrCBs =
{
  (pfnPasscodeCB_t)SimplePeripheral_passcodeCB, // Passcode callback,
  NULL  // Pairing / Bonding state Callback (not used by application)
};
static void project_init(void)
{
...
  // 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;
    uint8_t replaceBonds = FALSE;

    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);
    GAPBondMgr_SetParameter(GAPBOND_LRU_BOND_REPLACEMENT, sizeof(uint8_t), &replaceBonds);
  }
...
  // Start the Device
  VOID GAPRole_StartDevice(&Bauernstolz_gapRoleCBs);

  // Start Bond Manager
  VOID GAPBondMgr_Register(&SimplePeripheral_BondMgrCBs);

/*********************************************************************
 * @fn      SimplePeripheral_passcodeCB
 *
 * @brief   Passcode callback.
 *
 * @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.
    project_enqueueMsg(SBP_PASSCODE_NEEDED_EVT, NULL,
                                    (uint8_t *) pData);
  }
}
/*********************************************************************
 * @fn      project_processAppMsg
 *
 * @brief   Process an incoming callback from a profile.
 *
 * @param   pMsg - message to process
 *
 * @return  None.
 */
static void project_processAppMsg(sbpEvt_t *pMsg)
{
  switch (pMsg->hdr.event)
  {
...
    case SBP_PASSCODE_NEEDED_EVT:
    {
      SimplePeripheral_processPasscode((gapPasskeyNeededEvent_t*)pMsg->pData);
      break;
    }
...
}
/*********************************************************************
* @fn      SimplePeripheral_processPasscode
*
* @brief   Process the Passcode request.
*
* @return  none
*/
static void SimplePeripheral_processPasscode(gapPasskeyNeededEvent_t *pData)
{
  // Use static passcode
  uint32_t passcode = 331734;
  //Display_print1(dispHandle, SBP_ROW_SECURITY, 0, "Passcode: %d", passcode);
  // Send passcode to GAPBondMgr
  GAPBondMgr_PasscodeRsp(pData->connectionHandle, SUCCESS, passcode);
}

Apparently, the passcode Callback never gets called: I added a counter variable, it never gets increased. Also, a breakpoint within SimplePeripheral_passcodeCB is never reached:

What other pieces of code might be interesting?

Any help appreciated

Harald

  • Hi Harald,
    Are you able to provide a sniffer trace?

    Regards, Joakim

     

  • In reply to J Lindh:

    Hy,

    here is the bt snoop log in two downloads, I do not know which one works within the TI forum:

    /cfs-file/__key/communityserver-discussions-components-files/538/1348.btsnoop_5F00_hci.log

    https://cloud.pieye.org/index.php/s/HFzZ5cLeY6NNX6G

    A Samsung J5 (SamsungE_83:3c:af (LytentecJ5)  )wants to talk to the BLE device (  TexasIns_81:cf:37 (ZFOBD ))

    Does that give you any insights?

    Regards

    Harald

  • In reply to Harald Ilg:

    Hello. Can you describe what exactly you're trying to do? In your original post, you said you did not want to authenticate / bond but now it appears you are trying to bond.

    Also, please describe how to replicate this in a step by step process. Ensure that are you starting with a clean test: remove the device from the paired devices in the phone's Bluetooth settings and erase the embedded device's flash before starting.

    Best wishes,
    Tim

    ------------------------------------------------------------------------------------------------------------

    Please be sure to mark the thread as answered if your question was answered :)

  • In reply to Tim C:

    Hy Tim,

    yes, this might have become unclear in the meantime:

    In the very end the overall system shall work like this:

    During production every device gets a passcode. This passcode is printed on the label of the device and stored to the external flash. When the device is taken into operation and connected the first time the user scans the printed passcode with the Android/iOS App, then the app shall be able to connect and bond to the device. If for whatever reason reading the code by camera is not possible the user shall be able to enter the code manually.

    Because at the beginning of the project pair/bond did not work instantly we decided to postpone the implementation that the developers of the app are able to connect and read and write data. I created a firmware version without pairing bonding which works perfectly for my PC connection (pygatt and BLED112), the iOS and _some_ android devices. On about 50% of the devices we are not able to connect because a bonding is initiated immediately which fails.

    >remove the device from the paired devices in the phone's Bluetooth settings and erase the embedded device's flash before starting.

    I did not find a way of removing the device from my bonded devices because I assume it is not bonded. In androids bluetooth list it appears under "available devices" and not under "bonded devices". I also switched off and on Bluetooth and reboot the android device.

    As for the BLE peripheral device: I used "mass erase" in Flash Programmer Tool and flashed BIM, Stack and App from flash programmers tool. I did not delete external flash but I can't think of how this can influence the behaviour.

    > Also, please describe how to replicate this in a step by step process

    - open nRF Connect on Android Samsung J5

    - scan for devices

    - identify UUT and verify advertising and scan response data -> everything OK

    - press connect on UUT

    - Android vibrates, no mask appears

    - message "unable to communicate"

    - Device is still connected, everything works: Discover, read, notify

    - Press "bond" on android

    - Android vibrates, no mask appears

    - device disconnects

    https://youtu.be/yMcQJ4Xg8Y0

    When using the original simple peripheral off chip example it feels like expected:

    - connect

    - press bond

    - mask appears, enter passcode

    - android shows "bonded"

    Again: I don't observe anything on the BLE peripheral device, no breakpoint is reached. What code should be called initially when a android device tries to bond? What ways of analyzing do I have? What settings do I need to check?

    Regards

    Harald

  • In reply to Harald Ilg:

    I would guess that you have some mismatched settings between the two devices that don't allow for pairing such as I/O capabilities, authentication, etc.

    I would try the following:
    1. Compare the GAPBondMgr parameters that you are using between your project and the default simple_peripheral project. I would start with the exact parameters from the simple_peripheral project so you know you have something working.
    2. You can inspect what is happening by looking at the callbacks received from GAPBondMgr(). I see that you have removed the pairing state callback. I would recommend adding this so you can see what states are occurring. You can find the expected sequence here (I would recommend reading the entire gapbondmgr section): dev.ti.com/.../gapbondmngr.html

    Another possibility is that you messed up the messaging between callback context and app processing context. So you should verify that you are actually getting to your process passcode / pair state function in your application.

    In short, if you have a working example for simple_peripheral, you can follow through the callbacks to see where the difference is.

    Best wishes,
    Tim

    ------------------------------------------------------------------------------------------------------------

    Please be sure to mark the thread as answered if your question was answered :)

  • In reply to Tim C:

    Hy Tim,

    thanks for your message.

    >1. Compare the GAPBondMgr parameters that you are using between your project and the default simple_peripheral project. I w

    I have done that before. My settings are identical

    >I see that you have removed the pairing state callback.

    I have not, there is no pairing state callback in the sample application.

    >So you should verify that you are actually getting to your process passcode / pair state function in your application.

    No, I do not. I do not reach any breakpoint that I set anywhere in the callback function.

    I started to do it the hard way:

    I started the project from scratch, so I used simple_peripheral_oad_offchip and integrated all code of my project step by step.

    After every integration of a couple of source code lines I tested if bonding works OK.

    Now I am at the point where a simple change in the source code gets my project into the false state:

    Within the init function I call my own init function:

    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);
      ...
      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) )
      initApplication();
    
    }
    void initApplication(void)
    {
        PWM_Params      pwmParams;
    
        /* Call driver init functions. */
        PWM_init();
        PWM_Params_init(&pwmParams);
        pwmParams.dutyUnits = PWM_DUTY_FRACTION;
        pwmParams.dutyValue = PWM_DUTY_FRACTION_MAX / 2;
        pwmParams.periodUnits = PWM_PERIOD_HZ;
        pwmParams.periodValue = 1000;
        pwmParams.idleLevel = PWM_IDLE_LOW;
        canclkpwm = PWM_open(Board_5XD_PWM0, &pwmParams);
        if ((uint32_t)canclkpwm == 0) {
            /* Board_PWM0 did not open */
            while (1);
        }
    
        PWM_start(canclkpwm);
    
    /* Open SPI as master (default) */
        SPI_Params_init(&spiParams);
        spiParams.bitRate = 8000000;  // 8 MHz Bit rate
        spiParams.frameFormat = SPI_POL0_PHA0;
        spiParams.transferTimeout = 0x1000;
        SPI_init();
        masterSpi = SPI_open(Board_5XD_SPI0, &spiParams);
    
        GPIO_write(Board_SPI_FLASH_CS, 1);
        GPIO_write(Board_SPI_CANA_CS, 1);
        GPIO_write(Board_SPI_CANB_CS, 1);
    }
    

    When I comment out the call to initApplication(); within simplePeripheral_init function bonding works OK, when I execute the initApplication(); function bonding does not work. The initApplication function itself works fine, the PWM signal is as expected and I can use SPI.

    Something must get corrupt when calling this function. Any idea on where to search?

    Might that be a memory issue? I do not get any warnings and the map files seem OK:

    App:
    MEMORY CONFIGURATION
    
             name            origin    length      used     unused   attr    fill
    ----------------------  --------  ---------  --------  --------  ----  --------
      FLASH_IMG_HDR         00000000   000000a8  00000050  00000058  R  X
      ENTRY                 000000a8   00000040  0000003c  00000004  R  X
      FLASH                 000000e8   00013f98  00009b02  0000a496  R  X
      SRAM                  20000000   00003f68  00002865  00001703  RW X
    
    Stack:
    MEMORY CONFIGURATION
    
             name            origin    length      used     unused   attr    fill
    ----------------------  --------  ---------  --------  --------  ----  --------
      FLASH                 00000000   0001e000  0000a000  00014000  R  X
      SRAM                  20000000   00004400  00000498  00003f68  RW X
    
    
    SEGMENT ALLOCATION MAP
    
    run origin  load origin   length   init length attrs members
    ----------  ----------- ---------- ----------- ----- -------
    00014000    00014000    00008edc   00008edc    r-x
      00014000    00014000    00000050   00000050    r-- .image_header
      00014050    00014050    00007858   00007858    r-x .text
      0001b8a8    0001b8a8    00000e30   00000e30    r-- .const
      0001c6d8    0001c6d8    00000094   00000094    r-- .rodata
      0001c770    0001c770    000003e0   000003e0    r-- .cinit
      0001cb50    0001cb50    0000038c   0000038c    r-x EntrySection
    0001d000    0001d000    00001000   00001000    r--
      0001d000    0001d000    00001000   00001000    r-- .snvSectors
    20003f68    20003f68    00000498   00000000    rw-
      20003f68    20003f68    000003b0   00000000    rw- .data
      20004318    20004318    000000e8   00000000    rw- .bss
    
    BIM:
    MEMORY CONFIGURATION
    
             name            origin    length      used     unused   attr    fill
    ----------------------  --------  ---------  --------  --------  ----  --------
      FLASH_BIM             0001e000   00001f54  0000115f  00000df5  R  X
      FLASH_CERT            0001ff54   0000004c  00000000  0000004c  R  X
      FLASH_FNPTR           0001ffa0   00000004  00000000  00000004  R  X
      FLASH_CCFG            0001ffa8   00000058  00000058  00000000  R  X
      SRAM                  20000000   00004400  0000437c  00000084  RW X

    Regards

    Harald

  • In reply to Harald Ilg:

    Hy,

    finally, it seemed that I solved the issue: It was a heap problem. I don't know why I haven't found that before, but now it seems quite clear.

    I enabled usage of AUX_RAM as described here, so I won 1936byte of RAM which is used for the heap.

    When running the application now, bonding works without problems.

    When I observe heap with HEAPMGR_METRICS I see that bonding costs 1,360bytes of heap. Thats more than I would have expected...

    So, now I hope that there won't be similar heap-expensive processes in the future. Is there anything else that costs a lot of heap that I should test?

    Regards

    Harald