This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

nRF52840 random disconnection

Good morning,

We have a new equipment based on the nRF52840 and s140.

                Just now, a new problem has appeared and it is very strange, as it seems to be a ‘random’ error:

 

                We have already assembled tens of equipment, and most of them are perfectly working with any smartphone (using both your ‘nRF Connect’ application or our own application).

                But, we have a few smartphones that show a strange behavior: they are able to perfectly connect to some of our nRF52840-based equipment, and in a few ones, they are able to connect but they get disconnected after a few seconds. Same equipment is connecting to other smartphones without problems (without disconnecting).

                This is (step by step) what it is happening a few times:

  • Equipment (nRF52840) is advertising.
  • Smartphone stablish connection with equipment using pin number
  • First time, the connection is perfectly working.
  • If smartphone is disconnected and connected back again with same equipment (Already bonded), then connection is stablished but smartphone disconnects after 30”, approximately. Same behavior is happening with both nRF connect application and our own application. Looking at log in nRF application we see: ‘Connection terminated by peer (status 19)’or ‘GATT_CONN_TIMEOUT’

 

Why is it happening?

Which is the reason?

How can we solve this?

 

 Could you help us? (For your information, we have set MIN_CONN_INTERVAL to 7.5m and MAX_CONN_INTERVAL to 100ms)

Thank you

