Buttonless DFU (w/o bond) cannot enter from my application

Hi,

Have an issue which has popped up with our application. It is configured to use buttonless DFU for OTA updates. 

It's been working fine in the past but with a recent build, the app cannot enter the bootloader when instructed to it seems. 

The app uses pretty much all the example code from ble_app_buttonless_dfu/main.c to intialize the Buttonless DFU service. The device is also programmed with the bootloader from 

examples/dfu/secure_bootloader/pca10056_s140_ble. (both from NRF5 SDK v17.1.0).
Here is what the logs from nRF connect app on DEBUG show when I initiate a DFU update and pass it a .zip file. It seems to get stuck in some sort of loop, I think it looks like it finds the DFU target but then tries to connect and gets disconnected? I'm not really sure whats going on. 
 
nRF Connect, 2023-03-07
MYDEVICE E67E (E6:7E:D1:F5:4A:11)
V	21:13:16.584	[DFU] DFU service started
V	21:13:16.584	[DFU] Opening file...
I	21:13:16.599	[DFU] Firmware file opened successfully
V	21:13:16.599	[DFU] Connecting to DFU target...
D	21:13:16.599	[DFU] gatt = device.connectGatt(autoConnect = false, TRANSPORT_LE, preferredPhy = LE_1M | LE_2M)
I	21:13:16.614	[DFU] Connected to E6:7E:D1:F5:4A:11
V	21:13:16.614	[DFU] Discovering services...
D	21:13:16.614	[DFU] gatt.discoverServices()
I	21:13:16.617	[DFU] Services discovered
D	21:13:16.634	[DFU] wait(1000)
W	21:13:17.656	[DFU] Application with buttonless update found
V	21:13:17.657	[DFU] Jumping to the DFU Bootloader...
V	21:13:17.657	[DFU] Enabling indications for 8ec90003-f315-4f60-9fb8-838830daea50
D	21:13:17.657	[DFU] gatt.setCharacteristicNotification(8ec90003-f315-4f60-9fb8-838830daea50, true)
D	21:13:17.657	[DFU] gatt.writeDescriptor(00002902-0000-1000-8000-00805f9b34fb, value=0x02-00)
I	21:13:17.955	[DFU] Data written to descr.8ec90003-f315-4f60-9fb8-838830daea50, value (0x): 02-00
V	21:13:17.955	[DFU] Notifications enabled for 8ec90003-f315-4f60-9fb8-838830daea50
A	21:13:17.956	[DFU] Indications enabled
D	21:13:17.956	[DFU] wait(1000)
V	21:13:18.973	[DFU] Writing to characteristic 8ec90003-f315-4f60-9fb8-838830daea50
D	21:13:18.973	[DFU] gatt.writeCharacteristic(8ec90003-f315-4f60-9fb8-838830daea50)
D	21:13:28.113	[Callback] Connection state changed with status: 0 and new state: DISCONNECTED (0)
I	21:13:28.113	Disconnected
A	21:13:28.151	[DFU] Enter bootloader sent (Op Code = 1)
D	21:13:28.151	[DFU] gatt.refresh() (hidden)
D	21:13:28.151	[DFU] gatt.disconnect()
D	21:13:28.192	[DFU] gatt.close()
V	21:13:28.192	[DFU] Scanning for the DFU Bootloader... (timeout 5000 ms)
D	21:13:28.192	[Broadcast] Action received: android.bluetooth.device.action.ACL_DISCONNECTED
D	21:13:28.192	[DFU] [Broadcast] Action received: android.bluetooth.device.action.ACL_DISCONNECTED
I	21:13:28.416	[DFU] DFU Bootloader found with address E6:7E:D1:F5:4A:11
V	21:13:28.435	[DFU] DFU service started
I	21:13:28.435	[DFU] Firmware file opened successfully
D	21:13:28.435	[DFU] wait(1000)
D	21:13:29.436	[DFU] wait(1000)
V	21:13:30.450	[DFU] Connecting to DFU target...
D	21:13:30.452	[DFU] gatt = device.connectGatt(autoConnect = false, TRANSPORT_LE, preferredPhy = LE_1M | LE_2M)
D	21:13:31.028	[Broadcast] Action received: android.bluetooth.device.action.ACL_CONNECTED
D	21:13:31.045	[DFU] [Broadcast] Action received: android.bluetooth.device.action.ACL_CONNECTED
I	21:13:31.087	[DFU] Connected to E6:7E:D1:F5:4A:11
V	21:13:31.087	[DFU] Discovering services...
D	21:13:31.087	[DFU] gatt.discoverServices()
I	21:13:32.799	[DFU] Services discovered
D	21:13:32.812	[DFU] wait(1000)
W	21:13:33.817	[DFU] Application with buttonless update found
V	21:13:33.817	[DFU] Jumping to the DFU Bootloader...
V	21:13:33.817	[DFU] Enabling indications for 8ec90003-f315-4f60-9fb8-838830daea50
D	21:13:33.817	[DFU] gatt.setCharacteristicNotification(8ec90003-f315-4f60-9fb8-838830daea50, true)
D	21:13:33.820	[DFU] gatt.writeDescriptor(00002902-0000-1000-8000-00805f9b34fb, value=0x02-00)
I	21:13:33.868	[DFU] Data written to descr.8ec90003-f315-4f60-9fb8-838830daea50, value (0x): 02-00
V	21:13:33.868	[DFU] Notifications enabled for 8ec90003-f315-4f60-9fb8-838830daea50
A	21:13:33.868	[DFU] Indications enabled
D	21:13:33.868	[DFU] wait(1000)
V	21:13:34.875	[DFU] Writing to characteristic 8ec90003-f315-4f60-9fb8-838830daea50
D	21:13:34.875	[DFU] gatt.writeCharacteristic(8ec90003-f315-4f60-9fb8-838830daea50)
A	21:13:43.889	[DFU] Enter bootloader sent (Op Code = 1)
D	21:13:43.891	[DFU] gatt.refresh() (hidden)
D	21:13:43.895	[DFU] gatt.disconnect()
D	21:13:43.918	[DFU] gatt.close()
D	21:13:43.924	[Broadcast] Action received: android.bluetooth.device.action.ACL_DISCONNECTED
D	21:13:43.951	[DFU] [Broadcast] Action received: android.bluetooth.device.action.ACL_DISCONNECTED
V	21:13:43.952	[DFU] Scanning for the DFU Bootloader... (timeout 5000 ms)
I	21:13:44.200	[DFU] DFU Bootloader found with address E6:7E:D1:F5:4A:11
V	21:13:44.212	[DFU] DFU service started
I	21:13:44.212	[DFU] Firmware file opened successfully
D	21:13:44.212	[DFU] wait(1000)
D	21:13:45.212	[DFU] wait(1000)
V	21:13:46.225	[DFU] Connecting to DFU target...
D	21:13:46.271	[DFU] gatt = device.connectGatt(autoConnect = false, TRANSPORT_LE, preferredPhy = LE_1M | LE_2M)
D	21:13:46.789	[Broadcast] Action received: android.bluetooth.device.action.ACL_CONNECTED
D	21:13:46.833	[DFU] [Broadcast] Action received: android.bluetooth.device.action.ACL_CONNECTED
I	21:13:46.833	[DFU] Connected to E6:7E:D1:F5:4A:11
V	21:13:46.833	[DFU] Discovering services...
D	21:13:46.833	[DFU] gatt.discoverServices()
I	21:13:48.561	[DFU] Services discovered
D	21:13:48.580	[DFU] wait(1000)
W	21:13:49.578	[DFU] Application with buttonless update found
V	21:13:49.578	[DFU] Jumping to the DFU Bootloader...
V	21:13:49.578	[DFU] Enabling indications for 8ec90003-f315-4f60-9fb8-838830daea50
D	21:13:49.578	[DFU] gatt.setCharacteristicNotification(8ec90003-f315-4f60-9fb8-838830daea50, true)
D	21:13:49.579	[DFU] gatt.writeDescriptor(00002902-0000-1000-8000-00805f9b34fb, value=0x02-00)
I	21:13:49.625	[DFU] Data written to descr.8ec90003-f315-4f60-9fb8-838830daea50, value (0x): 02-00
V	21:13:49.625	[DFU] Notifications enabled for 8ec90003-f315-4f60-9fb8-838830daea50
A	21:13:49.625	[DFU] Indications enabled
D	21:13:49.625	[DFU] wait(1000)
V	21:13:50.647	[DFU] Writing to characteristic 8ec90003-f315-4f60-9fb8-838830daea50
D	21:13:50.647	[DFU] gatt.writeCharacteristic(8ec90003-f315-4f60-9fb8-838830daea50)
A	21:13:59.649	[DFU] Enter bootloader sent (Op Code = 1)
D	21:13:59.652	[DFU] gatt.refresh() (hidden)
D	21:13:59.655	[DFU] gatt.disconnect()
D	21:13:59.678	[DFU] gatt.close()
D	21:13:59.684	[Broadcast] Action received: android.bluetooth.device.action.ACL_DISCONNECTED
D	21:13:59.703	[DFU] [Broadcast] Action received: android.bluetooth.device.action.ACL_DISCONNECTED
V	21:13:59.707	[DFU] Scanning for the DFU Bootloader... (timeout 5000 ms)
I	21:14:00.225	[DFU] DFU Bootloader found with address E6:7E:D1:F5:4A:11
V	21:14:00.246	[DFU] DFU service started
I	21:14:00.246	[DFU] Firmware file opened successfully
D	21:14:00.246	[DFU] wait(1000)
D	21:14:01.246	[DFU] wait(1000)
V	21:14:02.263	[DFU] Connecting to DFU target...
D	21:14:02.266	[DFU] gatt = device.connectGatt(autoConnect = false, TRANSPORT_LE, preferredPhy = LE_1M | LE_2M)
D	21:14:02.818	[Broadcast] Action received: android.bluetooth.device.action.ACL_CONNECTED
D	21:14:02.838	[DFU] [Broadcast] Action received: android.bluetooth.device.action.ACL_CONNECTED
I	21:14:02.888	[DFU] Connected to E6:7E:D1:F5:4A:11
V	21:14:02.888	[DFU] Discovering services...
D	21:14:02.888	[DFU] gatt.discoverServices()
I	21:14:04.592	[DFU] Services discovered
D	21:14:04.615	[DFU] wait(1000)
W	21:14:05.606	[DFU] Application with buttonless update found
V	21:14:05.606	[DFU] Jumping to the DFU Bootloader...
V	21:14:05.606	[DFU] Enabling indications for 8ec90003-f315-4f60-9fb8-838830daea50
D	21:14:05.606	[DFU] gatt.setCharacteristicNotification(8ec90003-f315-4f60-9fb8-838830daea50, true)
D	21:14:05.606	[DFU] gatt.writeDescriptor(00002902-0000-1000-8000-00805f9b34fb, value=0x02-00)
I	21:14:05.634	[DFU] Data written to descr.8ec90003-f315-4f60-9fb8-838830daea50, value (0x): 02-00
V	21:14:05.634	[DFU] Notifications enabled for 8ec90003-f315-4f60-9fb8-838830daea50
A	21:14:05.634	[DFU] Indications enabled
D	21:14:05.634	[DFU] wait(1000)
V	21:14:06.658	[DFU] Writing to characteristic 8ec90003-f315-4f60-9fb8-838830daea50
D	21:14:06.658	[DFU] gatt.writeCharacteristic(8ec90003-f315-4f60-9fb8-838830daea50)
A	21:14:15.665	[DFU] Enter bootloader sent (Op Code = 1)
D	21:14:15.673	[DFU] gatt.refresh() (hidden)
D	21:14:15.676	[DFU] gatt.disconnect()
D	21:14:15.691	[Broadcast] Action received: android.bluetooth.device.action.ACL_DISCONNECTED
D	21:14:15.718	[DFU] [Broadcast] Action received: android.bluetooth.device.action.ACL_DISCONNECTED
D	21:14:15.719	[DFU] gatt.close()
V	21:14:15.754	[DFU] Scanning for the DFU Bootloader... (timeout 5000 ms)
I	21:14:16.028	[DFU] DFU Bootloader found with address E6:7E:D1:F5:4A:11
V	21:14:16.044	[DFU] DFU service started
I	21:14:16.044	[DFU] Firmware file opened successfully
D	21:14:16.044	[DFU] wait(1000)
D	21:14:17.045	[DFU] wait(1000)
V	21:14:18.064	[DFU] Connecting to DFU target...
D	21:14:18.066	[DFU] gatt = device.connectGatt(autoConnect = false, TRANSPORT_LE, preferredPhy = LE_1M | LE_2M)
D	21:14:18.343	[Broadcast] Action received: android.bluetooth.device.action.ACL_CONNECTED
D	21:14:18.368	[DFU] [Broadcast] Action received: android.bluetooth.device.action.ACL_CONNECTED
I	21:14:18.371	[DFU] Connected to E6:7E:D1:F5:4A:11
V	21:14:18.403	[DFU] Discovering services...
D	21:14:18.403	[DFU] gatt.discoverServices()
I	21:14:20.143	[DFU] Services discovered
D	21:14:20.164	[DFU] wait(1000)
W	21:14:21.158	[DFU] Application with buttonless update found
V	21:14:21.158	[DFU] Jumping to the DFU Bootloader...
V	21:14:21.158	[DFU] Enabling indications for 8ec90003-f315-4f60-9fb8-838830daea50
D	21:14:21.158	[DFU] gatt.setCharacteristicNotification(8ec90003-f315-4f60-9fb8-838830daea50, true)
D	21:14:21.158	[DFU] gatt.writeDescriptor(00002902-0000-1000-8000-00805f9b34fb, value=0x02-00)
I	21:14:21.212	[DFU] Data written to descr.8ec90003-f315-4f60-9fb8-838830daea50, value (0x): 02-00
V	21:14:21.212	[DFU] Notifications enabled for 8ec90003-f315-4f60-9fb8-838830daea50
A	21:14:21.212	[DFU] Indications enabled
D	21:14:21.212	[DFU] wait(1000)
V	21:14:22.229	[DFU] Writing to characteristic 8ec90003-f315-4f60-9fb8-838830daea50
D	21:14:22.229	[DFU] gatt.writeCharacteristic(8ec90003-f315-4f60-9fb8-838830daea50)
A	21:14:31.232	[DFU] Enter bootloader sent (Op Code = 1)
D	21:14:31.235	[DFU] gatt.refresh() (hidden)
D	21:14:31.241	[DFU] gatt.disconnect()
D	21:14:31.262	[DFU] gatt.close()
D	21:14:31.276	[Broadcast] Action received: android.bluetooth.device.action.ACL_DISCONNECTED
D	21:14:31.293	[DFU] [Broadcast] Action received: android.bluetooth.device.action.ACL_DISCONNECTED
V	21:14:31.293	[DFU] Scanning for the DFU Bootloader... (timeout 5000 ms)
I	21:14:31.543	[DFU] DFU Bootloader found with address E6:7E:D1:F5:4A:11
V	21:14:31.583	[DFU] DFU service started
I	21:14:31.583	[DFU] Firmware file opened successfully
D	21:14:31.584	[DFU] wait(1000)
D	21:14:32.585	[DFU] wait(1000)
V	21:14:33.586	[DFU] Connecting to DFU target...
D	21:14:33.621	[DFU] gatt = device.connectGatt(autoConnect = false, TRANSPORT_LE, preferredPhy = LE_1M | LE_2M)
D	21:14:34.377	[Broadcast] Action received: android.bluetooth.device.action.ACL_CONNECTED
D	21:14:34.410	[DFU] [Broadcast] Action received: android.bluetooth.device.action.ACL_CONNECTED
I	21:14:34.449	[DFU] Connected to E6:7E:D1:F5:4A:11
V	21:14:34.449	[DFU] Discovering services...
D	21:14:34.449	[DFU] gatt.discoverServices()
I	21:14:36.151	[DFU] Services discovered
D	21:14:36.166	[DFU] wait(1000)
W	21:14:37.166	[DFU] Application with buttonless update found
V	21:14:37.167	[DFU] Jumping to the DFU Bootloader...
V	21:14:37.167	[DFU] Enabling indications for 8ec90003-f315-4f60-9fb8-838830daea50
D	21:14:37.167	[DFU] gatt.setCharacteristicNotification(8ec90003-f315-4f60-9fb8-838830daea50, true)
D	21:14:37.171	[DFU] gatt.writeDescriptor(00002902-0000-1000-8000-00805f9b34fb, value=0x02-00)
I	21:14:37.208	[DFU] Data written to descr.8ec90003-f315-4f60-9fb8-838830daea50, value (0x): 02-00
V	21:14:37.208	[DFU] Notifications enabled for 8ec90003-f315-4f60-9fb8-838830daea50
A	21:14:37.208	[DFU] Indications enabled
D	21:14:37.208	[DFU] wait(1000)
V	21:14:38.233	[DFU] Writing to characteristic 8ec90003-f315-4f60-9fb8-838830daea50
D	21:14:38.233	[DFU] gatt.writeCharacteristic(8ec90003-f315-4f60-9fb8-838830daea50)
A	21:14:47.231	[DFU] Enter bootloader sent (Op Code = 1)
D	21:14:47.235	[DFU] gatt.refresh() (hidden)
D	21:14:47.239	[DFU] gatt.disconnect()
D	21:14:47.248	[DFU] gatt.close()
D	21:14:47.264	[Broadcast] Action received: android.bluetooth.device.action.ACL_DISCONNECTED
D	21:14:47.283	[DFU] [Broadcast] Action received: android.bluetooth.device.action.ACL_DISCONNECTED
V	21:14:47.283	[DFU] Scanning for the DFU Bootloader... (timeout 5000 ms)
I	21:14:47.539	[DFU] DFU Bootloader found with address E6:7E:D1:F5:4A:11
V	21:14:47.548	[DFU] DFU service started
I	21:14:47.548	[DFU] Firmware file opened successfully
D	21:14:47.548	[DFU] wait(1000)
D	21:14:48.548	[DFU] wait(1000)
V	21:14:49.567	[DFU] Connecting to DFU target...
D	21:14:49.569	[DFU] gatt = device.connectGatt(autoConnect = false, TRANSPORT_LE, preferredPhy = LE_1M | LE_2M)
D	21:14:49.933	[Broadcast] Action received: android.bluetooth.device.action.ACL_CONNECTED
D	21:14:49.956	[DFU] [Broadcast] Action received: android.bluetooth.device.action.ACL_CONNECTED
I	21:14:50.006	[DFU] Connected to E6:7E:D1:F5:4A:11
V	21:14:50.006	[DFU] Discovering services...
D	21:14:50.006	[DFU] gatt.discoverServices()
E	21:14:54.557	[DFU] Disconnected
D	21:14:54.557	[DFU] gatt.refresh() (hidden)
D	21:14:54.560	[DFU] gatt.disconnect()
D	21:14:54.571	[DFU] gatt.close()
D	21:14:54.587	[Broadcast] Action received: android.bluetooth.device.action.ACL_DISCONNECTED
D	21:14:54.607	[DFU] wait(600)
D	21:14:54.607	[DFU] [Broadcast] Action received: android.bluetooth.device.action.ACL_DISCONNECTED
D	21:14:55.197	gatt.close()
D	21:14:55.207	wait(200)
V	21:14:55.410	Connecting to E6:7E:D1:F5:4A:11...
D	21:14:55.410	gatt = device.connectGatt(autoConnect = false, TRANSPORT_LE, preferred PHY = LE 1M)
D	21:14:55.813	[Broadcast] Action received: android.bluetooth.device.action.ACL_CONNECTED
D	21:14:55.848	[Callback] Connection state changed with status: 0 and new state: CONNECTED (2)
I	21:14:55.848	Connected to E6:7E:D1:F5:4A:11
V	21:14:55.849	Requesting new MTU...
D	21:14:55.849	gatt.requestMtu(517)
I	21:14:56.402	Connection parameters updated (interval: 15.0ms, latency: 0, timeout: 4000ms)
I	21:14:56.429	PHY updated (TX: LE 2M, RX: LE 2M)
D	21:15:00.420	[Callback] Connection state changed with status: 0 and new state: DISCONNECTED (0)
I	21:15:00.420	Disconnected
D	21:15:00.537	[Broadcast] Action received: android.bluetooth.device.action.ACL_DISCONNECTED
I'll try to post snippets that I think are relevant:
Connection parameters:
// Connection parameters
#define DEFAULT_MAX_CONN_INTERVAL MSEC_TO_UNITS(15, UNIT_1_25_MS)  /**< Default maximum acceptable connection interval on init, Connection interval uses 1.25 ms unorbs. */
#define SLAVE_LATENCY 0                                            /**< Slave latency. */
#define CONN_SUP_TIMEOUT MSEC_TO_UNITS(4000, UNIT_10_MS)           /**< Connection supervisory timeout, Supervision Timeout uses 10 ms unorbs. */
#define FIRST_CONN_PARAMS_UPDATE_DELAY APP_TIMER_TICKS(10)         /**< Delay before negotiation is initiated. */
#define NEXT_CONN_PARAMS_UPDATE_DELAY APP_TIMER_TICKS(10)          /**< Delay for subsequent request to be sent in case parameters are not updated as requested. */
#define MAX_CONN_PARAMS_UPDATE_COUNT 5                             /**< Number of attempts before giving up the connection parameter negotiation. */
#define CONNECTION_POWER 8                                         /**< Connection power in dB.                                      \
                                        Supported tx_power values: -40dBm, -20dBm, -16dBm, -12dBm, -8dBm, -4dBm, 0dBm, +2dBm, +3dBm, \
                                        +4dBm, +5dBm, +6dBm, +7dBm and +8dBm. */
