SDK13 Buttonless DFU Service doesnt change into Bootloader

dpa gravatar image

asked 2017-07-13 14:01:17 +0200

Hi to everybody,

I am working with a custom board based on the nrf52832, while trying to integrate to my existing application the DFU functionality I am having problems when I try to change from app to bootloader through Buttonless DFU Service.

I follow this steps:

(nrf Studio)

  • Erase chip.
  • Program SoftDevice (s132_nrf52_4.0.2_softdevice.hex)
  • Program my modified Bootloader based on bootloader_secure_ble example.

(nrfToolbox Android)

  • Download my application with Buttonless DFU Service Integrated.

(nrfConnect V2.0)

  • Discover my device and connect.
  • Scan Services (Buttolenss DFU Service is OK)
  • Subscribe for indications.
  • Write 0x01 into the characteristic.

When I follow this steps I see how the nrfConnect receives the indication from the device with "20-01-01" data and after that "Disconnected from device F7:91:6A:2B:B8:D8, reason: BLE_HCI_CONNECTION_TIMEOUT".

This leads to a reboot on the the device but it does not start into the bootloader, it starts the app. Why is not entering into the bootloader?

If I write into the Buttonless DFU Service characteristics any value that is not 0x01 I can see on my logs this messages:

:INF:ble_dfu_on_ble_evt --> Write

:INF:Received indication state 1, notification state 0 BLE:INF:Indication for BLE_DFU is enabled.

:INF:ble_dfu_on_ble_evt --> RW Authorize Req.

:INF:on_ctrlpt_write: indication enabled

:INF:on_ctrlpt_write: execute enter

:INF:sd_ble_gatts_hvx retval = 0

:INF:ble_dfu_on_ble_evt --> HVC

:INF:is_waiting_for_reset = 0

But when the written values corresponds with 0x01 I can see how the device receives the ble_dfu_on_ble_evt --> HVC:

:INF:ble_dfu_on_ble_evt --> Write

:INF:Received indication state 1, notification state 0 BLE:INF:Indication for BLE_DFU is enabled.

:INF:ble_dfu_on_ble_evt --> RW Authorize Req.

:INF:on_ctrlpt_write: indication enabled

:INF:on_ctrlpt_write: execute enter

:DEB:on_ctrlpt_write: execuing!!

:INF:enter_bootloader --> is_waiting_for_reset = true

:INF:sd_ble_gatts_hvx retval = 0

I don't know if this is due to the reset that is performed to enter into the bootloader that doesn't let the log messages going out or is part of the issue.

My app is developed with freertos, it uses watchdog and also NRF Log messages trough a dedicated task.

The changes I have made into the bootloader_secure_ble are:

  • main.c: Delete leds_init() & buttons_init() functions.
  • nrf_dfu.c: nrf_dfu_enter_check(). Delete button check to enter bootloader
  • nrf_ble_duf.c: advertising_init() & gap_params_init() fucntions to set a custom device name using NRF_FICR->DEVICEID.

Changes made for integrating the Buttonless DFU Service into my app:

  • ble_dfu.c: added NRF_LOG_INFO messages to trace.

Inside my BLE task *.c file added:

  • Inside ble_evt_dispatch() the ble_dfu_on_ble_evt() function.
  • ble_dfu_evt_handler() handler function.
  • Inside services_ini() service creation/initilization:

    memset(&dfus_init, 0, sizeof(dfus_init));
    dfus_init.evt_handler = ble_dfu_evt_handler; dfus_init.ctrl_point_security_req_write_perm = SEC_SIGNED; dfus_init.ctrl_point_security_req_cccd_write_perm = SEC_SIGNED;

    err_code = ble_dfu_init(&m_dfus, &dfus_init); APP_ERROR_CHECK(err_code);

  • *.icf memory regions:

    define symbol __ICFEDIT_intvec_start__ = 0x1f000;

    define symbol __ICFEDIT_region_ROM_start__ = 0x1f000;

    define symbol __ICFEDIT_region_ROM_end__ = 0x77fff;

    define symbol __ICFEDIT_region_RAM_start__ = 0x20002060;

    define symbol __ICFEDIT_region_RAM_end__ = 0x2000ffff;

    export symbol __ICFEDIT_region_RAM_start__;

    export symbol __ICFEDIT_region_RAM_end__;

    define symbol __ICFEDIT_size_cstack__ = 0x800;

    define symbol __ICFEDIT_size_heap__ = 0x200;

