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

Problem in jumping from application to bootloader

Dear team,

Device  - nRF52832
SDK - SDK_15.0.0
IDE - Segger Embedded studio
Softdevice - s132_nrf52_6.0.0

I am doing buttonless DFU in my application. I have successfully build the secure bootloader code and also jump from bootloader to application by following your guidelines.

The problem is that When i tried to jump from application to bootloader it causes "GATT connection timeout" error. I have seen this error in nrfconnect android application. 

But when i remove "CONFIG_AS_GPIO_PINRESET" macro in both codes bootloader and application then everything works perfectly. I don't want to remove this macro but want some another solution .

Please guide me on the same.
Your quick reply would be highly appreciated.

Thanks.  

Parents Reply Children
  • /**
     * Copyright (c) 2017 - 2018, Nordic Semiconductor ASA
     * 
     * All rights reserved.
     * 
     * Redistribution and use in source and binary forms, with or without modification,
     * are permitted provided that the following conditions are met:
     * 
     * 1. Redistributions of source code must retain the above copyright notice, this
     *    list of conditions and the following disclaimer.
     * 
     * 2. Redistributions in binary form, except as embedded into a Nordic
     *    Semiconductor ASA integrated circuit in a product or a software update for
     *    such product, must reproduce the above copyright notice, this list of
     *    conditions and the following disclaimer in the documentation and/or other
     *    materials provided with the distribution.
     * 
     * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
     *    contributors may be used to endorse or promote products derived from this
     *    software without specific prior written permission.
     * 
     * 4. This software, with or without modification, must only be used with a
     *    Nordic Semiconductor ASA integrated circuit.
     * 
     * 5. Any software provided in binary form under this license must not be reverse
     *    engineered, decompiled, modified and/or disassembled.
     * 
     * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
     * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
     * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
     * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
     * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
     * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     * 
     */
    
    #include <stdint.h>
    #include <stdbool.h>
    #include <stddef.h>
    #include "nrf_dfu_ble_svci_bond_sharing.h"
    #include "nordic_common.h"
    #include "nrf_error.h"
    #include "ble_dfu.h"
    #include "nrf_log.h"
    #include "nrf_sdh_soc.h"
    #include "nrf_gpio.h"
    #include "nrf_delay.h"
    
    #if (!NRF_DFU_BLE_BUTTONLESS_SUPPORTS_BONDS)
    
    #define NRF_DFU_ADV_NAME_MAX_LENGTH     (20)
    
    
    void ble_dfu_buttonless_on_sys_evt(uint32_t, void * );
    uint32_t nrf_dfu_svci_vector_table_set(void);
    uint32_t nrf_dfu_svci_vector_table_unset(void);
    
    /**@brief Define functions for async interface to set new advertisement name for DFU mode.  */
    NRF_SVCI_ASYNC_FUNC_DEFINE(NRF_DFU_SVCI_SET_ADV_NAME, nrf_dfu_set_adv_name, nrf_dfu_adv_name_t);
    
    // Register SoC observer for the Buttonless Secure DFU service
    NRF_SDH_SOC_OBSERVER(m_dfu_buttonless_soc_obs, BLE_DFU_SOC_OBSERVER_PRIO, ble_dfu_buttonless_on_sys_evt, NULL);
    
    ble_dfu_buttonless_t      * mp_dfu = NULL;
    static nrf_dfu_adv_name_t   m_adv_name;
    
    //extern bool ResetPinDisable;
    
    
    /**@brief Function for setting an advertisement name.
     *
     * @param[in]   adv_name    The new advertisement name.
     *
     * @retval NRF_SUCCESS      Advertisement name was successfully set.
     * @retval DFU_RSP_BUSY     Advertisement name was not set because of an ongoing operation.
     * @retval Any other errors from the SVCI interface call.
     */
    static uint32_t set_adv_name(nrf_dfu_adv_name_t * p_adv_name)
    {
        uint32_t err_code;
    
        if (mp_dfu->is_waiting_for_svci)
        {
            return DFU_RSP_BUSY;
        }
    
        err_code = nrf_dfu_set_adv_name(p_adv_name);
        if (err_code == NRF_SUCCESS)
        {
            // The request was accepted.
            mp_dfu->is_waiting_for_svci = true;
        }
        else if (err_code == NRF_ERROR_FORBIDDEN)
        {
            NRF_LOG_ERROR("The bootloader has write protected its settings page. This prohibits setting the advertising name. "\
                          "The bootloader must be compiled with NRF_BL_SETTINGS_PAGE_PROTECT=0 to allow setting the advertising name.");
        }
    
        return err_code;
    }
    
    
    /**@brief Function for entering the bootloader.
     */
    static uint32_t enter_bootloader()
    {
        uint32_t err_code;
    
        if (mp_dfu->is_waiting_for_svci)
        {
            // We have an ongoing async operation. Entering bootloader mode is not possible at this time.
            err_code = ble_dfu_buttonless_resp_send(DFU_OP_ENTER_BOOTLOADER, DFU_RSP_BUSY);
            if (err_code != NRF_SUCCESS)
            {
                mp_dfu->evt_handler(BLE_DFU_EVT_RESPONSE_SEND_ERROR);
    
            }
            
            return NRF_SUCCESS;
        }
    
        // Set the flag indicating that we expect DFU mode.
        // This will be handled on acknowledgement of the characteristic indication.
        mp_dfu->is_waiting_for_reset = true;
    
        err_code = ble_dfu_buttonless_resp_send(DFU_OP_ENTER_BOOTLOADER, DFU_RSP_SUCCESS);
        if (err_code != NRF_SUCCESS)
        {
            mp_dfu->is_waiting_for_reset = false;
        }
        
        return err_code;
    }
    
    
    uint32_t ble_dfu_buttonless_backend_init(ble_dfu_buttonless_t * p_dfu)
    {
        VERIFY_PARAM_NOT_NULL(p_dfu);
    
        mp_dfu = p_dfu;
    
        return NRF_SUCCESS;
    }
    
    
    uint32_t ble_dfu_buttonless_async_svci_init(void)
    {
        uint32_t ret_val;
    
        ret_val = nrf_dfu_svci_vector_table_set();
        VERIFY_SUCCESS(ret_val);
    
        ret_val = nrf_dfu_set_adv_name_init();
        VERIFY_SUCCESS(ret_val);
    
        ret_val = nrf_dfu_svci_vector_table_unset();
    
        return ret_val;
    }
    
    
    void ble_dfu_buttonless_on_sys_evt(uint32_t sys_evt, void * p_context)
    {
        uint32_t err_code;
    
        if (!nrf_dfu_set_adv_name_is_initialized())
        {
            return;
        }
    
        err_code = nrf_dfu_set_adv_name_on_sys_evt(sys_evt);
        if (err_code == NRF_ERROR_INVALID_STATE)
        {
            // The system event is not from an operation started by buttonless DFU.
            // No action is taken, and nothing is reported.
        }
        else if (err_code == NRF_SUCCESS)
        {
            // The async operation is finished.
            // Set the flag indicating that we are waiting for indication response
            // to activate the reset.
            mp_dfu->is_waiting_for_svci = false;
    
            // Report back the positive response
            err_code = ble_dfu_buttonless_resp_send(DFU_OP_SET_ADV_NAME, DFU_RSP_SUCCESS);
            if (err_code != NRF_SUCCESS)
            {
                mp_dfu->evt_handler(BLE_DFU_EVT_RESPONSE_SEND_ERROR);
            }
        }
        else
        {
            // Invalid error code reported back.
            mp_dfu->is_waiting_for_svci = false;
    
            err_code = ble_dfu_buttonless_resp_send(DFU_OP_SET_ADV_NAME, DFU_RSP_BUSY);
            if (err_code != NRF_SUCCESS)
            {
                mp_dfu->evt_handler(BLE_DFU_EVT_RESPONSE_SEND_ERROR);
            }
    
            // Report the failure to enter DFU mode
            mp_dfu->evt_handler(BLE_DFU_EVT_BOOTLOADER_ENTER_FAILED);
        }
    }
    
    
    uint32_t ble_dfu_buttonless_char_add(ble_dfu_buttonless_t * p_dfu)
    {
        ble_gatts_char_md_t char_md         = {{0}};
        ble_gatts_attr_md_t cccd_md         = {{0}};
        ble_gatts_attr_t    attr_char_value = {0};
        ble_gatts_attr_md_t attr_md         = {{0}};
        ble_uuid_t          char_uuid;
    
    
        BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.read_perm);
        BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.write_perm);
    
        cccd_md.vloc = BLE_GATTS_VLOC_STACK;
    
        char_md.char_props.indicate     = 1;
        char_md.char_props.write        = 1;
        char_md.p_char_user_desc        = NULL;
        char_md.p_char_pf               = NULL;
        char_md.p_user_desc_md          = NULL;
        char_md.p_cccd_md               = &cccd_md;
        char_md.p_sccd_md               = NULL;
    
        char_uuid.type = p_dfu->uuid_type;
        char_uuid.uuid = BLE_DFU_BUTTONLESS_CHAR_UUID;
    
        BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.read_perm);
        BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.write_perm);
    
        attr_md.vloc    = BLE_GATTS_VLOC_STACK;
        attr_md.rd_auth = 0;
        attr_md.wr_auth = 1;
        attr_md.vlen    = 1;
    
        attr_char_value.p_uuid    = &char_uuid;
        attr_char_value.p_attr_md = &attr_md;
        attr_char_value.init_len  = 0;
        attr_char_value.init_offs = 0;
        attr_char_value.max_len   = BLE_GATT_ATT_MTU_DEFAULT;
        attr_char_value.p_value   = 0;
    
        return sd_ble_gatts_characteristic_add(p_dfu->service_handle,
                                               &char_md,
                                               &attr_char_value,
                                               &p_dfu->control_point_char);
    }
    
    
    void ble_dfu_buttonless_on_ctrl_pt_write(ble_gatts_evt_write_t const * p_evt_write)
    {
        uint32_t err_code;
        ble_dfu_buttonless_rsp_code_t rsp_code = DFU_RSP_OPERATION_FAILED;
    
        // Start executing the control point write operation
        /*lint -e415 -e416 -save "Out of bounds access"*/
        switch (p_evt_write->data[0])
        {
            case DFU_OP_ENTER_BOOTLOADER:
    //              nrf_gpio_cfg_output(29);
    //              nrf_gpio_pin_set(29);
    //              nrf_delay_ms(2000);
                  err_code = enter_bootloader();
               if (err_code == NRF_SUCCESS)
                {
                    rsp_code = DFU_RSP_SUCCESS;
                    //nrf_gpio_cfg_output(4);
                    //nrf_gpio_pin_set(4);
                    
                }
                else if (err_code == NRF_ERROR_BUSY)
                {
                    rsp_code = DFU_RSP_BUSY;
                    /*nrf_gpio_cfg_output(4);
                    nrf_gpio_pin_set(4);*/
                }
                //break;
    
            case DFU_OP_SET_ADV_NAME:
                if(    (p_evt_write->data[1] > NRF_DFU_ADV_NAME_MAX_LENGTH)
                    || (p_evt_write->data[1] == 0))
                {
                    // New advertisement name too short or too long.
                    rsp_code = DFU_RSP_ADV_NAME_INVALID;
                    
                }
                else
                {
                    memcpy(m_adv_name.name, &p_evt_write->data[2], p_evt_write->data[1]);
                    m_adv_name.len = p_evt_write->data[1];
                    err_code = set_adv_name(&m_adv_name);
                    if (err_code == NRF_SUCCESS)
                    {
                        rsp_code = DFU_RSP_SUCCESS;
                    }
                }
                break;
    
            default:
                rsp_code = DFU_RSP_OP_CODE_NOT_SUPPORTED;
                break;
        }
        /*lint -restore*/
    
    
        // Report back in case of error
        if (rsp_code != DFU_RSP_SUCCESS)
        {
            err_code = ble_dfu_buttonless_resp_send((ble_dfu_buttonless_op_code_t)p_evt_write->data[0], rsp_code);
            if (err_code != NRF_SUCCESS)
            {
                mp_dfu->evt_handler(BLE_DFU_EVT_RESPONSE_SEND_ERROR);
    
            }
            // Report the error to the main application
            mp_dfu->evt_handler(BLE_DFU_EVT_BOOTLOADER_ENTER_FAILED);
        }
    }
    
    uint32_t ble_dfu_buttonless_bootloader_start_prepare(void)
    {
        uint32_t err_code;
    
        
        //nrf_delay_ms(10);
    
        // Indicate to main app that DFU mode is starting.
        mp_dfu->evt_handler(BLE_DFU_EVT_BOOTLOADER_ENTER_PREPARE);
    
        err_code = ble_dfu_buttonless_bootloader_start_finalize();
        //ResetPinDisable = true;
        return err_code;
    
    }
    
    #endif // NRF_DFU_BOTTONLESS_SUPPORT_BOND
    
    /**
     * Copyright (c) 2017 - 2018, Nordic Semiconductor ASA
     * 
     * All rights reserved.
     * 
     * Redistribution and use in source and binary forms, with or without modification,
     * are permitted provided that the following conditions are met:
     * 
     * 1. Redistributions of source code must retain the above copyright notice, this
     *    list of conditions and the following disclaimer.
     * 
     * 2. Redistributions in binary form, except as embedded into a Nordic
     *    Semiconductor ASA integrated circuit in a product or a software update for
     *    such product, must reproduce the above copyright notice, this list of
     *    conditions and the following disclaimer in the documentation and/or other
     *    materials provided with the distribution.
     * 
     * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
     *    contributors may be used to endorse or promote products derived from this
     *    software without specific prior written permission.
     * 
     * 4. This software, with or without modification, must only be used with a
     *    Nordic Semiconductor ASA integrated circuit.
     * 
     * 5. Any software provided in binary form under this license must not be reverse
     *    engineered, decompiled, modified and/or disassembled.
     * 
     * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
     * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
     * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
     * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
     * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
     * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     * 
     */
    /* Attention!
     *  To maintain compliance with Nordic Semiconductor ASA's Bluetooth profile
     *  qualification listings, this section of source code must not be modified.
     */
    
    #include "ble_dfu.h"
    #include <string.h>
    #include "ble_hci.h"
    #include "sdk_macros.h"
    #include "ble_srv_common.h"
    #include "nrf_nvic.h"
    #include "nrf_sdm.h"
    #include "nrf_soc.h"
    #include "nrf_log.h"
    #include "nrf_dfu_ble_svci_bond_sharing.h"
    #include "nrf_bootloader_info.h"
    #include "nrf_svci_async_function.h"
    #include "nrf_pwr_mgmt.h"
    #include "peer_manager.h"
    #include "gatts_cache_manager.h"
    #include "peer_id.h"
    #include "nrf_gpio.h"
    #include "nrf_delay.h"
    
    #define MAX_CTRL_POINT_RESP_PARAM_LEN   3                           /**< Max length of the responses. */
    
    #define BLE_DFU_SERVICE_UUID            0xFE59                      /**< The 16-bit UUID of the Secure DFU Service. */
    
    static ble_dfu_buttonless_t             m_dfu;                      /**< Structure holding information about the Buttonless Secure DFU Service. */
    //extern bool ResetPinDisable;
    NRF_SDH_BLE_OBSERVER(m_dfus_obs, BLE_DFU_BLE_OBSERVER_PRIO, ble_dfu_buttonless_on_ble_evt, &m_dfu);
    
    /**@brief Function for handling write events to the Buttonless Secure DFU Service Service Control Point characteristic.
     *
     * @param[in]   p_evt_write   Write event received from the BLE stack.
     */
    static void on_ctrlpt_write(ble_gatts_evt_write_t const * p_evt_write)
    {
        uint32_t      err_code;
    
    
        ble_gatts_rw_authorize_reply_params_t write_authorize_reply;
        memset(&write_authorize_reply, 0, sizeof(write_authorize_reply));
    
        write_authorize_reply.type   = BLE_GATTS_AUTHORIZE_TYPE_WRITE;
    
        if (m_dfu.is_ctrlpt_indication_enabled)
        {
            write_authorize_reply.params.write.update      = 1;
            write_authorize_reply.params.write.gatt_status = BLE_GATT_STATUS_SUCCESS;
        }
        else
        {
            write_authorize_reply.params.write.gatt_status = DFU_RSP_CCCD_CONFIG_IMPROPER;
        }
    
        // Authorize the write request
        do {
            err_code = sd_ble_gatts_rw_authorize_reply(m_dfu.conn_handle, &write_authorize_reply);
        } while (err_code == NRF_ERROR_BUSY);
    
    
        if (write_authorize_reply.params.write.gatt_status != BLE_GATT_STATUS_SUCCESS)
        {
            return;
        }
    
        // Forward the write event to the Buttonless DFU module.
        ble_dfu_buttonless_on_ctrl_pt_write(p_evt_write);
    }
    
    
    /**@brief Write authorization request event handler.
     *
     * @details The write authorization request event handler is called when writing to the control point.
     *
     * @param[in]   p_ble_evt Event received from the BLE stack.
     */
    static void on_rw_authorize_req(ble_evt_t const * p_ble_evt)
    {
        if (p_ble_evt->evt.gatts_evt.conn_handle != m_dfu.conn_handle)
        {
            return;
        }
    
        const ble_gatts_evt_rw_authorize_request_t * p_auth_req =
            &p_ble_evt->evt.gatts_evt.params.authorize_request;
    
        if (
            (p_auth_req->type == BLE_GATTS_AUTHORIZE_TYPE_WRITE)                            &&
            (p_auth_req->request.write.handle == m_dfu.control_point_char.value_handle)     &&
            (p_auth_req->request.write.op != BLE_GATTS_OP_PREP_WRITE_REQ)                   &&
            (p_auth_req->request.write.op != BLE_GATTS_OP_EXEC_WRITE_REQ_NOW)               &&
            (p_auth_req->request.write.op != BLE_GATTS_OP_EXEC_WRITE_REQ_CANCEL)
           )
        {
            on_ctrlpt_write(&p_auth_req->request.write);
        }
    }
    
    
    /**@brief Connect event handler.
     *
     * @param[in]   p_ble_evt   Event received from the BLE stack.
     */
    static void on_connect(ble_evt_t const * p_ble_evt)
    {
        m_dfu.conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
    }
    
    
    /**@brief Disconnect event handler.
     *
     * @param[in]   p_ble_evt   Event received from the BLE stack.
     */
    static void on_disconnect(ble_evt_t const * p_ble_evt)
    {
        if (m_dfu.conn_handle != p_ble_evt->evt.gatts_evt.conn_handle)
        {
            return;
        }
    
        m_dfu.conn_handle = BLE_CONN_HANDLE_INVALID;
    }
    
    
    /**@brief Write event handler.
     *
     * @param[in]   p_ble_evt Event received from the BLE stack.
     */
    static void on_write(ble_evt_t const * p_ble_evt)
    {
        const ble_gatts_evt_write_t * p_evt_write = &p_ble_evt->evt.gatts_evt.params.write;
    
    //    nrf_gpio_cfg_output(29);
    //    nrf_gpio_pin_set(29);
    //    nrf_delay_ms(300);
    
        if (p_evt_write->handle != m_dfu.control_point_char.cccd_handle)
        {
            return;
        }
    
        if (p_evt_write->len == BLE_CCCD_VALUE_LEN)
        {
            // CCCD written, update indications state
             m_dfu.is_ctrlpt_indication_enabled = ble_srv_is_indication_enabled(p_evt_write->data);
             
             NRF_LOG_INFO("Received indication state %d",
                          m_dfu.is_ctrlpt_indication_enabled);
        }
    }
    
    
    /**@brief Function for handling the HVC events.
     *
     * @details Handles HVC events from the BLE stack.
     *
     * @param[in] p_ble_evt  Event received from the BLE stack.
     */
    static void on_hvc(ble_evt_t const * p_ble_evt)
    {
        uint32_t err_code;
        ble_gatts_evt_hvc_t const * p_hvc = &p_ble_evt->evt.gatts_evt.params.hvc;
    //    nrf_gpio_cfg_output(29);
    //    nrf_gpio_pin_set(29);
    //    nrf_delay_ms(300);
    
        if (p_hvc->handle == m_dfu.control_point_char.value_handle)
        {
    
            // Enter bootloader if we were waiting for reset after hvc indication confimation.
            if (m_dfu.is_waiting_for_reset)
            {
                err_code = ble_dfu_buttonless_bootloader_start_prepare();
                if (err_code != NRF_SUCCESS)
                {
                    m_dfu.evt_handler(BLE_DFU_EVT_BOOTLOADER_ENTER_FAILED);
                }
            }
        }
    }
    
    
    void ble_dfu_buttonless_on_ble_evt(ble_evt_t const * p_ble_evt, void * p_context)
    {
        VERIFY_PARAM_NOT_NULL_VOID(p_ble_evt);
    
        switch (p_ble_evt->header.evt_id)
        {
            case BLE_GAP_EVT_CONNECTED:
                on_connect(p_ble_evt);
                break;
    
            case BLE_GAP_EVT_DISCONNECTED:
                on_disconnect(p_ble_evt);
                break;
    
            case BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST:
    
                on_rw_authorize_req(p_ble_evt);
                break;
    
            case BLE_GATTS_EVT_WRITE:
    
                on_write(p_ble_evt);
                break;
    
            case BLE_GATTS_EVT_HVC:
    
                on_hvc(p_ble_evt);
                break;
    
            default:
                // no implementation
                break;
        }
    }
    
    
    uint32_t ble_dfu_buttonless_resp_send(ble_dfu_buttonless_op_code_t op_code, ble_dfu_buttonless_rsp_code_t rsp_code)
    {
        // Send notification
        uint32_t                err_code;
        const uint16_t          len = 3;
        uint16_t                hvx_len;
        uint8_t                 hvx_data[MAX_CTRL_POINT_RESP_PARAM_LEN];
        ble_gatts_hvx_params_t  hvx_params;
        
    
        memset(&hvx_params, 0, sizeof(hvx_params));
    
        hvx_len = len;
        hvx_data[0] = DFU_OP_RESPONSE_CODE;
        hvx_data[1] = (uint8_t)op_code;
        hvx_data[2] = (uint8_t)rsp_code;
    
        hvx_params.handle   = m_dfu.control_point_char.value_handle;
        hvx_params.type     = BLE_GATT_HVX_INDICATION;
        hvx_params.offset   = 0;
        hvx_params.p_len    = &hvx_len;
        hvx_params.p_data   = hvx_data;
    
    
        err_code = sd_ble_gatts_hvx(m_dfu.conn_handle, &hvx_params);
        if ((err_code == NRF_SUCCESS) && (hvx_len != len))
        {
            err_code = NRF_ERROR_DATA_SIZE;
        }
    
        return err_code;
    }
    
    
    uint32_t ble_dfu_buttonless_bootloader_start_finalize(void)
    {
        uint32_t err_code;
    
        NRF_LOG_DEBUG("In ble_dfu_buttonless_bootloader_start_finalize\r\n");
        
    
        err_code = sd_power_gpregret_clr(0, 0xffffffff);
        VERIFY_SUCCESS(err_code);
    
      
        err_code = sd_power_gpregret_set(0, BOOTLOADER_DFU_START);
        VERIFY_SUCCESS(err_code);
    
        // Indicate that the Secure DFU bootloader will be entered
        m_dfu.evt_handler(BLE_DFU_EVT_BOOTLOADER_ENTER);
        
    //    nrf_gpio_pin_clear(4);
        // Signal that DFU mode is to be enter to the power management module
    
        
        
        nrf_pwr_mgmt_shutdown(NRF_PWR_MGMT_SHUTDOWN_GOTO_DFU);
        
        //NVIC_SystemReset();
        return NRF_SUCCESS;
    }
    
    
    uint32_t ble_dfu_buttonless_init(const ble_dfu_buttonless_init_t * p_dfu_init)
    {
        uint32_t        err_code;
        ble_uuid_t      service_uuid;
        ble_uuid128_t   nordic_base_uuid = BLE_NORDIC_VENDOR_BASE_UUID;
    
        VERIFY_PARAM_NOT_NULL(p_dfu_init);
    
        // Initialize the service structure.
        m_dfu.conn_handle                  = BLE_CONN_HANDLE_INVALID;
        m_dfu.evt_handler                  = p_dfu_init->evt_handler;
        m_dfu.is_waiting_for_reset         = false;
        m_dfu.is_ctrlpt_indication_enabled = false;
    
        err_code = ble_dfu_buttonless_backend_init(&m_dfu);
        VERIFY_SUCCESS(err_code);
        
        BLE_UUID_BLE_ASSIGN(service_uuid, BLE_DFU_SERVICE_UUID);
    
        // Add the DFU service declaration.
        err_code = sd_ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY,
                                            &service_uuid,
                                            &(m_dfu.service_handle));
    
        VERIFY_SUCCESS(err_code);
    
        // Add vendor specific base UUID to use with the Buttonless DFU characteristic.
        err_code = sd_ble_uuid_vs_add(&nordic_base_uuid, &m_dfu.uuid_type);
        VERIFY_SUCCESS(err_code);
    
        // Add the Buttonless DFU Characteristic (with bonds/without bonds).
        err_code = ble_dfu_buttonless_char_add(&m_dfu);
        VERIFY_SUCCESS(err_code);
    
        return NRF_SUCCESS;
    }
    
    Yes I am using custom board. I am attaching ble_dfu.c and ble_dfu_unbounded.c files of my application code. i have not make any changed in both files. One more thing , What is the need of making reset pin low during jumping from application to bootloader?

Related