nrf9160 Modem Delta Update write error

Hi,

we have been trying to implement modem delta updates to our nrf9160 project using DFU target.
We send delta .bin file over LTE to our device, and save it to external flash. Then we start copying from external flash to modem using DFU target functions.

The write procedure runs ok until last couple of addresses, when it fails at the end.

We use same procedure for our own sw update (MCUBOOT image type), and it is working OK.

RTT debug shows following:

Start of update once file is on external flash:

00> 1: TransferFile.cpp - TransferFile_CopySerialFlashToFlash: Size = 213896

00> [00:01:51.450,714] <inf> nrf_modem_lib_trace: Modem was turned off, no more traces
00> [00:01:52.659,790] <inf> nrf_modem_lib_trace: Trace thread ready
00> [00:01:52.667,846] <inf> nrf_modem_lib_trace: Trace level override: 2
00> 1: Bootloader.cpp - Modem Delta Area Size: 294912
00> [00:01:52.687,866] <inf> dfu_target_modem_delta: Modem firmware version: dc8e7aff-5331-409e-be02-5529dffa5537
00> [00:01:52.697,265] <inf> dfu_target_modem_delta: Deleting firmware image, this can take several minutes
00> 1: Bootloader.cpp - prDfuTargetCallbackHandler: Event = 0
00> 1: Bootloader.cpp - prDfuTargetCallbackHandler: Event = 2
00> [00:01:56.932,891] <inf> dfu_target_modem_delta: Modem FW delete complete
00> 1: Bootloader.cpp - Bootloader_WriteApplication: prImgType = 2
00> 1: Bootloader.cpp - Bootloader_WriteApplication: 0x00000000 - 0x000000FF 256 Success = 0


it all goes smooth until last part:

00> 1: Bootloader.cpp - Bootloader_WriteApplication: 0x00033E00 - 0x00033EFF 256 Success = 0
00> 1: Bootloader.cpp - Bootloader_WriteApplication: Write OK
00> 1: Bootloader.cpp - Bootloader_WriteApplication: 0x00033F00 - 0x00033FFF 256 Success = 0
00> 1: Bootloader.cpp - Bootloader_WriteApplication: Write OK
00> 1: Bootloader.cpp - Bootloader_WriteApplication: 0x00034000 - 0x000340FF 256 Success = 0
00> 1: Bootloader.cpp - Bootloader_WriteApplication: Write OK
00> 1: Bootloader.cpp - Bootloader_WriteApplication: 0x00034100 - 0x000341FF 256 Success = 0
00> 1: Bootloader.cpp - Bootloader_WriteApplication: Write OK
00> 1: Bootloader.cpp - Bootloader_WriteApplication: 0x00034200 - 0x000342FF 256 Success = 0
00> 1: Bootloader.cpp - Bootloader_WriteApplication: Write OK
00> 1: Bootloader.cpp - Bootloader_WriteApplication: 0x00034300 - 0x000343FF 256 Success = 0
00> [00:02:18.249,084] <err> dfu_target_modem_delta: Write failed, modem error 2
00> 1: Bootloader.cpp - Bootloader_WriteApplication: Write ERROR: -7
00> 1: Bootloader.cpp - Bootloader_WriteApplication: 0x00034400 - 0x000344FF 256 Success = 0
00> [00:02:18.265,197] <err> dfu_target_modem_delta: Write failed, modem error 14
00> [00:02:18.265,777] <inf> dfu_target_modem_delta: Deleting firmware image, this can take several minutes
00> 1: Bootloader.cpp - prDfuTargetCallbackHandler: Event = 0
00> 1: Bootloader.cpp - prDfuTargetCallbackHandler: Event = 2
00> [00:02:22.510,528] <inf> dfu_target_modem_delta: Modem FW delete complete
00> [00:02:22.519,744] <err> dfu_target_modem_delta: Write failed, modem error 22
00> 1: Bootloader.cpp - Bootloader_WriteApplication: Write ERROR: -22
00> 1:   End!
00> 1: Bootloader.cpp - Bootloader_FinishedApplication
00> [00:02:22.542,724] <err> dfu_target_modem_delta: Modem firmware upgrade scheduling failed, incomplete data
00> 1:   dfu_target_schedule_update ERROR: -22



Here's the main function:

int TransferFile_CopySerialFlashToFlash(uint32_t Size)
{
  int loErr = 1;
  
#ifdef DEBUG
  Debug_Printf(DEBUG_STIMULUSPORT_USER_1, "TransferFile.cpp - TransferFile_CopySerialFlashToFlash: Size = %u", Size);
#endif

  if(Size < BOOTLOADER_APPICATION_SPACE_SIZE)
  {
    uint8_t loData[256];
    uint32_t loAddress = 0;
    uint32_t loEndAddress = Size + sizeof(loData);

    if(!Bootloader_EraseApplication())
      while(loAddress <= loEndAddress)
      {
        loErr = flash_read(prFlashDev, loAddress, loData, sizeof(loData));

#ifdef DEBUG_RECEIVING
        //Debug_Printf(DEBUG_STIMULUSPORT_USER_1, "TransferFile.cpp - TransferFileCopySerialFlashToFlash: Address: 0x%02x // EndAddress: 0x%02x // Size: 0x%02x", loAddress, loEndAddress, sizeof(loData)); TODO Andrej - začasno zakomentirano. lahko odstrani po testu
        if(loErr)
          Debug_Printf(DEBUG_STIMULUSPORT_USER_1, "  flash_read ERROR: %i", loErr);
#endif

        loErr = Bootloader_WriteApplication(loAddress, loData, sizeof(loData));
        loAddress += sizeof(loData);
      }

#ifdef DEBUG_RECEIVING
      Debug_Printf(DEBUG_STIMULUSPORT_USER_1, "  End!");
#endif

    Bootloader_FinishApplication();
  }

  return loErr;
}

And the WriteApplication():

bool Bootloader_WriteApplication(uint32_t Add, uint8_t *Ptr, uint16_t Len)
{
  int loErr;
  enum dfu_target_image_type loImgType;
  size_t loFileWriteOffset;

  if(prFirstFragment)
  {
  	prFirstFragment = false;

    loImgType = dfu_target_img_type(Ptr, Len);

    if((loImgType != DFU_TARGET_IMAGE_TYPE_MCUBOOT) && (loImgType != DFU_TARGET_IMAGE_TYPE_MODEM_DELTA))
    {
#if defined(DEBUG_INFO) 
      Debug_Printf(DEBUG_STIMULUSPORT_USER_1, "Bootloader.cpp - Bootloader_WriteApplication: dfu_target_img_type not DFU_TARGET_IMAGE_TYPE_MCUBOOT");
#endif
      return true;
    }
    
    if(loImgType == DFU_TARGET_IMAGE_TYPE_MCUBOOT)
      loErr = dfu_target_init(loImgType , 0, BOOTLOADER_APPICATION_SPACE_SIZE, prDfuTargetCallbackHandler);

    if(loImgType == DFU_TARGET_IMAGE_TYPE_MODEM_DELTA)
    {
      if(nrf_modem_lib_shutdown())
      {
        printk("Bootloader.cpp - Failed nrf_modem_lib_shutdown()\n");
        return true;
      }

      if(nrf_modem_lib_init())
      {
        printk("Bootloader.cpp - Failed nrf_modem_lib_init()\n");
        return true;
      }

      size_t loDeltaArea;
      nrf_modem_delta_dfu_area(&loDeltaArea);

      Debug_Printf(DEBUG_STIMULUSPORT_USER_1, "Bootloader.cpp - Modem Delta Area Size: %u", loDeltaArea);

      loErr = dfu_target_init(loImgType , 0, TransferSW_GetFileSize(), prDfuTargetCallbackHandler);  // TODO Andrej - tole je še treba določiti velikost
    }

    if(loErr)
    {
#if defined(DEBUG_INFO) 
      Debug_Printf(DEBUG_STIMULUSPORT_USER_1, "pBootloader.cpp - Bootloader_WriteApplication: dfu_target_init ERROR: %i", loErr);
#endif
      return true;
    }

#if defined(DEBUG_INFO)
    Debug_Printf(DEBUG_STIMULUSPORT_USER_1, "Bootloader.cpp - Bootloader_WriteApplication: prImgType = %d", loImgType);
#endif
  }

  if(loImgType == DFU_TARGET_IMAGE_TYPE_MCUBOOT)
  {
    dfu_target_offset_get(&loFileWriteOffset);
    Debug_Printf(DEBUG_STIMULUSPORT_USER_1, "Bootloader.cpp - Bootloader_WriteApplication: Add: 0x%02x || loFileWriteOffset: 0x%02x", Add, loFileWriteOffset);

    if(Add > loFileWriteOffset) // Če preskoči 0xFF, ... bloke, jih je potrebno zapisati!
    {
#if defined(DEBUG_INFO)
        Debug_Printf(DEBUG_STIMULUSPORT_USER_1, "Bootloader.cpp - Bootloader_WriteApplication: zapisovanje 0xFF blokov");
        uint8_t loBlockCnt = 0;
#endif

        uint8_t loDummyBuffer[MAX_PACKET_SIZE];
        memset(loDummyBuffer, 0xFF, sizeof(loDummyBuffer));

        while(Add > loFileWriteOffset)
        {
          loErr = dfu_target_write(loDummyBuffer, sizeof(loDummyBuffer));
          dfu_target_offset_get(&loFileWriteOffset);
#if defined(DEBUG_INFO)
          loBlockCnt++;
#endif
        }
#if defined(DEBUG_INFO)
        Debug_Printf(DEBUG_STIMULUSPORT_USER_1, "  Zapisanih %u 0xFF blokov!", loBlockCnt);
#endif
      }
  }

#if defined(DEBUG_INFO)
  Debug_Printf(DEBUG_STIMULUSPORT_USER_1, "Bootloader.cpp - Bootloader_WriteApplication: 0x%08X - 0x%08X %u Success = %i", Add, Add + Len - 1, Len, loErr);
#endif

  loErr = dfu_target_write(Ptr, Len);

  if(loErr)
  {
#if defined(DEBUG_INFO)
    Debug_Printf(DEBUG_STIMULUSPORT_USER_1, "Bootloader.cpp - Bootloader_WriteApplication: Write ERROR: %i", loErr);
#endif
  return true;
  }
  else
  {
#if defined(DEBUG_INFO)
    Debug_Printf(DEBUG_STIMULUSPORT_USER_1, "Bootloader.cpp - Bootloader_WriteApplication: Write OK");
#endif
    return false;
  }

}