And I think I don't forget anything, so If somebody know the reason why my device is not entering properly into the bootloader after a correct DFU application download and subscribing to application's Buttonless DFU service indication and wrinting 0x01into it, please let me know if there is something missing or mistaken because I am stucked adding the DFU functionality to my app.

Thanks in advance for everyone and sorry for the long post/question.

edit retag flag offensive close delete report spam


After some test I have made, The device is resetting properly with the write of 0x01 into the Buttonless DFU characteristic. And I have also confirmed that the GPREGRET values is set to 0xB1.

I am resetting the device letting the watchdog to expire because I read in section H that the watchdog continues working after a NVIC_SystemReset() call.

In any case, it continues restarting without entering bootloader mode, it starts the application.

Any help about configuring the secure bootloader example to enable logs through the jlink and continue digging? Any advice to check what can be occuring into the bootloader to skip into the application directly?

Thanks in advance.

dpa ( 2017-07-14 13:44:08 +0200 )editconvert to answer

Can you debug the bootloader, set a breakpoint in nrf_dfu_enter_check() in nrf_dfu.cand verify whether the bootloader reaches this function or not?

Bjørn Spockeli ( 2017-07-14 14:44:44 +0200 )editconvert to answer

I can't debug bootloader neither see the logs through jlink. Is there any tutorial or post about how to enable this? thanks in advance for your help.

dpa ( 2017-07-17 07:13:31 +0200 )editconvert to answer

You should be able to debug the bootloader with out any modifications to the project, could you try to flash the dedicated debug example to your device, i.e. the one found inexamples\dfu\bootloader_secure_ble\pca10040_debug and see if that helps?

Bjørn Spockeli ( 2017-07-17 11:11:31 +0200 )editconvert to answer

I have been testing with debug bootloader.

I dont know how to debug or see jlink log messages from the bootloader once I program the SD+BL+APP+SETTINGS over nrfjprog.

In one of my test I have seen how after writing 01 to buttonless DFU characteristic the app reboots and in the logs of the bootloader it sends "Application sent bootloader request", but it doent stay at bootloader, it runs application.

Any help in how to debug this situation or any configuration that could be mistaken? Thanks

dpa ( 2017-07-17 14:03:18 +0200 )editconvert to answer

I have get the bootloader logs, and once the app is restarting to entre the bootloader this is what i get:

:INF:Inside main
:DEB:In nrf_bootloader_init
:DEB:In real nrf_dfu_init
:DEB:running nrf_dfu_settings_init
:DEB:Enter nrf_dfu_continue
:DEB:Valid App
:DEB:Application sent bootloader request  !!!
:DEB:In nrf_dfu_transports_init
:DEB:num transports: 1
:DEB:vector table: 0x00073000
:DEB:vector table: 0x00073000
:DEB:Error code - sd_softdevice_vector_table_base_set: 0x00000000
:INF:Error code - sd_ble_cfg_set: 0x00000000
:DEB:Enabling softdevice.
SDH:DEB:RAM start at 0x20002060.
:DEB:Softdevice enabled
:DEB:After nrf_dfu_transports_init
dpa ( 2017-07-17 14:19:58 +0200 )editconvert to answer

log cont'd ...

:DEB:------- nrf_dfu_flash_init-------
:DEB:Waiting for events
:INF:Inside main
:DEB:In nrf_bootloader_init
:DEB:In real nrf_dfu_init
:DEB:running nrf_dfu_settings_init
:DEB:Enter nrf_dfu_continue
:DEB:Valid App
:DEB:Enter nrf_dfu_app_is_valid
:DEB:Return true. App was valid
:DEB:Enter nrf_dfu_app_is_valid

So it seems that during the first restart it detect ok it must stay at bootloader but it restarts once more and this erased the order of staying at bootloader.

The app is using the watchdog, I will modify the app to restart not by bootloader_start() function. I will use the WDT restart to see if this solves the double reboot.

Is there any option to force a quick WDT restart or I must let the WDt to expire?

