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

Central device reboots on peripheral disconnect

I am building an application where a central device is controlled by only one remote control, which is a peripheral device (both nrf52 running S132 v3 softdevices and the v12.3 SDK). The central device has no external controls other than a charging port. When the user unplugs the charger, the central device is reset electronically.

For 10 seconds I want the central device to only accept it's single whitelisted peripheral, then for 10 seconds I want it to accept new peripherals, forget the old one and whitelist the new one. After 20 seconds it will accept no connections other than the whitelisted peripheral, or no connections if it has never had a peripheral assigned.

static void peer_list_get(pm_peer_id_t * p_peers, uint32_t * p_size)
{
pm_peer_id_t peers[BLE_GAP_WHITELIST_ADDR_MAX_COUNT];
pm_peer_id_t peer_id;
uint32_t     peers_to_copy;

memset(peers, PM_PEER_ID_INVALID, sizeof(peers));
peers_to_copy = (*p_size < BLE_GAP_WHITELIST_ADDR_MAX_COUNT) ?
                 *p_size : BLE_GAP_WHITELIST_ADDR_MAX_COUNT;

pm_peer_id_t highest_ranked;

ret_code_t err_code = pm_peer_ranks_get(&highest_ranked, NULL, NULL, NULL);

peer_id = pm_next_peer_id_get(PM_PEER_ID_INVALID);
*p_size = 0;

while ((peer_id != PM_PEER_ID_INVALID) && (peers_to_copy--))
{
    p_peers[(*p_size)++] = peer_id;

    if (err_code == NRF_SUCCESS){
    	if(peer_id != highest_ranked)
    	{
    		pm_peer_delete(peer_id);
    		(*p_size)--;
    	}
    }
    peer_id = pm_next_peer_id_get(peer_id);
  }
}

I call this function on startup to delete every peer except the highest ranked one, from whitelist_load(), which I am borrowing unmodified from various examples. This is how I disable the whitelist for the 10s - 20s period to allow new remotes to be connected.

The bool I pass to my scan_start function tells it whether or not to make a new whitelist or simply use the saved one. I only ever do this once, at startup (so the user has to bond the devices, then use the charger plug to reset the central again) to properly set the whitelist.

static void disableWhitelist(void * p_context)
  {
  sd_ble_gap_scan_stop();
m_whitelist_disabled = true;
scan_start(false);
app_timer_start(allowNewDevices, APP_TIMER_TICKS(ALLOW_NEW_DEVICES,  
     APP_TIMER_PRESCALER), NULL);
 }

I then re-enable it:

static void enableWhitelist(void * p_context)
{
sd_ble_gap_scan_stop();
m_whitelist_disabled = false;
scan_start(false);
}

This approach seems to work, except the central device restarts itself when it loses the peripheral connection, which causes the period where it will accept new connections to occur again. The only service I am running on the peripheral & central is the NUS service, which I use to transfer data and control the central device.

I'm really at a loss as to where to even begin looking for the cause of this behaviour.

Related