The Bootloader_FinishApplication at end just calls dfu_Target_done() and dfu_target_schedule_update().
We also do modem library reinitialization before update just in case.

I suppose DFU Target takes care of scratch area and other stuff, that needs to be done for delta updates (stuff that is within nrf_modem_delta_dfu)?


We are using SDK 2.6.0 and modem FW 1.3.5 for this test, so we can update to 1.3.6
File that is being sent to device is: mfw_nrf9160_update_from_1.3.5_to_1.3.6.bin

EDIT:

There was unnecessary addition of Size + sizeof(loData) at start in TransferFile_CopySerialFlashToFlash(). This reduced the address to proper end address... but still fails at end.

> 1: Bootloader.cpp - Bootloader_WriteApplication: 0x00034200 - 0x000342FF 256 Success = 0
00> 1: Bootloader.cpp - Bootloader_WriteApplication: Write OK
00> 1: Bootloader.cpp - Bootloader_WriteApplication: 0x00034300 - 0x000343FF 256 Success = 0
00> [00:04:00.203,460] <err> dfu_target_modem_delta: Write failed, modem error 2
00> 1: Bootloader.cpp - Bootloader_WriteApplication: Write ERROR: -7
00> 1: End!
00> 1: Bootloader.cpp - Bootloader_FinishedApplication
00> [00:04:00.219,055] <err> dfu_target_modem_delta: Modem firmware upgrade scheduling failed, error 18
00> 1: dfu_target_schedule_update ERROR: -14


Thanks for help.

BR,
Andrej


Parents
  • Well, it seems that i managed to find the solution...

    It was in length of data being copied. When transferring data for modem delta update, they need to be exact size.... we used fixed block sizes for application (mcuboot image type)...
    Now that i changed code, so that only the size of the image is copied, the update works Slight smile

    I'm closing this ticket now...

Reply
  • Well, it seems that i managed to find the solution...

    It was in length of data being copied. When transferring data for modem delta update, they need to be exact size.... we used fixed block sizes for application (mcuboot image type)...
    Now that i changed code, so that only the size of the image is copied, the update works Slight smile

    I'm closing this ticket now...

Children
No Data
Related