This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

PM_EVT_CONN_SEC_FAILED

I am developing a Central/Peripheral application with SDK 15.2.0 for s132 device on nRF52 development kits. I switch back and forth between my application and the example "ble_app_hrs_rscs_relay" on my nRF52 development boards. In doing so, eventually my nRF52 development boards will throw the error PM_EVT_CONN_SEC_FAILED when running on my application firmware and connecting to a peripheral device. I can never get PM_EVT_CONN_SEC_SUCCEEDED again on this nRF52 development board operating as a Central and Peripheral. When I put my application firmware on a new nRF52 DK, it runs fine and gets PM_EVT_CONN_SEC_SUCCEEDED every time it connects to a peripheral BLE device. This has happened to me with two nRF DKs and now I'm working with a 3rd, but I have not cycled between the "ble_app_hrs_rscs_relay" and my application firmware. I have only been programming it with my application firmware and it has been running fine. I have tried "erase all" on the problem DKs and this didn't help.

Parents Reply Children
  • I have run out of things to try. I purchased a couple more dev boards, in case it happens again. As long as I don't switch back and forth between my firmware and "ble_app_hrs_rscd_relay" example on the same dev board, the problem doesn't happen. But I have 2 previous dev boards I can't use now because of this. I even program them with the BLE peripheral heart rate example, and they don't work.

    Did you see my question earlier? When I did a full erase in nRF Connect, the log showed "Non-volatile memory has been read. 1 non-empty memory blocks identified".

    Is that normal?

  • I am not too familiar with the log message and what it means, and I could not find much information about it either. 

    I might be on thin ice here, and I am not sure if I understand everything perfectly, but I'll take a shot.

    You said you got a procedure failed of 133 (0x85), which corresponds to a BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP. If I understand everything correctly, this comes from the smd_params_reply() function in the security_dispatcher.c file. Specifically these lines:

    if ((im_peer_id_get_by_conn_handle(conn_handle) != PM_PEER_ID_INVALID) &&
                (role == BLE_GAP_ROLE_PERIPH) &&
                !allow_repairing(conn_handle))
            {
                // Bond already exists. Reject the pairing request if the user doesn't intervene.
                send_config_req(conn_handle);
                if (!allow_repairing(conn_handle))
                {
                    // Reject pairing.
                    sec_status = BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP;
                }
            }

    However, could you set a break point at sec_status = BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP;  to check if this line is executed. 

    This line should be run if there is a valid peer associated with the connection handle, if the role is peripheral and repairing is not allowed. The problem for you (I guess) is that the function im_peer_id_get_by_conn_handle() returns a valid peer id.

    How should you avoid this? First take a look at the id_manager.c file and the function im_ble_evt_handler(). After a connection, it will look for the address of the newly connected peer among the peer data in flash. If it finds the address, it will associate the connection handle with the matching peer id thorugh the line: 

    m_connections[gap_evt.conn_handle].peer_id      = bonded_matching_peer_id;

    and the peer id will not be invalid anymore, and you will get a BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP as described above.

     case BLE_GAP_ADDR_TYPE_RANDOM_STATIC:
                   while (pds_peer_data_iterate(PM_PEER_DATA_ID_BONDING, &peer_id, &peer_data))
                    {
                        if (addr_compare(&gap_evt.params.connected.peer_addr,
                                         &peer_data.p_bonding_data->peer_ble_id.id_addr_info))
                        {
                            bonded_matching_peer_id = peer_id;
                            break;
                        }
                    }

    The easiest way to solve this, would be to simply erase all the flash, but lets try another approach. Inside the function im_ble_evt_handler()  add this code snippet under switch (gap_evt.params.connected.peer_addr.addr_type)

    .
    .
    
    switch (gap_evt.params.connected.peer_addr.addr_type)
        {
            /////Add this///
            while (pds_peer_data_iterate(PM_PEER_DATA_ID_BONDING, &peer_id, &peer_data))
            {
                if (addr_compare(&gap_evt.params.connected.peer_addr,
                                 &peer_data.p_bonding_data->peer_ble_id.id_addr_info))
                {
                    pds_peer_id_free(peer_id);
                    break;
                }
            }
            /////Add this///
        case BLE_GAP_ADDR_TYPE_PUBLIC:
        .
        .
        

    Similarly if your address is resolvable, you switch out addr_compare() with im_address_resolve(). This code snippet will erase all peer data from flash related to the address. This code snippet is only supposed to run once, in order to delete the peer data from flash, and you should stop the code execution after these lines.  This is a quite messy way of doing it, and is is probably a more easy and clean approach, my apologies for that. 

    You could also try this.

    Best regards,

    Simon

  • Hi Simon. I never said that I got a procedure failed of 133 (0x85), so I'm not sure your suggested changes in im_ble_evt_handler() are relevant.

  • mzarling said:

    <info> peer_manager_handler: Connection security failed: role: Central, conn_handle: 0x0, procedure: Bonding, error: 133

    Is this what you asked for?

  • My mistake, sorry. I will set the breakpoint as suggested and proceed from there.

Related