DFU related fns and callbacks:
/**@brief Callback function for asserts in the SoftDevice.
 *
 * @details This function will be called in case of an assert in the SoftDevice.
 *
 * @warning This handler is an example only and does not fit a final product. You need to analyze
 *          how your product is supposed to react in case of Assert.
 * @warning On assert from the SoftDevice, the system can only recover on reset.
 *
 * @param[in] line_num   Line number of the failing ASSERT call.
 * @param[in] file_name  File name of the failing ASSERT call.
 */
void assert_nrf_callback(uint16_t line_num, const uint8_t *p_file_name)
{
    app_error_handler(0xDEADBEEF, line_num, p_file_name);
}

/**@brief Handler for shutdown preparation.
 *
 * @details During shutdown procedures, this function will be called at a 1 second interval
 *          untill the function returns true. When the function returns true, it means that the
 *          app is ready to reset to DFU mode.
 *
 * @param[in]   event   Power manager event.
 *
 * @retval  True if shutdown is allowed by this power manager handler, otherwise false.
 */
static bool _app_shutdown_handler(nrf_pwr_mgmt_evt_t event)
{
    switch (event)
    {
    case NRF_PWR_MGMT_EVT_PREPARE_DFU:
        NRF_LOG_INFO("Power management wants to reset to DFU mode.");
        // YOUR_JOB: Get ready to reset into DFU mode
        //
        // If you aren't finished with any ongoing tasks, return "false" to
        // signal to the system that reset is impossible at this stage.
        //
        // Here is an example using a variable to delay resetting the device.
        //
        // if (!m_ready_for_reset)
        // {
        //      return false;
        // }
        // else
        //{
        //
        //    // Device ready to enter
        //    uint32_t err_code;
        //    err_code = sd_softdevice_disable();
        //    APP_ERROR_CHECK(err_code);
        //    err_code = app_timer_stop_all();
        //    APP_ERROR_CHECK(err_code);
        //}
        break;

    default:
        // YOUR_JOB: Implement any of the other events available from the power management module:
        //      -NRF_PWR_MGMT_EVT_PREPARE_SYSOFF
        //      -NRF_PWR_MGMT_EVT_PREPARE_WAKEUP
        //      -NRF_PWR_MGMT_EVT_PREPARE_RESET
        return true;
    }

    NRF_LOG_INFO("Power management allowed to reset to DFU mode.");
    return true;
}