Parents
  • Hi Daniel, 

    I got the update from Brian Kim about your email discussion. I agree with Brian that the sniffer trace would play a very important role here to solve the issue. I have some comments: 

    - Regarding the sniffer trace, I could see the communication because the link was encrypted. What you need to do is to either do Legacy pairing and use the sniffer to follow the initial bonding. Or use LESC but in debug mode. 

    - Another option you can try is to turn off bonding and encryption requirement to see if the issue is related to bonding or not. If the issue remain, please capture a sniffer trace. 

    - The disconnection happened at second 26th into the connection so it may not related to the 30seconds GAP/GATT timeout.

    - Please try to do a chip erase on the defected board and test again.

    - Please try to test using one of our example in the SDK, ble_app_proximity for example. 

  • Hi again,

    I have programmed one equipment turning bonding off, and then it is imposssible to connect (please, look at the attached screenshot with nRF Connect).

    In order to set it off, I set my variable 'BONDING_WITH_NO_CODE' to 1, and I have implement this in 'peer_manager_init' function:

    static void peer_manager_init(void)
    {
        ble_gap_sec_params_t sec_param;
        ret_code_t           err_code;
    
        err_code = pm_init();
        APP_ERROR_CHECK(err_code);
    
        memset(&sec_param, 0, sizeof(ble_gap_sec_params_t));
    
        // Security parameters to be used for all security procedures.
    		if(BONDING_WITH_NO_CODE)
    		{
    			sec_param.bond         = 0;    
    			sec_param.oob          = 0;
    			sec_param.mitm         = 0; 
    			sec_param.io_caps      = BLE_GAP_IO_CAPS_NONE;
    			sec_param.kdist_own.enc  = 0;
    			sec_param.kdist_own.id   = 0;
    			sec_param.kdist_peer.enc = 0;
    			sec_param.kdist_peer.id  = 0;
    		}
    		else
    		{
    			sec_param.bond           = SEC_PARAM_BOND;
    			sec_param.oob            = SEC_PARAM_OOB;
    			sec_param.mitm           = SEC_PARAM_MITM; //Static Key
    			sec_param.io_caps        = SEC_PARAM_IO_CAPABILITIES;    
    			sec_param.kdist_own.enc  = 1;
    			sec_param.kdist_own.id   = 1;
    			sec_param.kdist_peer.enc = 1;
    			sec_param.kdist_peer.id  = 1;
    		}
    		
            
        sec_param.lesc           = SEC_PARAM_LESC;
        sec_param.keypress       = SEC_PARAM_KEYPRESS;    
        sec_param.min_key_size   = SEC_PARAM_MIN_KEY_SIZE;
        sec_param.max_key_size   = SEC_PARAM_MAX_KEY_SIZE;
        
    
        err_code = pm_sec_params_set(&sec_param);
        APP_ERROR_CHECK(err_code);
    
        err_code = pm_register(pm_evt_handler);
        APP_ERROR_CHECK(err_code);
    }

    Furthermore, in this case, in all services, I proceed in the following way:

    if(BONDING_WITH_NO_CODE)
    {
    	BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.read_perm);
    	BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.write_perm);			
    }		
    else
    {
    	BLE_GAP_CONN_SEC_MODE_SET_ENC_WITH_MITM(&attr_md.read_perm);
    	BLE_GAP_CONN_SEC_MODE_SET_ENC_WITH_MITM(&attr_md.write_perm);
    }

    Hope to go ahead with the solution.

    Best regards,

    Dani.

  • Hi Hung,

    Could you also check my 'ble_evt_handler' function:

    static void delete_bonds(void)
    {
        ret_code_t err_code;   
    	
    		if(pm_peer_count()>8)
    		{
    			pm_peer_id_t peer_id_to_delete;
    			err_code = pm_peer_ranks_get(NULL,NULL,&peer_id_to_delete,NULL); //Bond més vell que no s'utilitza
    			APP_ERROR_CHECK(err_code);
    			err_code = pm_peer_delete(peer_id_to_delete);
    			APP_ERROR_CHECK(err_code);
    		}
    }
    
    static void ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context)
    {
        ret_code_t err_code;
    		u8 *p_ch_index;
    
        switch (p_ble_evt->header.evt_id)
        {
            case BLE_GAP_EVT_CONNECTED:
    					
                m_ble_general.ble_conn_handle = p_ble_evt->evt.gap_evt.conn_handle;				
    						err_code = nrf_ble_qwr_conn_handle_assign(&m_qwr, m_ble_general.ble_conn_handle);
                APP_ERROR_CHECK(err_code);
    				
    						//Long Range: 8dBm (Long Range)
    						err_code = sd_ble_gap_tx_power_set(BLE_GAP_TX_POWER_ROLE_CONN, m_ble_general.ble_conn_handle, 8);
    				
    						//App management
    						T_equip.Estat_canvi_PIN=AGR_PIN_NO_CHANGE;
    						T_equip.xTempsGestioPIN=0;	
    
    						//RSSI		
    						err_code = sd_ble_gap_rssi_start(p_ble_evt->evt.gap_evt.conn_handle, 10, 0);
                APP_ERROR_CHECK(err_code);
    						
                
                
                break;
    
            case BLE_GAP_EVT_DISCONNECTED:					
    					
    						NRF_LOG_INFO("Disconnected reason: %d.",p_ble_evt->evt.gap_evt.params.disconnected.reason);
    				
    						//Stop RSSI
    						sd_ble_gap_rssi_stop(p_ble_evt->evt.gap_evt.conn_handle);
    				
                
                            m_ble_general.ble_conn_handle = BLE_CONN_HANDLE_INVALID;
    						
    						//App management
    						m_ble_general.T_advertising.busy=NO;						
    				
    						//App management
    						if(T_equip.Estat_canvi_PIN==AGR_PIN_USER_CHANGE)
    						{
    							T_equip.Estat_canvi_PIN=AGR_PIN_NO_CHANGE;
    							u8 passkey[]="000000";
    							u32_to_ascii(ble_installer_configuracio_sortides_psw.password_app,passkey,XIFRES_PASSKEY); //Convertim el valor del password disponible a cadena de caràcters
    							m_static_pin_option.gap_opt.passkey.p_passkey = passkey;
    							err_code =  sd_ble_opt_set(BLE_GAP_OPT_PASSKEY, &m_static_pin_option);
    							APP_ERROR_CHECK(err_code);
    							T_equip.PIN_actual=ble_installer_configuracio_sortides_psw.password_app;
    						}
    						
    						else if(T_equip.Estat_canvi_PIN==AGR_PIN_FACTORY_CHANGE)
    						{
    							T_equip.Estat_canvi_PIN=AGR_PIN_WAITING_FACTORY_CONNECTION;
    							u8 passkey[]="000000";
    							u32_to_ascii(CodisActivacio(ID_CODI_PIN_APP),passkey,XIFRES_PASSKEY); //Convertim el valor del password DE FÀBRICA a cadena de caràcters
    							m_static_pin_option.gap_opt.passkey.p_passkey = passkey;
    							err_code =  sd_ble_opt_set(BLE_GAP_OPT_PASSKEY, &m_static_pin_option);
    							APP_ERROR_CHECK(err_code);
    							T_equip.PIN_actual=CodisActivacio(ID_CODI_PIN_APP);
    							T_equip.xTempsGestioPIN=TEMPS_MAXIM_CANVI_PIN;
    						}
    						
    						
    						else
    						{
    							if(T_equip.PIN_actual==CodisActivacio(ID_CODI_PIN_APP))
    							{
    					
    								if(T_equip.PIN_actual!=ble_installer_configuracio_sortides_psw.password_app)
    								{
    									u8 passkey[]="000000";
    									u32_to_ascii(ble_installer_configuracio_sortides_psw.password_app,passkey,XIFRES_PASSKEY); //Convertim el valor del password disponible a cadena de caràcters
    									m_static_pin_option.gap_opt.passkey.p_passkey = passkey;
    									err_code =  sd_ble_opt_set(BLE_GAP_OPT_PASSKEY, &m_static_pin_option);
    									APP_ERROR_CHECK(err_code);
    									T_equip.PIN_actual=ble_installer_configuracio_sortides_psw.password_app;	
    								}
    							}
    							
    							//Erase bonds if more than 8 are saved
    							delete_bonds();
    							
    						}
    							
                
                break;
    
    						
    				case BLE_GAP_EVT_TIMEOUT:
                
    					              
    
                m_ble_general.ble_conn_handle               = BLE_CONN_HANDLE_INVALID; //Això ens permetrà fer l'Advertising de forma periòdica mentre estem desconnectats.
    								
    						//App management
    						m_ble_general.T_advertising.busy=NO;								
    								
    								
    						
                
            break;
    						
    				case BLE_GATTS_EVT_SYS_ATTR_MISSING:
                
    						err_code = sd_ble_gatts_sys_attr_set(p_ble_evt->evt.gap_evt.conn_handle, NULL, 0, 0);
                APP_ERROR_CHECK(err_code);
            break;
    						
            case BLE_GAP_EVT_PHY_UPDATE_REQUEST:
            {
                
                ble_gap_phys_t const phys =
                {
                    .rx_phys = BLE_GAP_PHY_AUTO,
                    .tx_phys = BLE_GAP_PHY_AUTO,
                };
                err_code = sd_ble_gap_phy_update(p_ble_evt->evt.gap_evt.conn_handle, &phys);
                APP_ERROR_CHECK(err_code);
            } break;
    				
    				
    				case BLE_GAP_EVT_DATA_LENGTH_UPDATE_REQUEST:
    					//sd_ble_gap_data_length_update(&(p_ble_evt->evt.gattc_evt));
    					sd_ble_gap_conn_param_update(p_ble_evt->evt.gap_evt.conn_handle, &p_ble_evt->evt.gap_evt.params.conn_param_update_request.conn_params);
    					break;
    
            case BLE_GATTC_EVT_TIMEOUT:
                // Disconnect on GATT Client timeout event.            
                err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gattc_evt.conn_handle,
                                                 BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
                APP_ERROR_CHECK(err_code);
    			m_ble_general.T_advertising.busy=SI; //App management
                break;
    
            case BLE_GATTS_EVT_TIMEOUT:						            
    						// Disconnect on GATT Server timeout event.            
                err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gatts_evt.conn_handle,
                                                 BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
                APP_ERROR_CHECK(err_code);
    						m_ble_general.T_advertising.busy=SI; //App management
    						
                break;
        
            case BLE_GAP_EVT_SEC_PARAMS_REQUEST:
                
                break;
            
            case BLE_GAP_EVT_AUTH_KEY_REQUEST:					
                
                break;
    
            case BLE_GAP_EVT_LESC_DHKEY_REQUEST:
    					
                
                break;
    
             case BLE_GAP_EVT_AUTH_STATUS:
                //App management
    						if(p_ble_evt->evt.gap_evt.params.auth_status.auth_status!= BLE_GAP_SEC_STATUS_SUCCESS)
    						{								
    							sd_ble_gap_disconnect(m_ble_general.ble_conn_handle,BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
    							m_ble_general.T_advertising.busy=SI; //Per evitar que faci advertising fins que estigui desconnectat
    						}
                break;
    						
    						
    				 case BLE_GAP_SEC_STATUS_CONFIRM_VALUE:
    						//App management
    						sd_ble_gap_disconnect(m_ble_general.ble_conn_handle,BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
    						m_ble_general.T_advertising.busy=SI; //Per evitar que faci advertising fins que estigui desconnectat
    				 
    					 break;
    				
    				 //Guardem el valor de RSSI registrat		
    				 case BLE_GAP_EVT_RSSI_CHANGED:
    						C_equip.Nivell_RSSI = p_ble_evt->evt.gap_evt.params.rssi_changed.rssi;
    					  //sd_ble_gap_rssi_get(p_ble_evt->evt.gap_evt.conn_handle,&(C_equip.Nivell_RSSI),p_ch_index);
    						
    					 break;
    				 
    				 case BLE_GATTC_EVT_HVX:
    					 sd_ble_gattc_hv_confirm(p_ble_evt->evt.gap_evt.conn_handle, p_ble_evt->evt.gattc_evt.params.hvx.handle);
    						break;
    
            default:
                // No implementation needed.
                break;
        }
    }

    And the 'pm_evt_handler' function:

    static void pm_evt_handler(pm_evt_t const * p_evt)
    {
        ret_code_t err_code;
    	
    		pm_conn_sec_config_t config; 
    		pm_conn_sec_status_t conn_sec_status;							   
     
    		pm_handler_on_pm_evt(p_evt);
    		pm_handler_disconnect_on_sec_failure(p_evt);									  
        pm_handler_flash_clean(p_evt);
    
        switch (p_evt->evt_id)
        {
    			
    				case PM_EVT_CONN_SEC_SUCCEEDED:						
    
              // Check if the link is authenticated (meaning at least MITM).
              err_code = pm_conn_sec_status_get(p_evt->conn_handle, &conn_sec_status);
              APP_ERROR_CHECK(err_code);
    					
    					break;
    				
    				case PM_EVT_CONN_SEC_FAILED:
    						m_ble_general.ble_conn_handle = BLE_CONN_HANDLE_INVALID;						
    					break;
    
                    case PM_EVT_PEERS_DELETE_SUCCEEDED:
    
                        break;
    				
    				case PM_EVT_CONN_SEC_CONFIG_REQ:
    					config.allow_repairing = true;
    					pm_conn_sec_config_reply(p_evt->conn_handle, &config);
    						break;
    				
    				case PM_EVT_BONDED_PEER_CONNECTED:
    					pm_local_database_has_changed(); 
    			
    						break;
    				
    				
    				case PM_EVT_CONN_SEC_PARAMS_REQ:
    					pm_conn_sec_params_reply(p_evt->conn_handle,NULL,NULL);
    						break;
    				
    	
    
            default:
                break;
        }
    }

    Dani

  • Hi Hung,

    What about my last questions?

    Regards,

    Dani

  • Hi Daniel, 

    Sorry for the late answer we have another public holiday last week. 

    When you set bond = 0 the peers will not exchange/store bond information and every time they connect it's like connect to a new device, hence new pairing. 

    I'm not so sure why you got GATT INSUF AUTHORIZATION as it's not related to the process. Unless you have a change in attribute table (for example you add or remove a service/characteristic etc)

    If you do : 

    SEC_PARAM_LESC=0
    sec_param.mitm = 0;
    sec_param.io_caps = BLE_GAP_IO_CAPS_NONE;

    Would the issue disappear ? 

    You don't really have to implement handle for PM_EVT_CONN_SEC_PARAMS_REQ , if pm_conn_sec_params_reply() is not called the default sec param configuration (in your main.c) will be used.

    Regarding your code, I noticed this: 

     BLE_GAP_SEC_STATUS_CONFIRM_VALUE is not an event, please remove the code that handle it. 

    Inside BLE_GATTC_EVT_HVX: This event is for both notification and indication (from the phoen) If you don't do indication, you should not call sd_ble_gattc_hv_confirm() and you may want to check which attribute handle it addresses to make sure if the notification/indication is to your characteristic. 

    As I mentioned, please try to reduce your functionality to narrow down where the issue can be. 

  • Also if you do SEC_PARAM_LESC=0 and MITM=1, (legacy pairing with passkey) I assume you still see the error ? 


    If it's the case, please use the sniffer and track the connection, you would need to input the passkey into "Legacy Passkey" .

    I tested here and it is more reliable than the SC LTK option that I suggested earlier. 

  • Hi Hung,

    As you suggested, if I do:

    SEC_PARAM_LESC=0

    sec_param.mitm=0

    sec_param.io_caps = BLE_GAP_IO_CAPS_NONE

    , then the issue disappears: I'm asked (As normal) every time to pair, but device connects without problems.

    I have also removed BLE_GATTC_EVT_HVX implementation.

    Furthermore, I have saved a trace taking into account following parameters:

    sec_param.bond           = 1;
    sec_param.oob            = 0;
    sec_param.mitm           = 1; //Static Key
    sec_param.io_caps        = SEC_PARAM_IO_CAPABILITIES;    						
    sec_param.kdist_own.enc  = 1;
    sec_param.kdist_own.id   = 1;
    sec_param.kdist_peer.enc = 1;
    sec_param.kdist_peer.id  = 1;
    
    		
            
    sec_param.lesc           = 0;
    sec_param.keypress       = 0;    
    sec_param.min_key_size   = 7;
    sec_param.max_key_size   = 16;

    And I have done the test with my equipment #A and two smartphone devices:

    - Device #1: Xiaomi Mi8

    - Device #2:  Samsung Galaxy TabA SM-T580

    Before starting testing I have desincrhonized my equipment #A from both Smartphone and Tablet.

    Then, these are the steps I have followed, that are all saved in the attached trace:

    • Wireshark: I have entered the key for my equipment #A: 6-digit pin code to start saving the trace
    • Using nRF Connect from Device #1:
      • I have connected to the equipment #A
      • I have been asked to enter the code
      • Connection is stablished and does not disconnect
    • I have manualy disconnected the equipment #A from Device #1 (disconnect option in nRF Tool): equipment #A starts advertising again
    • I have proceeded in the same way with Device #2:
      • I have connected to the equipment #A
      • I have been asked to enter the code
      • Connection is stablished and does not disconnect
    • I have manualy disconnected the equipment #A from Device #2 (disconnect option in nRF Tool): equipment #A starts advertising again
    • I have taken the Device #1 again and I have selected 'Connect' to the same equipment #A:
      • It connects (bonding already done before) but:
        • It disconnects after about 30"
        • Looking at the trace, the 'bad MIC' message has appeared this time
    • I have stopped saving the trace at this point

    This full sequence is provided in the attached trace.

    Hope it helps to find out the reason of this disconnection.

    Regards,

    DaniAndroid_pairing_30_05_22.pcapng

Reply
  • Hi Hung,

    As you suggested, if I do:

    SEC_PARAM_LESC=0

    sec_param.mitm=0

    sec_param.io_caps = BLE_GAP_IO_CAPS_NONE

    , then the issue disappears: I'm asked (As normal) every time to pair, but device connects without problems.

    I have also removed BLE_GATTC_EVT_HVX implementation.

    Furthermore, I have saved a trace taking into account following parameters:

    sec_param.bond           = 1;
    sec_param.oob            = 0;
    sec_param.mitm           = 1; //Static Key
    sec_param.io_caps        = SEC_PARAM_IO_CAPABILITIES;    						
    sec_param.kdist_own.enc  = 1;
    sec_param.kdist_own.id   = 1;
    sec_param.kdist_peer.enc = 1;
    sec_param.kdist_peer.id  = 1;
    
    		
            
    sec_param.lesc           = 0;
    sec_param.keypress       = 0;    
    sec_param.min_key_size   = 7;
    sec_param.max_key_size   = 16;

    And I have done the test with my equipment #A and two smartphone devices:

    - Device #1: Xiaomi Mi8

    - Device #2:  Samsung Galaxy TabA SM-T580

    Before starting testing I have desincrhonized my equipment #A from both Smartphone and Tablet.

    Then, these are the steps I have followed, that are all saved in the attached trace:

    • Wireshark: I have entered the key for my equipment #A: 6-digit pin code to start saving the trace
    • Using nRF Connect from Device #1:
      • I have connected to the equipment #A
      • I have been asked to enter the code
      • Connection is stablished and does not disconnect
    • I have manualy disconnected the equipment #A from Device #1 (disconnect option in nRF Tool): equipment #A starts advertising again
    • I have proceeded in the same way with Device #2:
      • I have connected to the equipment #A
      • I have been asked to enter the code
      • Connection is stablished and does not disconnect
    • I have manualy disconnected the equipment #A from Device #2 (disconnect option in nRF Tool): equipment #A starts advertising again
    • I have taken the Device #1 again and I have selected 'Connect' to the same equipment #A:
      • It connects (bonding already done before) but:
        • It disconnects after about 30"
        • Looking at the trace, the 'bad MIC' message has appeared this time
    • I have stopped saving the trace at this point

    This full sequence is provided in the attached trace.

    Hope it helps to find out the reason of this disconnection.

    Regards,

    DaniAndroid_pairing_30_05_22.pcapng

Children
No Data
Related