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