// lint -esym(528, m_app_shutdown_handler)
/**@brief Register application shutdown handler with priority 0.
 */
NRF_PWR_MGMT_HANDLER_REGISTER(_app_shutdown_handler, 0);

/* ===================================================================================================================== */
/* ==============================================  Connection State  =================================================== */
/* ===================================================================================================================== */

static void _disconnect(uint16_t conn_handle, void *p_context)
{
    UNUSED_PARAMETER(p_context);

    ret_code_t err_code = sd_ble_gap_disconnect(conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);

    if (err_code != NRF_SUCCESS)
    {
        NRF_LOG_ERROR("Failed to disconnect connection. Connection handle: %d Error: %d", conn_handle, err_code);
    }
    else
    {
        NRF_LOG_INFO("Disconnected connection handle %d", conn_handle);
    }

    led_blink(500, 4000);
}

/* ===================================================================================================================== */
/* =====================================================  DFU  ========================================================= */
/* ===================================================================================================================== */

// YOUR_JOB: Update this code if you want to do anything given a DFU event (optional).
/**@brief Function for handling dfu events from the Buttonless Secure DFU service
 *
 * @param[in]   event   Event from the Buttonless Secure DFU service.
 */
static void _ble_dfu_evt_handler(ble_dfu_buttonless_evt_type_t event)
{
    uint32_t conn_count;

    switch (event)
    {
    case BLE_DFU_EVT_BOOTLOADER_ENTER_PREPARE:
    {
        NRF_LOG_INFO("Device is preparing to enter bootloader mode.");

        // Prevent device from advertising on disconnect.
        advertising_disable_adv_on_disconnect();

        // Disconnect all other bonded devices that currently are connected.
        // This is required to receive a service changed indication
        // on bootup after a successful (or aborted) Device Firmware Update.
        conn_count = ble_conn_state_for_each_connected(_disconnect, NULL);
        NRF_LOG_INFO("Disconnected %d links.", conn_count);
        break;
    }

    case BLE_DFU_EVT_BOOTLOADER_ENTER:
        // YOUR_JOB: Write app-specific unwritten data to FLASH, control finalization of this
        //           by delaying reset by reporting false in app_shutdown_handler
        NRF_LOG_INFO("Device will enter bootloader mode.");
        break;

    case BLE_DFU_EVT_BOOTLOADER_ENTER_FAILED:
        NRF_LOG_ERROR("Request to enter bootloader mode failed asynchroneously.");
        // YOUR_JOB: Take corrective measures to resolve the issue
        //           like calling APP_ERROR_CHECK to reset the device.
        break;

    case BLE_DFU_EVT_RESPONSE_SEND_ERROR:
        NRF_LOG_ERROR("Request to send a response to client failed.");
        // YOUR_JOB: Take corrective measures to resolve the issue
        //           like calling APP_ERROR_CHECK to reset the device.
        APP_ERROR_CHECK(false);
        break;

    default:
        NRF_LOG_ERROR("Unknown event from ble_dfu_buttonless.");
        break;
    }
}