Bjørn Spockeli ( 2017-07-17 15:26:41 +0200 )editconvert to answer

I have tried without success modifying bootloader_start() function:


  • Set GPREGSET to 0xB1

  • NVIC_SystemReset()

This leads to a restart where the boot loader sees:

 0> :DEB:RESETREAS: 0x00000006.
 0> :DEB:TGPREGRET: 0x000000B1.

but after reaching to:

:DEB:Waiting for events

It restarts once more with:

 0> :DEB:RESETREAS: 0x00000006.
 0> :DEB:TGPREGRET: 0x00000000.

So there is no bootloader DFU, the app starts normally.

dpa ( 2017-07-18 08:56:32 +0200 )editconvert to answer


  • Set GPREGSET to 0xB1

  • Force a WDT reset

This leads to a restart where the boot loader sees:

 0> :DEB:RESETREAS: 0x00000006.
 0> :DEB:TGPREGRET: 0x00000000.

The app starts normally.

Right now I have commented sd_softdevice_disable(), sd_softdevice_vector_table_base_set() and NVIC_ClearPendingIRQ() lines because I read that with setting GPREGRET to 0xB1 and restarting is enough.

Any help for this issue/problem?

dpa ( 2017-07-18 08:57:57 +0200 )editconvert to answer

If the App uses the WDT there is no possibility of reseting the app from WDT because the GPREGRET will be lost.

I am trying to include WDT support to the secure bootloader using this post1 and this other post2 but I am still suffering the restart once the bootloader detects it must stays at bootloader DFU.

Where is the right place to refresh the WDT at the secure bootloader? I am using SDK13.

dpa ( 2017-07-18 13:40:14 +0200 )editconvert to answer

What kind of WDT interval have you set in the application? Have you placed

NRF_WDT->RR[0] = 0x6E524635UL;

in the wait_for_event() function in nrf_dfu.c?

Bjørn Spockeli ( 2017-07-18 14:52:11 +0200 )editconvert to answer

Mi WDT interval is 3s.

With "NRF_WDT_BEHAVIOUR_RUN_SLEEP" configuration it didnt work, but now I am testing with "NRF_WDT_BEHAVIOUR_PAUSE_SLEEP_HALT" and the bootloader part with the corresponding WDT refresh order "NRF_WDT->RR[0] = WDT_RR_RR_Reload" it works.

The problem is that once the bootloader mode is entered and after 5-6 minutes (or something like that) the devices restarts again after no DFu initiation or communication and the application starts again. Is there any timeout or why can be the bootloader being reseted?

dpa ( 2017-07-19 08:19:11 +0200 )editconvert to answer

As far as I know there is no timeout in the Secure bootloader that causes it to reset if there is no activity. Did you place the NRF_WDT->RR[0] = WDT_RR_RR_Reload statement in the wait_for_event()function? The Secure bootloader is configured to advertise forever with an advertisment interval of 25ms, so the chip should wake-up every 25ms and reload the RR register of the WDT if there is no activity.

Bjørn Spockeli ( 2017-07-19 16:22:20 +0200 )editconvert to answer

1 answer

Sort by » oldest newest most voted
dpa gravatar image

answered 2017-07-20 09:22:50 +0200

bjorn-spockeli gravatar image

updated 2017-07-20 10:52:47 +0200

I have the WDT reload command:

  • Inside the wait_for_event()
  • Inside nrf_dfu_app_continue() [for the bank transfer ]

In both cases the refresh is conditioned to the WDT status:


I have also integrated a Timeout using the RTC2 that you mention on this answer so now it seems everything works perfectly and there is no WDT reset during the DFU transfer and if the configured RTC2 timeout expires, the device reset and start with the application.

Thanks for the support and if there is any other issue or problem I will come for advice, thanks!

edit flag offensive delete publish link more


Great! Happy to hear that everything is working now.

Bjørn Spockeli ( 2017-07-20 10:53:10 +0200 )editconvert to answer

Your Answer

Please start posting anonymously - your entry will be published after you log in or create a new account.

Add Answer. Do not ask a new question or reply to an answer here.

[hide preview]

Question Tools

1 follower


Asked: 2017-07-13 14:01:17 +0200

Seen: 73 times

Last updated: Jul 17