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

OTA Thread DFU: Merge SDK example with custom application

Hi all!

I'm able to fully test the SDK example https://infocenter.nordicsemi.com/index.jsp?topic=%2Fsdk_tz_v3.2.0%2Fthread_example_dfu.html and it works pretty well.

Now, the next step is the integration of this OTA DFU over Thread example in my custom application (that already exploits Thread and MQTT-SN protocol).

I haven't found a tutorial that explains step-by-step this kind of operation. 

Basically I need some help to integrate the DFU client with the user application. I think the key point is the IoT SDK CoAP library that implement a DFU algorithm that should run concurrently to the user application, but I'm a bit confused about merging process.

Thanks in advance,

Alessio

Parents
  • I think I need some clarifications about flashing different FW components.

    In order to have the OTA DFU example working, I have to flash:

    • mbr_nrf52_2.4.1_mbr.hex (MBR)
    • nrf52840_xxaa_mbr.hex (BOOTLOADER)
    • dfu_client.hex (EXAMPLE HEX)

    In order to have my application working, I have to flash:

    • s140_nrf52_7.0.1_softdevice.hex (SOFTDEVICE)
    • my_app.hex (APPLICATION HEX)

    At the moment, I have merged the two application codes and, let's say, I have the  

    my_app_DFU.hex

    I have tried to flash all the components:

    1. mbr_nrf52_2.4.1_mbr.hex (MBR)
    2. nrf52840_xxaa_mbr (BOOTLOADER)
    3. s140_nrf52_7.0.1_softdevice.hex (SOFTDEVICE)
    4. my_app_DFU.hex (APPLICATION+DFU HEX)

    I received back this when I flash the SD

    and this when I flash the application

    Moreover, the dongle is stucked with the green led lit up.

    Maybe I am supposed to do some mergehex operations?

    Thanks,

    Alessio 

     

  • Hi,

    You do not need to flash both the MBR and Softdevice HEX-files. The MBR is merged into the softdevice, and you will find that if you do a compare, the first page (0x0 - 0x1000) will be identical.

    The Bootloader needs information about the application in order to verify that it is a valid application. This means that you either needs to generate the settings using nrfutil, or create a DFU packet of the application and "flash" it using the DFU process. 

    I recommend that you follow the instructions in the Testing section of the Thread Secure OTA DFU Example, especially steps 3.c-d.

    Best regards,
    Jørgen 

  • Sorry but I didn't get your point.

    I generate the priv_key as 1.a and I use it when I generate the DFU package 

    nrfutil pkg generate --hw-version 52 --sd-req 0xCA --application-version 2 --application SAMBA_Node_DFU.hex --key-file priv.pem app_dfu_package.zip

    I generate also the public_key and I drag it into my project explorer.

    I totally miss point 1.c as I don't have that path in my custom project

  • By default, the DFU client example uses our public debug-key, found in examples\dfu\dfu_public_key.c. This key only works with the test-images for BLE/serial DFU, found in examples\dfu\secure_dfu_test_images. If you did not include the file containing the debug-key in your project, it should work fine to drag in the generated public key like you describe. Including both or none of the files should give compile errors, so I guess that should not be the issue here.

  • Ah ok, I thought that the public key was used also to generate the bootloader hex file.

    I had a try generating a new  nrf52840_xxaa_mbr.hex (bootloader) file copying my new public key in examples\dfu\dfu_public_key.c but I keep having the "prevalidation failed" error.

    I'm pretty sure this error has something to do with keys.

    EDIT: I put a debug message to get which is the error cause

    From nrf_dfu_req_handler.h I can see:

    NRF_DFU_RES_CODE_INVALID_OBJECT          = 0x05,    //!< Data object does not match the firmware and hardware requirements, the signature is wrong, or parsing the command failed.

    So I think that:

    • Or it is a problem of keys and so I need some help to understand what is wrong in my approach
    • Or it is a problem of --sd-req 0xCA (I put 0xCA cause my app exploits s140_nrf52_7.0.1_softdevice.hex but I don't know if it is the right approach since DFU example used --sd-req 0x00)

    Thanks in advance,

    AS 

  • EDIT: Finally, with an hardcoded debug session, I found where my code failed

    How can I solve "Signature failed" error?

    I had the attention to use the same public key to compile bootloader and code, and the private key (from which I generated the public key) to create the app_dfu_package.zip

  • This reply was deleted.
Reply Children
  • UPDATE

    I found that I didn't have this macro on my custom app

    while It is present in the DFU example.

    I added it and now the FW crashes when I start the DFU process.

    The blue mark indicates where the crash happens.

    I think that macro should be in my app, so the problem is that the app crashes.

    Thanks in advance,

    Alessio

  • UPDATE

    I think I found the bug finally.

    My problem is that when the board starts the update, it starts erasing flash memory where there is the Softdevice so It crashes.

    I had a try with a version of my application that doesn't exploit the SD and the DFU starts normally.

    I think something must be changed in the DFU example code to adapt it with a custom application that includes the softdevice.

    I don't wanna update also the SD, but just the application.

    Do you have any ideas which are the required steps? 

    I can attach the debug during the crash

    Seems like there is a problem with 0x000FF000 memory slot, where there is the bootloader_settings_page

    IIs it normal that the DFU application tries to erase settings memory space?

    Moreover I don't know if it is normal this data when I generate the settings with

    $ nrfutil settings generate --family NRF52840 --application SAMBA_Node.hex --application-version 1 --bootloader-version 1 --bl-settings-version 2 settings.hex

    I think i'm using a bootloader compiled without the Softdevice options set...

  • UPDATE

    Also if I use the NOSD version of my application I have the crash.

    The DFU process stucks at 33% 

    and my client starts rebooting continuosly.

    This is the log of the client

    As with the SD version, it tries to erase and write at 0xFF000 where there is the bootloader_setting_page and the FW crashes.

    I think the new data written in 0XFF000 are wrong in some way and then the process can't go ahead.

    Anyone has a tip for this? I'm out of ideas.

  • Are you using the same sdk_config.h configurations in your application as the Thread DFU client example? If you could post your full project, it would be easier to debug the application and help you find the root cause of the issue. If you do not want to share in public, I can convert the case to a private one.

  • Hi Jorgen,

    unfortunatly at the moment I can't share the project with third parties, I need to check the policy with my company.

    I compared the Thread DFU client sdk_config (that I copied-pasted in my project) with the one of my project. I found these main differences (other small differences are about LOG but I think they are useless)

    This is what I have in the Thread DFU client sdk_config:

    // <e> MEM_MANAGER_ENABLED - mem_manager - Dynamic memory allocator
    //==========================================================
    #ifndef MEM_MANAGER_ENABLED
    #define MEM_MANAGER_ENABLED 1
    #endif
    // <o> MEMORY_MANAGER_SMALL_BLOCK_COUNT - Size of each memory blocks identified as 'small' block.  <0-255> 
    
    #ifndef MEMORY_MANAGER_SMALL_BLOCK_COUNT
    #define MEMORY_MANAGER_SMALL_BLOCK_COUNT 8
    #endif
    
    // <o> MEMORY_MANAGER_SMALL_BLOCK_SIZE -  Size of each memory blocks identified as 'small' block. 
    // <i>  Size of each memory blocks identified as 'small' block. Memory block are recommended to be word-sized.
    
    #ifndef MEMORY_MANAGER_SMALL_BLOCK_SIZE
    #define MEMORY_MANAGER_SMALL_BLOCK_SIZE 128
    #endif
    
    // <o> MEMORY_MANAGER_MEDIUM_BLOCK_COUNT - Size of each memory blocks identified as 'medium' block.  <0-255> 
    
    #ifndef MEMORY_MANAGER_MEDIUM_BLOCK_COUNT
    #define MEMORY_MANAGER_MEDIUM_BLOCK_COUNT 4
    #endif
    
    // <o> MEMORY_MANAGER_MEDIUM_BLOCK_SIZE -  Size of each memory blocks identified as 'medium' block. 
    // <i>  Size of each memory blocks identified as 'medium' block. Memory block are recommended to be word-sized.
    
    #ifndef MEMORY_MANAGER_MEDIUM_BLOCK_SIZE
    #define MEMORY_MANAGER_MEDIUM_BLOCK_SIZE 256
    #endif
    
    // <o> MEMORY_MANAGER_LARGE_BLOCK_COUNT - Size of each memory blocks identified as 'large' block.  <0-255> 
    
    #ifndef MEMORY_MANAGER_LARGE_BLOCK_COUNT
    #define MEMORY_MANAGER_LARGE_BLOCK_COUNT 2
    #endif
    
    // <o> MEMORY_MANAGER_LARGE_BLOCK_SIZE -  Size of each memory blocks identified as 'large' block. 
    // <i>  Size of each memory blocks identified as 'large' block. Memory block are recommended to be word-sized.
    
    #ifndef MEMORY_MANAGER_LARGE_BLOCK_SIZE
    #define MEMORY_MANAGER_LARGE_BLOCK_SIZE 1024
    #endif

    This is what I have in my application:

    // <e> MEM_MANAGER_ENABLED - mem_manager - Dynamic memory allocator
    //==========================================================
    #ifndef MEM_MANAGER_ENABLED
    #define MEM_MANAGER_ENABLED 1
    #endif
    // <o> MEMORY_MANAGER_SMALL_BLOCK_COUNT - Size of each memory blocks identified as 'small' block.  <0-255> 
    
    
    #ifndef MEMORY_MANAGER_SMALL_BLOCK_COUNT
    #define MEMORY_MANAGER_SMALL_BLOCK_COUNT 64
    #endif
    
    // <o> MEMORY_MANAGER_SMALL_BLOCK_SIZE -  Size of each memory blocks identified as 'small' block. 
    // <i>  Size of each memory blocks identified as 'small' block. Memory block are recommended to be word-sized.
    
    #ifndef MEMORY_MANAGER_SMALL_BLOCK_SIZE
    #define MEMORY_MANAGER_SMALL_BLOCK_SIZE 64
    #endif
    
    // <o> MEMORY_MANAGER_MEDIUM_BLOCK_COUNT - Size of each memory blocks identified as 'medium' block.  <0-255> 
    
    
    #ifndef MEMORY_MANAGER_MEDIUM_BLOCK_COUNT
    #define MEMORY_MANAGER_MEDIUM_BLOCK_COUNT 16
    #endif
    
    // <o> MEMORY_MANAGER_MEDIUM_BLOCK_SIZE -  Size of each memory blocks identified as 'medium' block. 
    // <i>  Size of each memory blocks identified as 'medium' block. Memory block are recommended to be word-sized.
    
    #ifndef MEMORY_MANAGER_MEDIUM_BLOCK_SIZE
    #define MEMORY_MANAGER_MEDIUM_BLOCK_SIZE 256
    #endif
    
    // <o> MEMORY_MANAGER_LARGE_BLOCK_COUNT - Size of each memory blocks identified as 'large' block.  <0-255> 
    
    
    #ifndef MEMORY_MANAGER_LARGE_BLOCK_COUNT
    #define MEMORY_MANAGER_LARGE_BLOCK_COUNT 4
    #endif
    
    // <o> MEMORY_MANAGER_LARGE_BLOCK_SIZE -  Size of each memory blocks identified as 'large' block. 
    // <i>  Size of each memory blocks identified as 'large' block. Memory block are recommended to be word-sized.
    
    #ifndef MEMORY_MANAGER_LARGE_BLOCK_SIZE
    #define MEMORY_MANAGER_LARGE_BLOCK_SIZE 512
    #endif

    Do you think this could have an impact?

    Another question, I thought that the DFU process (at least the single bank approach) was carried out by bootloader (so the application is stopped). So what's the meaning of this macro? 

    // <q> NRF_DFU_IN_APP  - Specifies that this code is in the app, not the bootloader, so some settings are off-limits.
     
    
    // <i> Enable this to disable writing to areas of the settings that are protected
    // <i> by the bootlader. If this is not enabled in the app, certain settings write
    // <i> operations will cause HardFaults or will be ignored. Enabling this option
    // <i> also causes postvalidation to be disabled since this is meant to be done
    // <i> in the bootloader. NRF_BL_DFU_ALLOW_UPDATE_FROM_APP must be enabled in the bootloader.
    
    #ifndef NRF_DFU_IN_APP
    #define NRF_DFU_IN_APP 1
    #endif

    And why it is called "background" DFU if the application is stopped anyway?

    If the application is carrying out the DFU process is pretty easy to understand that I can't use the single bank approach (since che app can't erase itself if it is running). I need some clarifications about this.

    Thanks in advance,

    Alessio

Related