static void _buttonless_dfu_sdh_state_observer(nrf_sdh_state_evt_t state, void *p_context)
{
    if (state == NRF_SDH_EVT_STATE_DISABLED)
    {
        // Softdevice was disabled before going into reset. Inform bootloader to skip CRC on next boot.
        nrf_power_gpregret2_set(BOOTLOADER_DFU_SKIP_CRC);

        // Go to system off.
        nrf_pwr_mgmt_shutdown(NRF_PWR_MGMT_SHUTDOWN_GOTO_SYSOFF);
    }
}

/* nrf_sdh state observer. */
NRF_SDH_STATE_OBSERVER(m_buttonless_dfu_state_obs, 0) =
    {
        .handler = _buttonless_dfu_sdh_state_observer,
};
Init of DFU buttonless service:
ble_dfu_buttonless_init_t dfus_init = {0};
   
err_code = ble_dfu_buttonless_init(&dfus_init);
APP_ERROR_CHECK(err_code);
I'm not really sure where to begin to diagnose this issue. Hoping it's still possible to update these devices.
Parents
  • Hi savvn001,

    Could you please clarify what changed with "a recent build?"

    What hardware are you testing all of this on? Do you see the LEDs indicating bootloader operations?

    Do you have any logs from your application or the bootloader?

    Hieu

  • Hi, sorry I should of mentioned these:

    So with more recent builds, we only changed some app functionality but it should have basically nothing to do with the BLE interface, and especially not the DFU side of things. I'm like 90% sure of this. We especially did not touch any of the bluetooth related code.

    The hardware is a custom board we have made using nF52840.

    Unfortunately the logs from our application don't tell us much. So I've tried to recreate the issue by flashing an empty development board with the same bootloader + softdevice plus our application.

    When it initally advertises as DFU target, it can be updated perfectly fine. We can then connect perfectly fine to the application initially.

    Think I'm starting to see where the issue is, from the application when it is running, after enabling indications on the 'Buttonless DFU' characteristic, we write '0x01' to the characteristic which should put it in DFU mode (enter bootloader) right, the MCU just resets. Not sure if this is WDT reset or Softdevice assertation, no idea.

    As you can see in the code posted there should be a lot of logging going on before entering DFU but I can't see any of it. Soon as we write to 'Buttonless DFU' characteristic, it resets after ~2s.

  • Update:

    Ok, I've found the offending code. It does have nothing to do with the DFU related functions.

    There is a on_ble_evt callback being called on another service when I write to the 'Buttonless DFU' characteristic (as you know these callbacks get called whenver any ble event happens)

    It does a switch on (p_ble_evt->header.evt_id) and in the case BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST happens. There is a for loop that loops too many times and causes segfault under this case. So program crashes here. Silly mistake.

    This means effectively, the one that is flashed currently is probably bricked indefinitely for now as I don't know how one would get round this if reflashing the device with a probe is not possible. Lesson learned!

