Using the DFU Target Library

We use a custom board implementation based on nrf52840 that makes use of a proprietary host transport protocol.

I am trying to implement  FOTA using our transport. We can successfully download the app_update.bin file that is created when using NCS to create the boot images.

I would like to confirm that by using the DFU Target Library I can update the image slot and reboot to the new image.

Is there anything special I need in order to do this?

Second question:

The app_update.bin image is downloaded to external flash. Could you possibly provide me with suggestions as to the external flash configuration should I wish to specify the secondary slot for DFU. We are using QSPI with an MX25R6435FM2IL0 flash chip. The image is downloaded to an offset of 0x300000.

Thank you

Parents Reply Children
  • Hi - I have started this implementation. I have included the DFU TARGET in prj.conf. It seems that there is more require as CONFIG_DFU_TARGET_MCUBOOT does ot get set to 1, so the whole thing fails.

    Can you tell me apart from CONFIG_DFU_TARGET=y, what else must be set for me to be able to use DFU Traget with my custom DFU implementation.

    See attached prj.conf and my code for DFU.At the time I start the process, the latest image has already been downloaded into the external flash.

    572725.prj.conf

    /********************************************************************
    FileName:     	mydfu.c
    Dependencies: 	See INCLUDES section
    ********************************************************************
    File Description:
    
    performs dfu update
    
    Change History:
    Rev   Date         Description
    1.0   Aug 2023    Initial release
    
    ********************************************************************/
    #include <zephyr/kernel.h>
    #include <zephyr/drivers/flash.h>
    #include <zephyr/device.h>
    #include <zephyr/devicetree.h>
    #include <stdio.h>
    #include <string.h>
    #include "besecure.h"
    #include "storage.h"
    #include "mydfu.h"
    #include "statled.h"
    #include "events.h"
    #include "watchdog.h"
    #include "dfu/dfu_target.h"
    #include <zephyr/logging/log.h>
    #include <dfu/dfu_target_mcuboot.h>
    
    #define LOG_MODULE_NAME MyDFU
    LOG_MODULE_REGISTER(LOG_MODULE_NAME);
    
    #define CONFIG_DFU_TARGET_MCUBOOT
    
    typedef enum
    {
      d_init,
      d_loop,
      d_err,
      d_done
    } dfuState;
    
    /** V A R I A B L E S */
    
    static enum dfu_target_image_type img_type;
    dfuState dstate;
    const struct device *flash_dv = DEVICE_DT_GET(DT_ALIAS(spi_flash0));
    int rcod;
    uint32_t dfuaddr;
    uint32_t fragsiz;
    int32_t dfutot;
    char dfubuff[2048];
    
    extern uint32_t FWTotal;         // total size of fw
    
    static void dfu_target_callback_handler(enum dfu_target_evt_id evt)
    {
    	switch (evt) {
    	case DFU_TARGET_EVT_TIMEOUT:
    		break;
    	case DFU_TARGET_EVT_ERASE_DONE:
    		break;
    	}
    }
    
    //
    //	Main entry point for the user interface state machine
    //
    void dfuMac(void)
    {
     	int err;
       
      switch (dstate)
      {
        case d_init:                  // we get here at startup
        {
          if (sysStat.rdSOFT == 1)
          {
            dfuaddr = 0x300000;
            // read in first block
            rcod = flash_read(flash_dv, dfuaddr, (char*)&dfubuff, (size_t)2048);
            dfuaddr = dfuaddr + 2048;
            if (rcod != 0)
            {
              dstate = d_err;
            }
            else
            {
              // get image type
              fragsiz = 2048;
              img_type = dfu_target_img_type((char*)&dfubuff,	fragsiz);
              // init
              err = dfu_target_init(img_type, 0, FWTotal, dfu_target_callback_handler);
              if (err == -EFBIG) {
                LOG_ERR("%s", "Image too big");
                dstate = d_err;
              } else if (err < 0) {
                LOG_ERR("dfu_target_init error %d", err);
                dstate = d_err;
              }
              dfutot = FWTotal;       // size we have to process
              fragsiz = 2048;         // first fragment is always 2K
              dstate = d_loop;
            }        
          }
          break;
        }
    
        case d_loop:        // process fragment
        {
          err = dfu_target_write(&dfubuff, fragsiz);
          if (err && err == -EINVAL) {
            LOG_INF("%s", "Image refused");
            dstate = d_err;
          } else if (err != 0) {
            LOG_ERR("dfu_target_write error %d", err);
            dstate = d_err;
          }
          // update our total
          dfutot = dfutot - fragsiz;
    
          // see if we are done
          if (dfutot == 0)
          {
            dstate = d_done;
          }
          else
          {
            if (dfutot <= 2048)
            {
              fragsiz = dfutot;
            }
    
            // read in next block
            rcod = flash_read(flash_dv, dfuaddr, (char*)&dfubuff, fragsiz);
            if (rcod != 0)
            {
              dstate = d_err;
            }
          }
          break;
        }
    
        case d_err:
        {
          err = dfu_target_reset();
          if (err != 0) {
            LOG_ERR("Unable to reset DFU target, err: %d", err);
          }      
          sysStat.rdSOFT = 0;
          break;
        }
    
       case d_done:
       {
    		err = dfu_target_done(true);
    		if (err == 0) {
    			err = dfu_target_schedule_update(0);
          sysStat.rdSOFT = 0;
    		}
        break;
       }
    
       
      }  // end switch
    } // end dfumac
    
    

  • Hi Francois, 
    Which issue do you have when you set CONFIG_DFU_TARGET_MCUBOOT=y ?

    I don't see that in your prj.conf. 

    Normally I would double check in the \build\zephyr\include\generated\autoconfig.h to see if the configuration is set to 1 or 0. VSCode may give wrong interpretation. 


    Could you try taking a look at the \modules\lib\memfault-firmware-sdk\examples\nrf-connect-sdk\nrf9160\memfault_demo_app sample ? 
    The sample uses fota_download library (which in turn uses dfu_target) to receive image. 

Related