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.

  • 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

  • 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

Related