Reply
  • Update:

    Ok, I've found the offending code. It does have nothing to do with the DFU related functions.

    There is a on_ble_evt callback being called on another service when I write to the 'Buttonless DFU' characteristic (as you know these callbacks get called whenver any ble event happens)

    It does a switch on (p_ble_evt->header.evt_id) and in the case BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST happens. There is a for loop that loops too many times and causes segfault under this case. So program crashes here. Silly mistake.

    This means effectively, the one that is flashed currently is probably bricked indefinitely for now as I don't know how one would get round this if reflashing the device with a probe is not possible. Lesson learned!

Children
  • Hi savvn001,

    It's great that you found the offending code so quickly.

    If you can access the debug pins on the bricked device, you can just recover it by programming it with J-Link or an equivalent option; but my guess is that you already considered this.

    Another option to consider is: The secure bootloader supports other method to enter DFU mode. There is an overview with links in its documentation page. Perhaps you would want to check if any of those work before giving up? For example, if the button enter method is supported, and the hardware layout allows it, then a bit of handywork with a copper wire can put the device in DFU mode.

    Hieu

  • Hi Hieu,

    Unfortunately the device is sealed so it's fully not acessable at all by any means sadly. But it's luckily a throwaway for us and not something out in the field. So we have no way we can think of currently to get the device into DFU mode if a BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST event causes a crash, as that's the only way to enter DFU mode as far as I know. A button enter fallback method may be added in a future design.

  • Hi savvn001,

    I see. It certainly is good that it didn't happen in the field. Perhaps you might want to consider adding a reset button in the design, just in case?

    With devices hard to physically access like that, please make sure to test the DFU feature extensively. One important test case is that the device, after being upgraded with DFU, can still perform DFU successfully.

  • Definitely, we will be looking at it for a future design. It's an oversight in our current design.

    Indeed, testing being able to update again, after actually updating is something we're noting down as extremely important right now. Goes to show how minor changes elsewhere can affect things you don't think are related.

Related