nrf52832 OTA over ESB based on SDK17.1.0

Hi everyone:    I developed an application based on ESB wireless communication protocol ofr the nRF52832, and I would like to perform an OTA DFU with it.    Do you know any example of some over the air FW upgrade of nRF52832 chip via ESB protocol.

    SDK is 17.1.0.

Best regards,

Lurn.

Parents
  • I only found examples of ble and uart in the dfu/secure_bootloader folder, Which one should I use or how should I modify it to adapt my program.

  • Hello,

    It is correct that you will only find BLE and UART in our samples, but I know that several customers have ported this to SPI, so if you need it over ESB, then that should also be possible. The transport layers in the bootloader for the nRF5 SDK are on purpose quite separated from the rest of the libraries, to make it easier to change the transport layer, or to add your own transport layer.

    But you do need to implement it yourself. Also note that we do not have the "DFU Master" as an official part of our SDK. We have tools like nrfutil (open source) or nRF Connect for Desktop (not open source), and applications for mobile phones that are open source (but mobile phones doesn't have ESB). However, there is an unofficial implementation (not properly tested. You can use it, but on your own "risk"), which you can find here. I have not tested these myself, but you can give it a go. I suggest you test out the UART master, in combination with the uart bootloader, and then you can port both to ESB once you are up and running.

    Best regards,

    Edvin

  • Lurn_Z said:
    No, I didn't change it, I mixed the other ticket answer.

    In that case, I suggest we only focus on one ticket at the time. I suggest this one, and we can continue with the other when this one is solved.

    Lurn_Z said:
    when change 115200 to 9600, I only get one line  >>  app:Received an error: 0x0000004!

    That is because you are using the wrong baud rate. Change it back to 115200.

    I still think you would have saved yourself a lot of trouble by getting up and running on a DK before attempting to do this on a custom board, and you may still save time by doing so.

    So it fails to send the serial response. The only possible reason I can think of is that you have enabled hardware flow control (HWFC) in your bootloader project. Try to disable it by setting:

    #define NRF_DFU_SERIAL_UART_USES_HWFC 0

    in your sdk_config.h (It is set to 1 by default. Search for this define in your bootloader's sdk_config.h).

    Lurn_Z said:
    I want to update the device by UART, and I will send it to nrf through the UART of other board.

    In that case, you will not see it in your nRF Connect for Android/iOS, as you would if you were using the BLE bootloader, for obvious reasons.

    Lurn_Z said:
    Do I need to do anything on other boards? For example on PC I need to use nrfjprog to update.

    From the other board, you need to transfer the image. For how to do this, I am afraid we don't have a very good documentation. You can look into the DFU library. There are some useful links from here. Alternatively, you need to look at the implementation of nrfutil (on github)

    Lastly, we have an unofficial implementation of the DFU master, which you can find in this tutorial:

     Getting started with Nordic's Secure DFU bootloader, a step by step guide 

    (Search for DFU master code).

    Best regards,

    Edvin

  • So it fails to send the serial response. The only possible reason I can think of is that you have enabled hardware flow control (HWFC) in your bootloader project. Try to disable it by setting:

    #define NRF_DFU_SERIAL_UART_USES_HWFC 0

    Yes, this is the wrong reason. Now I can update my device successfully.

    I have a question now.

    How should I enter the DFU mode when my device in application?

    I don't think I can use the while loop that you suggest before, because I didn't use softdevice now(I used the wrong example to test before).

    To see whether it is written.

    So to fix this, you can use something like this:

    {
        uint32_t old_gpregret = sd_power_gpregret_get();
        uint32_t new_gpregret = old_gpregret & BOOTLOADER_DFU_START; //Just to retain other things written to gpregret. Not necessarily needed.
        uint32_t temp = 0;
        
        sd_power_gpregret_set(new_gpregret);
        while ((temp & BOOTLOADER_DFU_START) != BOOTLOADER_DFU_START)
        {
            // Wait until the gpregret is written, and refresh the value of temp.
            sd_power_gpregret_get(0, &temp);
        }
        // When this is reached, the gpregret is successfully written.
        nrf_pwr_mgmt_shutdown(NRF_PWR_MGMT_SHUTDOWN_GOTO_DFU);
        NVIC_SystemReset();
    }

    maybe I still need to modify gpregret, but can not use the function sd_power_gpregret_set() ?

    From the other board, you need to transfer the image. For how to do this, I am afraid we don't have a very good documentation. You can look into the DFU library. There are some useful links from here. Alternatively, you need to look at the implementation of nrfutil (on github)

    I will view and study these materials

    BR,

    Lurn

  • Good good! We are getting closer. Now you only need a way to enter DFU mode. You are correct that we can still use the GPREGRET, and we can do so without using the softdevice. By default, the api to interact with the GPREGRET is nrf_power_gpregret_set() and nrf_power_gpregret_get(), like it is used in the bootloader example. However, if the softdevice is enabled, the gpregret is restricted, so you need to access the gpregret via the softdevice API (sd_power_gpregret_set/get()). When the softdevice is not enabled, you are free to use the "normal" nrf_power_gpregret_set()/nrf_power_gpregret_get(). These are declared in SDK\modules\nrfx\hal\nrf_power.h.

    So the snippet in your last reply will still work. Just replace all "sd_..." with "nrf_...", and make all the variables uint8_t instead of unt32_t (because the GPREGRET is just an 8 bit value, and the non-softdevice actually expects and returns uint8_t instead of uint32_t) and you are good. 

    Do you know where you want to call this function? We have not discussed this, but perhaps you already have a plan. In a BLE bootloader, it is typical to use a special BLE service to put the device in DFU mode (the buttonless_dfu service). Other methods are:

    1: Always enter DFU mode on power on, and make it time out after X time, and then enter the application.

    2: Hold a button/gpio on reset to enter DFU mode.

    3: Use the gpregret from your application. You are free to decide when you write this register. If you have a UART device connected, you can e.g. use a special UART message to trigger this.

    Best regards,

    Edvin

  • OK, I will try enter DFU mode on power on for first test, and if it worked I can use my own way, like you said UART etc...

    BR

    Lurn

  • So the snippet in your last reply will still work. Just replace all "sd_..." with "nrf_...", and make all the variables uint8_t instead of unt32_t (because the GPREGRET is just an 8 bit value, and the non-softdevice actually expects and returns uint8_t instead of uint32_t) and you are good. 

    1.I can't enter the DFU mode in use the while loop, so I print the old_gpregret and new_gpregret, and the value is 0. so I change nrf_power_gpregret_set(new_gpregret); to nrf_power_gpregret_set(0XB1); 

    It also can't enter DFU, but the code break from while loop, when I use nrfjprog --reset to reset system, the device enter the DFU mode, so I think the reset code doesn't work.

    2.When the device in DFU mode, it can't enter the application after time out, the device is always in DFU mode.

    the NRF_BL_DFU_CONTINUATION_TIMEOUT_MS is 10000

    and the NRF_BL_DFU_INACTIVITY_TIMEOUT_MS is 120000.

    the RTT log is here.

    # SEGGER J-Link RTT Viewer V7.00a Terminal Log File
    # Compiled: 15:35:52 on Apr 16 2021
    # Logging started @ 22 Feb 2023 18:14:19
    00> <debug> app: timer_stop (0x20000020)
    00> 
    00> <debug> app: timer_fire (<info> app: Inside main
    00> 
    00> <debug> app: In nrf_bootloader_init
    00> 
    00> <debug> nrf_dfu_settings: Calling nrf_dfu_settings_init()...
    00> 
    00> <<info> app: Inside main
    00> 
    00> <debug> app: In nrf_bootloader_init
    00> 
    00> <debug> nrf_dfu_settings: Calling nrf_dfu_settings_init()...
    00> 
    00> <debug> nrf_dfu_flash: Initializing nrf_fstorage_nvmc backend.
    00> 
    00> <debug> nrf_dfu_settings: Using settings page.
    00> 
    00> <debug> nrf_dfu_settings: Copying forbidden parts from backup page.
    00> 
    00> <debug> nrf_dfu_settings: Destination settings are identical to source, write not needed. Skipping.
    00> 
    00> <info> nrf_dfu_settings: Backing up settings page to address 0x7E000.
    00> 
    00> <debug> nrf_dfu_settings: Destination settings are identical to source, write not needed. Skipping.
    00> 
    00> <debug> app: Enter nrf_bootloader_fw_activate
    00> 
    00> <info> app: No firmware to activate.
    00> 
    00> <debug> app: App is valid
    00> 
    00> <debug> app: DFU mode requested via GPREGRET.
    00> 
    00> <info> nrf_bootloader_wdt: WDT is not enabled
    00> 
    00> <debug> app: in weak nrf_dfu_init_user
    00> 
    00> <debug> app: timer_stop (0x20000020)
    00> 
    00> <debug> app: timer_activate (0x20000020)
    00> 
    00> <info> app: Entering DFU mode.
    00> 
    00> <debug> app: Initializing transports (found: 1)
    00> 
    00> <debug> nrf_dfu_serial_uart: serial_dfu_transport_init()
    00> 
    00> <debug> nrf_dfu_serial_uart: serial_dfu_transport_init() completed
    00> 
    00> <debug> nrf_dfu_flash: Initializing nrf_fstorage_nvmc backend.
    00> 
    00> <debug> app: Enter main loop
    00> 
    00> <debug> app: timer_stop (0x20000020)
    00> 
    00> <info> app: Inside main
    00> 
    00> <debug> app: In nrf_bootloader_init
    00> 
    00> <debug> nrf_dfu_settings: Calling nrf_dfu_settings_init()...
    00> 
    00> <debug> nrf_dfu_flash: Initializing nrf_f<debug> nrf_dfu_flash: Initializing nrf_fstorage_nvmc backend.
    00> 
    00> <debug> nrf_dfu_settings: Using settings page.
    00> 
    00> <debug> nrf_dfu_settings: Copying forbidden parts from backup page.
    00> 
    00> <debug> nrf_dfu_settings: Destination settings are identical to source, write not needed. Skipping.
    00> 
    00> <info> nrf_dfu_settings: Backing up settings page to address 0x7E000.
    00> 
    00> <debug> nrf_dfu_settings: Destination settings are identical to source, write not needed. Skipping.
    00> 
    00> <debug> app: Enter nrf_bootloader_fw_activate
    00> 
    00> <info> app: No firmware to activate.
    00> 
    00> <debug> app: App is valid
    00> 
    00> <debug> app: DFU mode requested via GPREGRET.
    00> 
    00> <info> nrf_bootloader_wdt: WDT is not enabled
    00> 
    00> <debug> app: in weak nrf_dfu_init_user
    00> 
    00> <debug> app: timer_stop (0x20000020)
    00> 
    00> <debug> app: timer_activate (0x20000020)
    00> 
    00> <info> app: Entering DFU mode.
    00> 
    00> <debug> app: Initializing transports (found: 1)
    00> 
    00> <debug> nrf_dfu_serial_uart: serial_dfu_transport_init()
    00> 
    00> <debug> nrf_dfu_serial_uart: serial_dfu_transport_init() completed
    00> 
    00> <debug> nrf_dfu_flash: Initializing nrf_fstorage_nvmc backend.
    00> 
    00> <debug> app: Enter main loop
    00> 
    00> <debug> app: timer_stop (0x20000020)
    00> 
    00> <debug> app: timer_fire (0x200000<info> app: Inside main
    00> 
    00> <debug> app: In nrf_bootloader_init
    00> 
    00> <debug> nrf_dfu_settings: Calling nrf_dfu_settings_init()...
    00> 
    00> <debug> nrf_dfu_flash: Initializing nrf_fstorage_nvmc backend.
    00> 
    00> <debug> nrf_dfu_settings: Using settings page.
    00> 
    00> <debug> nrf_dfu_settings: Copying forbidden parts from backup page.
    00> 
    00> <debug> nrf_dfu_settings: Destination settings are identical to source, write not needed. Skipping.
    00> 
    00> <info> nrf_dfu_settings: Backing up settings page to address 0x7E000.
    00> 
    00> <debug> nrf_dfu_settings: Destination settings are identical to source, write not needed. Skipping.
    00> 
    00> <debug> app: Enter nrf_bootloader_fw_activate
    00> 
    00> <info> app: No firmware to activate.
    00> 
    00> <debug> app: App is valid
    00> 
    00> <debug> app: DFU mode requested via GPREGRET.
    00> 
    00> <info> nrf_bootloader_wdt: WDT is not enabled
    00> 
    00> <debug> app: in weak nrf_dfu_init_user
    00> 
    00> <debug> app: timer_stop (0x20000020)
    00> 
    00> <debug> app: timer_activate (0x20000020)
    00> 
    00> <info> app: Entering DFU mode.
    00> 
    00> <debug> app: Initializing transports (found: 1)
    00> 
    00> <debug> nrf_dfu_serial_uart: serial_dfu_transport_init()
    00> 
    00> <debug> nrf_dfu_serial_uart: serial_dfu_transport_init() completed
    00> 
    00> <debug> nrf_dfu_flash: Initializing nrf_fstorage_nvmc backend.
    00> 
    00> <debug> app: Enter main loop
    00> 
    00> <debug> app: timer_stop (0x2<info> app: Inside main
    00> 
    00> <debug> app: In nrf_bootloader_init
    00> 
    00> <debug> nrf_dfu_settings: Calling nrf_dfu_settings_init()...
    00> 
    00> <debug> nrf_dfu_flash: Initializing nrf_fstorage_nvmc backend.
    00> 
    00> <debug> nrf_dfu_settings<info> app: Inside main
    00> 
    00> <debug> app: In nrf_bootloader_init
    00> 
    00> <debug> nrf_dfu_settings: Calling nrf_dfu_settings_init()...
    00> 
    00> <debug> nrf_dfu_flash: Initializing nrf_fstorage_nvmc backend.
    00> 
    00> <debug> nrf_dfu_settings: Using settings page.
    00> 
    00> <debug> nrf_dfu_settings: Copying forbidden parts from backup page.
    00> 
    00> <debug> nrf_dfu_settings: Destination settings are identical to source, write not needed. Skipping.
    00> 
    00> <info> nrf_dfu_settings: Backing up settings page to address 0x7E000.
    00> 
    00> <debug> nrf_dfu_settings: Destination settings are identical to source, write not needed. Skipping.
    00> 
    00> <debug> app: Enter nrf_bootloader_fw_activate
    00> 
    00> <info> app: No firmware to activate.
    00> 
    00> <debug> app: App is valid
    00> 
    00> <debug> app: DFU mode requested via GPREGRET.
    00> 
    00> <info> nrf_bootloader_wdt: WDT is not enabled
    00> 
    00> <debug> app: in weak nrf_dfu_init_user
    00> 
    00> <debug> app: timer_stop (0x20000020)
    00> 
    00> <debug> app: timer_activate (0x20000020)
    00> 
    00> <info> app: Entering DFU mode.
    00> 
    00> <debug> app: Initializing transports (found: 1)
    00> 
    00> <debug> nrf_dfu_serial_uart: serial_dfu_transport_init()
    00> 
    00> <debug> nrf_dfu_serial_uart: serial_dfu_transport_init() completed
    00> 
    00> <debug> nrf_dfu_flash: Initializing nrf_fstorage_nvmc backend.
    00> 
    00> <debug> app: Enter main loop
    00> 
    
    # Logging stopped @ 22 Feb 2023 18:21:49
    

    but when use nrfjprog --reset, the device enter the application.

    So, for the two problem what's wrong with it?

    BR,

    Lurn

Reply
  • So the snippet in your last reply will still work. Just replace all "sd_..." with "nrf_...", and make all the variables uint8_t instead of unt32_t (because the GPREGRET is just an 8 bit value, and the non-softdevice actually expects and returns uint8_t instead of uint32_t) and you are good. 

    1.I can't enter the DFU mode in use the while loop, so I print the old_gpregret and new_gpregret, and the value is 0. so I change nrf_power_gpregret_set(new_gpregret); to nrf_power_gpregret_set(0XB1); 

    It also can't enter DFU, but the code break from while loop, when I use nrfjprog --reset to reset system, the device enter the DFU mode, so I think the reset code doesn't work.

    2.When the device in DFU mode, it can't enter the application after time out, the device is always in DFU mode.

    the NRF_BL_DFU_CONTINUATION_TIMEOUT_MS is 10000

    and the NRF_BL_DFU_INACTIVITY_TIMEOUT_MS is 120000.

    the RTT log is here.

    # SEGGER J-Link RTT Viewer V7.00a Terminal Log File
    # Compiled: 15:35:52 on Apr 16 2021
    # Logging started @ 22 Feb 2023 18:14:19
    00> <debug> app: timer_stop (0x20000020)
    00> 
    00> <debug> app: timer_fire (<info> app: Inside main
    00> 
    00> <debug> app: In nrf_bootloader_init
    00> 
    00> <debug> nrf_dfu_settings: Calling nrf_dfu_settings_init()...
    00> 
    00> <<info> app: Inside main
    00> 
    00> <debug> app: In nrf_bootloader_init
    00> 
    00> <debug> nrf_dfu_settings: Calling nrf_dfu_settings_init()...
    00> 
    00> <debug> nrf_dfu_flash: Initializing nrf_fstorage_nvmc backend.
    00> 
    00> <debug> nrf_dfu_settings: Using settings page.
    00> 
    00> <debug> nrf_dfu_settings: Copying forbidden parts from backup page.
    00> 
    00> <debug> nrf_dfu_settings: Destination settings are identical to source, write not needed. Skipping.
    00> 
    00> <info> nrf_dfu_settings: Backing up settings page to address 0x7E000.
    00> 
    00> <debug> nrf_dfu_settings: Destination settings are identical to source, write not needed. Skipping.
    00> 
    00> <debug> app: Enter nrf_bootloader_fw_activate
    00> 
    00> <info> app: No firmware to activate.
    00> 
    00> <debug> app: App is valid
    00> 
    00> <debug> app: DFU mode requested via GPREGRET.
    00> 
    00> <info> nrf_bootloader_wdt: WDT is not enabled
    00> 
    00> <debug> app: in weak nrf_dfu_init_user
    00> 
    00> <debug> app: timer_stop (0x20000020)
    00> 
    00> <debug> app: timer_activate (0x20000020)
    00> 
    00> <info> app: Entering DFU mode.
    00> 
    00> <debug> app: Initializing transports (found: 1)
    00> 
    00> <debug> nrf_dfu_serial_uart: serial_dfu_transport_init()
    00> 
    00> <debug> nrf_dfu_serial_uart: serial_dfu_transport_init() completed
    00> 
    00> <debug> nrf_dfu_flash: Initializing nrf_fstorage_nvmc backend.
    00> 
    00> <debug> app: Enter main loop
    00> 
    00> <debug> app: timer_stop (0x20000020)
    00> 
    00> <info> app: Inside main
    00> 
    00> <debug> app: In nrf_bootloader_init
    00> 
    00> <debug> nrf_dfu_settings: Calling nrf_dfu_settings_init()...
    00> 
    00> <debug> nrf_dfu_flash: Initializing nrf_f<debug> nrf_dfu_flash: Initializing nrf_fstorage_nvmc backend.
    00> 
    00> <debug> nrf_dfu_settings: Using settings page.
    00> 
    00> <debug> nrf_dfu_settings: Copying forbidden parts from backup page.
    00> 
    00> <debug> nrf_dfu_settings: Destination settings are identical to source, write not needed. Skipping.
    00> 
    00> <info> nrf_dfu_settings: Backing up settings page to address 0x7E000.
    00> 
    00> <debug> nrf_dfu_settings: Destination settings are identical to source, write not needed. Skipping.
    00> 
    00> <debug> app: Enter nrf_bootloader_fw_activate
    00> 
    00> <info> app: No firmware to activate.
    00> 
    00> <debug> app: App is valid
    00> 
    00> <debug> app: DFU mode requested via GPREGRET.
    00> 
    00> <info> nrf_bootloader_wdt: WDT is not enabled
    00> 
    00> <debug> app: in weak nrf_dfu_init_user
    00> 
    00> <debug> app: timer_stop (0x20000020)
    00> 
    00> <debug> app: timer_activate (0x20000020)
    00> 
    00> <info> app: Entering DFU mode.
    00> 
    00> <debug> app: Initializing transports (found: 1)
    00> 
    00> <debug> nrf_dfu_serial_uart: serial_dfu_transport_init()
    00> 
    00> <debug> nrf_dfu_serial_uart: serial_dfu_transport_init() completed
    00> 
    00> <debug> nrf_dfu_flash: Initializing nrf_fstorage_nvmc backend.
    00> 
    00> <debug> app: Enter main loop
    00> 
    00> <debug> app: timer_stop (0x20000020)
    00> 
    00> <debug> app: timer_fire (0x200000<info> app: Inside main
    00> 
    00> <debug> app: In nrf_bootloader_init
    00> 
    00> <debug> nrf_dfu_settings: Calling nrf_dfu_settings_init()...
    00> 
    00> <debug> nrf_dfu_flash: Initializing nrf_fstorage_nvmc backend.
    00> 
    00> <debug> nrf_dfu_settings: Using settings page.
    00> 
    00> <debug> nrf_dfu_settings: Copying forbidden parts from backup page.
    00> 
    00> <debug> nrf_dfu_settings: Destination settings are identical to source, write not needed. Skipping.
    00> 
    00> <info> nrf_dfu_settings: Backing up settings page to address 0x7E000.
    00> 
    00> <debug> nrf_dfu_settings: Destination settings are identical to source, write not needed. Skipping.
    00> 
    00> <debug> app: Enter nrf_bootloader_fw_activate
    00> 
    00> <info> app: No firmware to activate.
    00> 
    00> <debug> app: App is valid
    00> 
    00> <debug> app: DFU mode requested via GPREGRET.
    00> 
    00> <info> nrf_bootloader_wdt: WDT is not enabled
    00> 
    00> <debug> app: in weak nrf_dfu_init_user
    00> 
    00> <debug> app: timer_stop (0x20000020)
    00> 
    00> <debug> app: timer_activate (0x20000020)
    00> 
    00> <info> app: Entering DFU mode.
    00> 
    00> <debug> app: Initializing transports (found: 1)
    00> 
    00> <debug> nrf_dfu_serial_uart: serial_dfu_transport_init()
    00> 
    00> <debug> nrf_dfu_serial_uart: serial_dfu_transport_init() completed
    00> 
    00> <debug> nrf_dfu_flash: Initializing nrf_fstorage_nvmc backend.
    00> 
    00> <debug> app: Enter main loop
    00> 
    00> <debug> app: timer_stop (0x2<info> app: Inside main
    00> 
    00> <debug> app: In nrf_bootloader_init
    00> 
    00> <debug> nrf_dfu_settings: Calling nrf_dfu_settings_init()...
    00> 
    00> <debug> nrf_dfu_flash: Initializing nrf_fstorage_nvmc backend.
    00> 
    00> <debug> nrf_dfu_settings<info> app: Inside main
    00> 
    00> <debug> app: In nrf_bootloader_init
    00> 
    00> <debug> nrf_dfu_settings: Calling nrf_dfu_settings_init()...
    00> 
    00> <debug> nrf_dfu_flash: Initializing nrf_fstorage_nvmc backend.
    00> 
    00> <debug> nrf_dfu_settings: Using settings page.
    00> 
    00> <debug> nrf_dfu_settings: Copying forbidden parts from backup page.
    00> 
    00> <debug> nrf_dfu_settings: Destination settings are identical to source, write not needed. Skipping.
    00> 
    00> <info> nrf_dfu_settings: Backing up settings page to address 0x7E000.
    00> 
    00> <debug> nrf_dfu_settings: Destination settings are identical to source, write not needed. Skipping.
    00> 
    00> <debug> app: Enter nrf_bootloader_fw_activate
    00> 
    00> <info> app: No firmware to activate.
    00> 
    00> <debug> app: App is valid
    00> 
    00> <debug> app: DFU mode requested via GPREGRET.
    00> 
    00> <info> nrf_bootloader_wdt: WDT is not enabled
    00> 
    00> <debug> app: in weak nrf_dfu_init_user
    00> 
    00> <debug> app: timer_stop (0x20000020)
    00> 
    00> <debug> app: timer_activate (0x20000020)
    00> 
    00> <info> app: Entering DFU mode.
    00> 
    00> <debug> app: Initializing transports (found: 1)
    00> 
    00> <debug> nrf_dfu_serial_uart: serial_dfu_transport_init()
    00> 
    00> <debug> nrf_dfu_serial_uart: serial_dfu_transport_init() completed
    00> 
    00> <debug> nrf_dfu_flash: Initializing nrf_fstorage_nvmc backend.
    00> 
    00> <debug> app: Enter main loop
    00> 
    
    # Logging stopped @ 22 Feb 2023 18:21:49
    

    but when use nrfjprog --reset, the device enter the application.

    So, for the two problem what's wrong with it?

    BR,

    Lurn

Children
  • Are you resetting manually in this log (using nrfjprog --reset) or is it the timer that times out? 

    It looks like it is entering DFU mode because "DFU mode requested via GPREGRET". So if you want to exit this, you need to clear the register from your bootloader. 

    I am not sure what you mean by the while loop anymore. Perhaps you can rephrase the question.

    BR,
    Edvin

  • Are you resetting manually in this log (using nrfjprog --reset) or is it the timer that times out? 

    nope, it is the times out.

    I clear the register by nrf_power_gpregret_set(nrf_power_gpregret_get() & ~BOOTLOADER_DFU_START); and then I print the nrf_power_gpregret_get() value, it is 0, So I think the register was cleared.

    I am not sure what you mean by the while loop anymore

    The while loop is that. I put the code in the preceding part of my main.c.

    void enter_dfu()
    {
        uint32_t old_gpregret = nrf_power_gpregret_get();
        uint32_t new_gpregret = old_gpregret & BOOTLOADER_DFU_START; //Just to retain other things written to gpregret. Not necessarily needed.
        uint32_t temp = 0;
        
        nrf_power_gpregret_set(0XB1);
        while ((temp & BOOTLOADER_DFU_START) != BOOTLOADER_DFU_START)
        {
            // Wait until the gpregret is written, and refresh the value of temp.
            nrf_power_gpregret_get(0, &temp);
        }
        // When this is reached, the gpregret is successfully written.
        nrf_pwr_mgmt_shutdown(NRF_PWR_MGMT_SHUTDOWN_GOTO_DFU);
        NVIC_SystemReset();
    }
    
    int main(void)
    {
        SEGGER_RTT_printf(0, "Start Application");
        nrf_drv_clock_init();
        clocks_start();
        bsp_board_init(BSP_INIT_LEDS);
        enter_dfu();
        ...
    }
    

    And this is the process, after I program the MBR, bootloader, application and settings, it will always in DFU mode, and I wasn't use the nrfjprog --reset in this log, it is the time out.

     The order of commands I used.

    nrfutil settings generate --family NRF52 --application app.hex --application-version 0 --bootloader-version 0 --bl-settings-version 2 settings.hex
    nrfutil pkg generate --application app.hex --application-version 2 --sd-req 0x00 --hw-version 52 --key-file priv.pem dfu_image.zip
    
    nrfjprog --eraseall -f NRF52
    nrfjprog --program mbr_nrf52_2.4.1_mbr.hex --verify -f NRF52
    nrfjprog --program bootloader.hex --verify -f NRF52
    nrfjprog --program app.hex --verify -f NRF52
    nrfjprog --program settings.hex --verify -f NRF52
    nrfjprog --reset -f NRF52
    

    and the logs

    # SEGGER J-Link RTT Viewer V7.00a Terminal Log File
    # Compiled: 15:35:52 on Apr 16 2021
    # Logging started @ 23 Feb 2023 14:26:17
    00> <info> app: Inside main
    00> 
    00> <debug> app: In nrf_bootloader_init
    00> 
    00> <debug> nrf_dfu_settings: Calling nrf_dfu_settings_init()...
    00> 
    00> <debug> nrf_dfu_flash: Initializing nrf_fstorage_nvmc backend.
    00> 
    00> <debug> nrf_dfu_settings: Using settings page.
    00> 
    00> <debug> nrf_dfu_settings: Copying forbidden parts from backup page.
    00> 
    00> <debug> nrf_dfu_settings: Destination settings are identical to source, write not needed. Skipping.
    00> 
    00> <info> nrf_dfu_settings: Backing up settings page to address 0x7E000.
    00> 
    00> <debug> nrf_dfu_settings: Destination settings are identical to source, write not needed. Skipping.
    00> 
    00> <debug> app: Enter nrf_bootloader_fw_activate
    00> 
    00> <info> app: No firmware to activate.
    00> 
    00> <debug> app: ACTIVATION_NONE
    00> 
    00> <debug> app: App is valid
    00> 
    00> <debug> app: DFU mode requested via GPREGRET.
    00> 
    00> <info> nrf_bootloader_wdt: WDT is not enabled
    00> 
    00> <debug> app: Clear DFU mark in GPREGRET register.
    00> 
    00> <debug> app: GPREGRET register = 0.
    00> 
    00> <debug> app: in weak nrf_dfu_init_user
    00> 
    00> <debug> app: timer_stop (0x20000020)
    00> 
    00> <debug> app: timer_activate (0x20000020)
    00> 
    00> <info> app: Entering DFU mode.
    00> 
    00> <debug> app: Initializing transports (found: 1)
    00> 
    00> <debug> nrf_dfu_serial_uart: serial_dfu_transport_init()
    00> 
    00> <debug> nrf_dfu_serial_uart: serial_dfu_transport_init() completed
    00> 
    00> <debug> nrf_dfu_flash: Initializing nrf_fstorage_nvmc backend.
    00> 
    00> <debug> app: Enter main loop
    00> 
    00> <debug> app: timer_stop (0x20000020)
    00> 
    00> <debug> app: timer_fire (0x2<info> app: Inside main
    00> 
    00> <debug> app: In nrf_bootloader_init
    00> 
    00> <debug> nrf_dfu_settings: Calling nrf_dfu_settings_init()...
    00> 
    00> <debug> nrf_dfu_flash: Initializing nrf_fstorage_nvmc backend.
    00> 
    00> <debug> nrf_dfu_settings: Using settings page.
    00> 
    00> <debug> nrf_dfu_settings: Copying forbidden parts from backup page.
    00> 
    00> <debug> nrf_dfu_settings: Destination settings are identical to source, write not needed. Skipping.
    00> 
    00> <info> nrf_dfu_settings: Backing up settings page to address 0x7E000.
    00> 
    00> <debug> nrf_dfu_settings: Destination settings are identical to source, write not needed. Skipping.
    00> 
    00> <debug> app: Enter nrf_bootloader_fw_activate
    00> 
    00> <info> app: No firmware to activate.
    00> 
    00> <debug> app: ACTIVATION_NONE
    00> 
    00> <debug> app: App is valid
    00> 
    00> <debug> app: DFU mode requested via GPREGRET.
    00> 
    00> <info> nrf_bootloader_wdt: WDT is not enabled
    00> 
    00> <debug> app: Clear DFU mark in GPREGRET register.
    00> 
    00> <debug> app: GPREGRET register = 0.
    00> 
    00> <debug> app: in weak nrf_dfu_init_user
    00> 
    00> <debug> app: timer_stop (0x20000020)
    00> 
    00> <debug> app: timer_activate (0x20000020)
    00> 
    00> <info> app: Entering DFU mode.
    00> 
    00> <debug> app: Initializing transports (found: 1)
    00> 
    00> <debug> nrf_dfu_serial_uart: serial_dfu_transport_init()
    00> 
    00> <debug> nrf_dfu_serial_uart: serial_dfu_transport_init() completed
    00> 
    00> <debug> nrf_dfu_flash: Initializing nrf_fstorage_nvmc backend.
    00> 
    00> <debug> app: Enter main loop
    00> 
    00> <debug> app: timer_stop (0x<info> app: Inside main
    00> 
    00> <debug> app: In nrf_bootloader_init
    00> 
    00> <debug> nrf_dfu_settings: Calling nrf_dfu_settings_init()...
    00> 
    00> <debug> nrf_dfu_flash: Initializing nrf_fstorage_nvmc backend.
    00> 
    00> <debug> nrf_dfu_settings: Using settings page.
    00> 
    00> <debug> nrf_dfu_settings: Copying forbidden parts from backup page.
    00> 
    00> <debug> nrf_dfu_settings: Destination settings are identical to source, write not needed. Skipping.
    00> 
    00> <info> nrf_dfu_settings: Backing up settings page to address 0x7E000.
    00> 
    00> <debug> nrf_dfu_settings: Destination settings are identical to source, write not needed. Skipping.
    00> 
    00> <debug> app: Enter nrf_bootloader_fw_activate
    00> 
    00> <info> app: No firmware to activate.
    00> 
    00> <debug> app: ACTIVATION_NONE
    00> 
    00> <debug> app: App is valid
    00> 
    00> <debug> app: DFU mode requested via GPREGRET.
    00> 
    00> <info> nrf_bootloader_wdt: WDT is not enabled
    00> 
    00> <debug> app: Clear DFU mark in GPREGRET register.
    00> 
    00> <debug> app: GPREGRET register = 0.
    00> 
    00> <debug> app: in weak nrf_dfu_init_user
    00> 
    00> <debug> app: timer_stop (0x20000020)
    00> 
    00> <debug> app: timer_activate (0x20000020)
    00> 
    00> <info> app: Entering DFU mode.
    00> 
    00> <debug> app: Initializing transports (found: 1)
    00> 
    00> <debug> nrf_dfu_serial_uart: serial_dfu_transport_init()
    00> 
    00> <debug> nrf_dfu_serial_uart: serial_dfu_transport_init() completed
    00> 
    00> <debug> nrf_dfu_flash: Initializing nrf_fstorage_nvmc backend.
    00> 
    00> <debug> app: Enter main loop
    00> 
    00> <debug> app: timer_stop (0x20000020)
    00> 
    00> <info> app: Inside main
    00> 
    00> <debug> app: In nrf_bootloader_init
    00> 
    00> <debug> nrf_dfu_settings: Calling nrf_dfu_settings_init()...
    00> 
    00> <debug> nrf_dfu_flash: Initializing nrf_fstorage_nvmc backend.
    00> 
    00> <debug> nrf_dfu_settings: Using settings page.
    00> 
    00> <debug> nrf_dfu_settings: Copying forbidden parts from backup page.
    00> 
    00> <debug> nrf_dfu_settings: Destination settings are identical to source, write not needed. Skipping.
    00> 
    00> <info> nrf_dfu_settings: Backing up settings page to address 0x7E000.
    00> 
    00> <debug> nrf_dfu_settings: Destination settings are identical to source, write not needed. Skipping.
    00> 
    00> <debug> app: Enter nrf_bootloader_fw_activate
    00> 
    00> <info> app: No firmware to activate.
    00> 
    00> <debug> app: ACTIVATION_NONE
    00> 
    00> <debug> app: App is valid
    00> 
    00> <debug> app: DFU mode requested via GPREGRET.
    00> 
    00> <info> nrf_bootloader_wdt: WDT is not enabled
    00> 
    00> <debug> app: Clear DFU mark in GPREGRET register.
    00> 
    00> <debug> app: GPREGRET register = 0.
    00> 
    00> <debug> app: in weak nrf_dfu_init_user
    00> 
    00> <debug> app: timer_stop (0x20000020)
    00> 
    00> <debug> app: timer_activate (0x20000020)
    00> 
    00> <info> app: Entering DFU mode.
    00> 
    00> <debug> app: Initializing transports (found: 1)
    00> 
    00> <debug> nrf_dfu_serial_uart: serial_dfu_transport_init()
    00> 
    00> <debug> nrf_dfu_serial_uart: serial_dfu_transport_init() completed
    00> 
    00> <debug> nrf_dfu_flash: Initializing nrf_fstorage_nvmc backend.
    00> 
    00> <debug> app: Enter main loop
    00> 
    00> <debug> app: timer_stop (0x20000020)
    00> 
    00> <debug> app: timer_fire <info> app: Inside main
    00> 
    00> <debug> app: In nrf_bootloader_init
    00> 
    00> <debug> nrf_dfu_settings: Calling nrf_dfu_settings_init()...
    00> 
    00> <debug> nrf_dfu_flash: Initia<debug> app: ti<de<info> app: Inside main
    00> 
    00> <debug> app: In nrf_bootloader_init
    00> 
    00> <debug> nrf_dfu_settings: Calling nrf_dfu_settings_init()...
    00> 
    00> <debug> nrf_dfu_flash: Initializing nrf_fstorage_nvmc backend.
    00> 
    00> <debug> nrf_dfu_settings: Using settings page.
    00> 
    00> <debug> app: timer_activate (0x20000020)
    00> 
    00> <info> app: Entering DFU mode.
    00> 
    00> <debug> app: Initializing transports (found: 1)
    00> 
    00> <debug> nrf_dfu_serial_uart: serial_dfu_transport_init()
    00> 
    00> <debug> nrf_dfu_serial_uart: serial_dfu_transport_init() completed
    00> 
    00> <debug> nrf_dfu_flash: Initializing nrf_fstorage_nvmc backend.
    00> 
    00> <debug> app: Enter main loop
    00> 
    00> <debug> app: timer_<info> app: Inside main
    00> 
    00> <debug> app: In nrf_bootloader_init
    00> 
    00> <debug> nrf_dfu_settings: Calling nrf_dfu_settings_init()...
    00> 
    00> <debug> nrf_dfu_flash: Initializing nrf_fstorage_nvmc backend.
    00> 
    00> <debug> nrf_dfu_settings: Using settings page.
    00> 
    00> <debug> nrf_dfu_settings: Copying forbidden parts from backup page.
    00> 
    00> <debug> nrf_dfu_settings: Destination settings are identical to source, write not needed. Skipping.
    00> 
    00> <info> nrf_dfu_settings: Backing up settings page to address 0x7E000.
    00> 
    00> <debug> nrf_dfu_settings: Destination settings are identical to source, write not needed. Skipping.
    00> 
    00> <debug> app: Enter nrf_bootloader_fw_activate
    00> 
    00> <info> app: No firmware to activate.
    00> 
    00> <debug> app: ACTIVATION_NONE
    00> 
    00> <debug> app: App is valid
    00> 
    00> <debug> app: DFU mode requested via GPREGRET.
    00> 
    00> <info> nrf_bootloader_wdt: WDT is not enabled
    00> 
    00> <debug> app: Clear DFU mark in GPREGRET register.
    00> 
    00> <debug> app: GPREGRET register = 0.
    00> 
    00> <debug> app: in weak nrf_dfu_init_user
    00> 
    00> <debug> app: timer_stop (0x20000020)
    00> 
    00> <debug> app: timer_activate (0x20000020)
    00> 
    00> <info> app: Entering DFU mode.
    00> 
    00> <debug> app: Initializing transports (found: 1)
    00> 
    00> <debug> nrf_dfu_serial_uart: serial_dfu_transport_init()
    00> 
    00> <debug> nrf_dfu_serial_uart: serial_dfu_transport_init() completed
    00> 
    00> <debug> nrf_dfu_flash: Initializing nrf_fstorage_nvmc backend.
    00> 
    00> <debug> app: Enter main loop
    00> 
    00> <debug> app: timer_stop (0x20000020)
    00> 
    00> <debug> app:<info> app: Inside main
    00> 
    00> <debug> app: In nrf_bootloader_init
    00> 
    00> <debug> nrf_dfu_settings: Calling nrf_dfu_settings_init()...
    00> 
    00> <debug> nrf_dfu_flash: Initializing nrf_fstorage_nvmc backend.
    00> 
    00> <debug> nrf_dfu_settings: Using settings page.
    00> 
    00> <debug> nrf_dfu_settings: Copying forbidden parts from backup page.
    00> 
    00> <debug> nrf_dfu_settings: Destination settings are identical to source, write not needed. Skipping.
    00> 
    00> <info> nrf_dfu_settings: Backing up settings page to address 0x7E000.
    00> 
    00> <debug> nrf_dfu_settings: Destination settings are identical to source, write not needed. Skipping.
    00> 
    00> <debug> app: Enter nrf_bootloader_fw_activate
    00> 
    00> <info> app: No firmware to activate.
    00> 
    00> <debug> app: ACTIVATION_NONE
    00> 
    00> <debug> app: App is valid
    00> 
    00> <debug> app: DFU mode requested via GPREGRET.
    00> 
    00> <info> nrf_bootloader_wdt: WDT is not enabled
    00> 
    00> <debug> app: Clear DFU mark in GPREGRET register.
    00> 
    00> <debug> app: GPREGRET register = 0.
    00> 
    00> <debug> app: in weak nrf_dfu_init_user
    00> 
    00> <debug> app: timer_stop (0x20000020)
    00> 
    00> <debug> app: timer_activate (0x20000020)
    00> 
    00> <info> app: Entering DFU mode.
    00> 
    00> <debug> app: Initializing transports (found: 1)
    00> 
    00> <debug> nrf_dfu_serial_uart: serial_dfu_transport_init()
    00> 
    00> <debug> nrf_dfu_serial_uart: serial_dfu_transport_init() completed
    00> 
    00> <debug> nrf_dfu_flash: Initializing nrf_fstorage_nvmc backend.
    00> 
    00> <debug> app: Enter main loop
    00> 
    
    # Logging stopped @ 23 Feb 2023 14:28:17
    

    You can see that I was clear the register and read the value in my new logs, but the device didn't enter application.

    BR,

    Lurn

  • Ok, you need to debug why it still enters:

    00> <debug> app: DFU mode requested via GPREGRET.

    after you cleared it. 

    Can you please show me how you clear the register (set it to 0)?

    BR,
    Edvin

  • Can you please show me how you clear the register (set it to 0)?

    In nrf_bootloader.c It have the function dfu_enter_flags_clear(); and my code ran into there

    nrf_power_gpregret_set(nrf_power_gpregretget() & ~ BOOTLOADER_DFU_START);

    after then I use nrf_power_gpregretget() to get value again, and the value is 0;

    Now, I have a new discovery.

    Before then, I program all the hex, they only have bootloader logs without application logs.

    But, when I program all the hex, and debug the application, I found that I can see the application logs but no bootloader logs.

    I set a break point in my main.c before the code run to my function enter_dfu();

    It was triggered again, and the time between triggered, it not much different from NRF_BL_DFU_INACTIVITY_TIMEOUT_MS.

    So, I change the time value of the macro, and the time interval was also changed.

    I think maybe it was enter the application, It's just reset by application and return to DFU (because my function is in the front of the main();)?

    But why is there no log printing?

    BR,

    Lurn

  • Hello Lurn,

    It may be that if RTT logging is enabled in both the bootloader and the application, that when you open an RTT terminal, it will only find the first one. I am not too familiar with the details, but it uses RAM that the debugger reads out. If it finds a dedicated buffer in the bootloader, it may stop searching, and don't look for the buffer from the application.

    If the bootloader is working, you can use the non-debug version of the bootloader, so that the RTT viewer will find the application. Alternatively, you can try to open several RTT viewers, where you specify what address to open. You can find where the RTT buffers are located by reading out the RAM:

    nrfjprog --memrd 0x20000000 --n 0x10000 >> ram_dump.txt

    When I tested this, I got:

    This is on address 0x20003EB4 (it is the 5th byte on line 0x20003EB0, starting from 0). 

    When I enter this address manually in RTT viewer, I can see the log:

    So you need to find both the strings in RAM saying "SEGGER RTT", and open these addresses manually. Note that when you search for SEGGER RTT, they may not be on one line, so if you can't find one of them, search for "SEG" and "RTT", and you will probably find it. 

    BR,
    Edvin

Related