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

Problem with Eddystone adding DFU Service !

Hi,

I am working on Eddystone project, after I successfully tested the Buttonless DFU example, I added DFU service to Eddystone example (nRF5_SDK_17.0.0_9d13099\examples\ble_peripheral\ble_app_eddystone\pca10040\s132\ses) ,   I can scan and connect to the beacon via andriod mobile,  there are Secure DFU Service,  I enabled indications, then write value to reset the device to bootloader,  the following error occurred,

<info> app: Booting....

<info> app: Setting vector table to bootloader: 0x00078000

<info> app: Setting vector table to main app: 0x00026000

<info> app_timer: RTC: initialized.

<info> app: DFU service init.

<info> app: Eddystone Application started.

<info> app: sent non connectable_advertising.

<info> app: sent non connectable_advertising.

<error> app: ERROR 5 [NRF_ERROR_NOT_FOUND] at E:\Example\nRF5_SDK_17.0.0_9d13099\components\ble\ble_services\eddystone\nrf_ble_es.c:395

PC at: 0x0002FE0F

<error> app: End of error report.

I just add one file related to DFU service and modified main.c , set NRF_SDH_BLE_VS_UUID_COUNT to 1, Enable DUF in sdk_congfig.h, no other changes, attached please find the code, please help me find the problem, thank you very much.  

/**
 * @brief Function for application main entry.
 */
int main(void)
{
    // Initialize.

    log_init();
    NRF_LOG_INFO("Booting....");

    // Initialize the async SVCI interface to bootloader before any interrupts are enabled.
    uint32_t err_code;
    err_code = ble_dfu_buttonless_async_svci_init();  //add for DFU
    APP_ERROR_CHECK(err_code);

    timers_init();
    leds_init();
    button_init();
    scheduler_init();
    power_management_init();
    ble_stack_init();
    gap_params_init();
    gatt_init();
 
    dfu_services_init();   // add for DFU
    NRF_LOG_INFO("DFU service init.");  

    conn_params_init();
    nrf_ble_es_init(on_es_evt);
    NRF_LOG_INFO("Eddystone Application started.");



    // Enter main loop.
    for (;;)
    {
        
        if (!NRF_LOG_PROCESS()) {
           idle_state_handle();
        }
    }
}

#include <stdbool.h>
#include <stdint.h>
#include <string.h>
#include "sdk_config.h"
#include "bsp.h"
#include "nrf_dfu_ble_svci_bond_sharing.h"
#include "nrf_svci_async_function.h"
#include "nrf_svci_async_handler.h"

#include "nordic_common.h"
#include "nrf.h"
#include "app_error.h"
#include "ble.h"
#include "ble_hci.h"
#include "ble_srv_common.h"
#include "ble_advdata.h"
#include "ble_advertising.h"
#include "ble_conn_params.h"
#include "nrf_sdh.h"
#include "nrf_sdh_soc.h"
#include "nrf_sdh_ble.h"
#include "app_timer.h"
#include "peer_manager.h"
#include "peer_manager_handler.h"
#include "bsp_btn_ble.h"
#include "ble_hci.h"
#include "ble_conn_state.h"
#include "ble_dfu.h"
#include "nrf_ble_qwr.h"
#include "fds.h"
#include "nrf_pwr_mgmt.h"
#include "nrf_drv_clock.h"
#include "nrf_power.h"
#include "nrf_log_ctrl.h"
#include "nrf_log_default_backends.h"
#include "nrf_bootloader_info.h"
#include "nrf_log.h"

/* Private defines */

BLE_ADVERTISING_DEF(m_advertising);

/* Private function implementations */

/**@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);



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,
};




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_WARNING("Failed to disconnect connection. Connection handle: %d Error: %d", conn_handle, err_code);
    }
    else
    {
        NRF_LOG_DEBUG("Disconnected connection handle %d", conn_handle);
    }
}


#define APP_ADV_INTERVAL                300                                         /**< The advertising interval (in units of 0.625 ms. This value corresponds to 187.5 ms). */
#define APP_ADV_DURATION                18000                                       /**< The advertising duration (180 seconds) in units of 10 milliseconds. */


static void advertising_config_get(ble_adv_modes_config_t * p_config)
{
    memset(p_config, 0, sizeof(ble_adv_modes_config_t));

    p_config->ble_adv_fast_enabled  = true;
    p_config->ble_adv_fast_interval = APP_ADV_INTERVAL;
    p_config->ble_adv_fast_timeout  = APP_ADV_DURATION;
}



// 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)
{
    switch (event)
    {
        case BLE_DFU_EVT_BOOTLOADER_ENTER_PREPARE:

            NRF_LOG_INFO("Device is preparing to enter bootloader mode.");


            // YOUR_JOB: Disconnect all 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.

            // Prevent device from advertising on disconnect.

            ble_adv_modes_config_t config;
            advertising_config_get(&config);
            config.ble_adv_on_disconnect_disabled = true;
            ble_advertising_modes_config_set(&m_advertising, &config);

            // 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.
            uint32_t 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;
    }
}



/**@brief Function for initializing services that will be used by the application.
 */
void dfu_services_init(void)
{
     uint32_t err_code;

  
    ble_dfu_buttonless_init_t dfus_init =
    {
        .evt_handler = ble_dfu_evt_handler
    };


    err_code = ble_dfu_buttonless_init(&dfus_init);
    APP_ERROR_CHECK(err_code);

}



Parents Reply Children
  • ble_app_eddystone.zip1184.bootloader.zip

    Hello Einar,

    I have uploaded the complete modified project . The IDE  I use is SES, ignore the others.  Another, I uploaded the bootload hex which generated from <SDK> \examples\dfu\secure_bootloader\pca10040_s132_ble. 

    Looking forward your reply, thank you very much.

    Best regards,

    Susan

  • Hi Susan,

    This issue is because the eddystone implementation iterates through the UUIDs it implements when there is a GATTS operation in get_evt_type_for_handle(), and this returns NRF_ERROR_NOT_FOUND for any UUID not handled by the Eddystone implementation. It should be safe to ignore this as now you know you are supporting more services. You could do it more elegantly, but I do not immediately see any problem with simply ignoring this error, by modifying nrf_ble_es.c like this:

    diff --git a/components/ble/ble_services/eddystone/nrf_ble_es.c b/components/ble/ble_services/eddystone/nrf_ble_es.c
    index a1f2565..0be8c05 100644
    --- a/components/ble/ble_services/eddystone/nrf_ble_es.c
    +++ b/components/ble/ble_services/eddystone/nrf_ble_es.c
    @@ -392,7 +392,10 @@ void nrf_ble_es_on_ble_evt(ble_evt_t const * p_ble_evt, void * p_context)
     
         es_adv_on_ble_evt(p_ble_evt);
         err_code = nrf_ble_escs_on_ble_evt(&m_ble_ecs, p_ble_evt);
    -    APP_ERROR_CHECK(err_code);
    +    if (err_code != NRF_ERROR_NOT_FOUND)
    +    {
    +        APP_ERROR_CHECK(err_code);
    +    }
         on_ble_evt(p_ble_evt);
         es_flash_on_ble_evt(p_ble_evt);
     }
    

    Einar

  • Hi Einar,

    According to your suggestion, I have successfully upgraded, thank you very very much.

    Susan

Related