DFU approach from cloud to ESP32 to nRF52840

Hi,

My setup include a nRF52840-DK board that has an ESP32 WiFi module connected to it via UART. The idea is to source the new firmware from a server located in the cloud.

GCC toolchain,

Running FreeRTOS,

SDK 15.2.0

I am getting really confused after reading all the information on DFU and how I should be doing it. Simon also recently posted an article on DFU using Connect SDK https://devzone.nordicsemi.com/guides/nrf-connect-sdk-guides/b/software/posts/ncs-dfu

However, we are not using NCS at the moment.

Questions that I asked myself or still confused about are:

  1. Should I be using background DFU or should I be modifying the bootloader to perform the DFU?
  2. Where do I get the bin file from? I have a .zip package from the build output. Is that the bin file to use?
  3. What is an init packet? Is that the .dat file that comes in the .zip package? How do you trigger the init packet? Via application or bootloader?
  4. What is this bootloader settings file?
  5. If I am using dual bank update, how do I specify the flash address for the second bank where the updated firmware gets written to?
  6. How to let the bootloader knows that there is a new firmware in the second bank for validation and swap over? 
  7. What transport should I be looking at? I assume serial - UART?

My initial approach is to write my own in a simplified manner.

The application will issue HTTP GET to the server and retrieve data chunks of the binary until the whole bin file is received. As it receives the chunks, it writes to a flash location.

After the whole bin file is received, the CPU reboots and the application copies the new firmware, overriding the old firmware in place.

Will that "upset" the bootloader when it reboots next time seeing that the firmware signature is different from the one being overwritten?

This is not foolproof as there is no validation and checks for data corruption. It's also not the "proper" way that Nordic perform DFU.

I hope someone can help with those questions and shed some light on the best method to approach this (given my setup, NRF52-ESP32-cloud).

What are the articles that I should focus reading up on. 

Parents
  • Hi Jason, 

    If you are working with nRF5SDK then the article from Simon is not relevant as it's applied for NCS SDK. 

    Could you let me know how you are setting up the ESP and the NRF52 in your application ? Where the main application running on ? Are you using the ESP32 as the connectivity chip or the main application running on it? This would decide how the background DFU should work in your case. 

    You mentioned "I have a .zip package from the build output". I'm not aware of a toolchain that can build the .zip output, could you elaborate more how your build system consist of ? Usually we use nrfutil.exe tool to generate .zip file. 

    Regarding your question about bootloader setting you can have a look here. I have a blog post here that covers a little bit about bootloader settting and also give you some explanation on how the bootloader works. You can also find the link to a background DFU example at the end of the blog. 

    What we do in the background DFU approach is to receive the image to bank 1 (swap bank , defined in the bootloader setting) and after the image is fully received, write to the bootloader setting about the progress and then reset to the bootloader to do post validation and the actual image swap. 

    You can also find the Background DFU example in Thread and Zigbee SDK where we receive the image via Thread/Zigbee and then reset to bootloader to do the swap. 

  • Hi Hung, thanks for your support.

    The ESP32 connects to the nrf52840 DK board via UART and the nrf52 issues AT commands to it to send and receive data to the cloud. The main application runs on the nrf52 and ESP32 is purely for connectivity. 

    The build system we are using is CMake with GCC and at the end of the CMakeList file, there are rules to make DFU archives using the nrfutil.

    In the light of this, can you recommend the best approach to undertake for our system? Will it be background DFU? If so, I will focus on making background DFU happen.

    From your suggestion, it seems like we do not need to modify the bootloader code, only the bootloader settings need to be modified? Where can I find the example code for a suitable bootloader?

    Thanks for the links, I will have a good read about them.

    Hope to hear from you soon.

Reply
  • Hi Hung, thanks for your support.

    The ESP32 connects to the nrf52840 DK board via UART and the nrf52 issues AT commands to it to send and receive data to the cloud. The main application runs on the nrf52 and ESP32 is purely for connectivity. 

    The build system we are using is CMake with GCC and at the end of the CMakeList file, there are rules to make DFU archives using the nrfutil.

    In the light of this, can you recommend the best approach to undertake for our system? Will it be background DFU? If so, I will focus on making background DFU happen.

    From your suggestion, it seems like we do not need to modify the bootloader code, only the bootloader settings need to be modified? Where can I find the example code for a suitable bootloader?

    Thanks for the links, I will have a good read about them.

    Hope to hear from you soon.

Children
  • Hi Jason, 

    You are right. In your case the nRF52 application should do the main job of getting the image and storing it into bank1 memory (background DFU). 

    And it's correct that you don't need to modify the bootloader for the task as it should be compatible except for declaring NRF_DFU_IN_APP=1 in sdk_config.h
    What you need to do in the application is to write to bootloader setting when you are done receiving the image. 

    I haven't looked into the background DFU example for awhile, but my suggestion is to look at these functions: 

    - nrf_dfu_req_handler_on_req() inside that on_data_obj_execute_request_sched() is important, it's where the image trunks are received and once it's fully received, nrf_dfu_validation_post_data_execute() -> postvalidate() will be called. 
    When you reset the bootloader the bootloader will do this: 

    It will start the progress of swapping the image.

    In the application, settings need to be written nrf_dfu_settings_write_and_backup() inside on_data_obj_execute_request_sched() 

  • Thanks Hung, that should get me off the ground.

    Couple of questions.

    1. How do I set or find where Bank1 address is allocated in Flash memory? Because the app needs to point to the starting address to start writing to it and also to be sure it's at least after main application size in flash.

    2. Maybe because I have 2 sdk_config.h files, one used for the main app and the other for the bootloader project, however I can't find the symbol NRF_DFU_IN_APP=1 in both configs.

    3. Do I set the following to 1 in both sdk_config.h files for app and bootloader?

    NRF_DFU_SETTINGS_ALLOW_UPDATE_FROM_APP
    NRF_DFU_SETTINGS_IN_APP
    NRF_DFU_FORCE_DUAL_BANK_APP_UPDATES
    They are currently set to zero.
    4. On my copy of on_data_obj_execute_request_sched(), where is the part that's receiving the image chunks and writing to flash? I am having trouble finding those operations. Also it mentioned about scheduler, is the function using back the same FreeRTOS scheduler I have running for the application or is it a specific one provided by Nordic SDK?

     

    5. In my copy of nrf_bootloader.c module, I don't see the lines you highlighted in the picture. Maybe I have a different version from yours? I've attached a copy of mine.

  • Hi Jason, 


    I think we need to align the SDK version that you are using. There were some change between SDK v15.2 and SDK v15.3
    I was looking at SDK v15.3 . And I would suggest to port from v15.2 to SDK v15.3 , Here is what I have in on_data_obj_execute_request_sched()

    It's important that you find a working example of background DFU and can actually do some background DFU to test. After we can use it as the golden sample to port it to your application. 

    I'm not sure if I have pointed you to the example by my coworker Vidar in my blog here.  Could you please try to test if it works for you ? 

  • Thanks Hung, I will see if I can update my SDK version.

    Can you help with question 1 please?

  • Hi Jason, 

    Please have a look at the function nrf_dfu_bank1_start_addr() in nrf_dfu_utils.c . It's used in this function update_data_addr_get() 

    Basically Bank1 starts right after Bank0 . So it dynamically changes depending on the size of the application which placed at bank0. This is only applied for dual bank update.  

Related