nrf52840 S140 Central DFU Bluetooth Zephyr 2.0.0 nrf52840 peripheral

We have nrf52840 S140 BLE Central device that currently connects to TI based sensors. I have implemented code that can upgrade those TI sensors' firmware using the TI BLE protocol.

Now we are developing our own BLE peripheral sensors also based on the nrf52840 but now using the newly supported Zephyr 2.0.0. RF connect stuff. I can update the sensors using the Nordic Android program (unauthenticated for now) and now need to implement upgrading BLE DFU using our central device which connects to a cellular gateway.

I do not want to reinvent the wheel, writing existing code, like I had to do with the TI sensors.

Could you point me to code that allows a Central device to update a peripheral device BLE DFU?

If not where can I look to reinvent another wheel?

Thanks David

Parents
  • Hi David,

    I did not change Simons list function.

    It worked as is. But I have not tried to upload a new image yet, meaning only 1 image lives on the device.
    It only lists 1 slot in this case. I suspect it will list 2 slots if I upload an image to the secondary slot.

    I will let you know when I have tested this.

    Regards,
    Sigurd Hellesvik

  • I am able to use Simons sample to upload images in v2.0.0.

    However, it fails in v2.2.0, and I have not been able to figure out why yet.

    Regards,
    Sigurd Hellesvik

  • DavidKaplan said:
    If I understand you wanted to try the upload, list, confirm(fails) & again list sequence?

    Yes.

    DavidKaplan said:
    Like I wrote I calculated a checksum on the data buffers sent with the bt_dfu_smp_command() function and verified it was correct.

    Thanks, it is nice to know this, for reference.

    DavidKaplan said:
    When I do a upload, list, test, reset sequence no problems are reported but the image is not updated after reset

    When doing "list", we can see that "pending: true". If an image is set as "pending", MCUboot should swap the image into the primary slot on reboot.
    It is odd that MCUboot does not do so.

    As I do not have your devices, I can not replicate this exactly.
    However, it worked on nRF52840DKs for me.
    Do you have 2x nRF52840DKs by chance? (Or other nordic developement kits?)
    I am thinking that if you can try on the DKs VS you custom board, we can find if it is the hardware or the software which is the issue here.

    DavidKaplan said:
    Like I wrote I calculated a checksum on the data buffers sent with the bt_dfu_smp_command() function and verified it was correct.

    This reinforces my "this should work, why does it not?" thoughts.

    DavidKaplan said:

    I also used the "nrfjprog --family nRF52 --readcode code.hex" command so I could try to compare part of the code with the app_update.bin or merged.hex.

    I see in my sensor bootloader map that it does not have the littlefs mapped.

    Should this matter since if the phone app works ours should too?

    Good thinking!

    It is likely not app_update.bin itself, as the phone app works.

    But maybe it is a difference to which address the application is uploaded to?
    In that case, the "test" tag could maybe be in the wrong place for MCUboot to find it?

    Can you try to see if there is any difference to the code if you upload it using a mobile and the SMP Client?
    To get the image into secondary slot using mobile, upload it and "test only". Then restart twice to make it swap back into the secondary slot.

    After reading out the code, can you try to list the mobile-uploaded image using the SMP Client?
    Then also try to "confirm" the mobile-uploaded image using the SMP client?
    That way we can learn if it is the "upload" or "test" that fails.

    DavidKaplan said:

    By the way do you know if there were any changes to power management from v2.0.2 to v2.2.0?

    It seems that v2.2.0 consumes more current for

    I might ask you to open a new ticket on this.
    But I want to give it a try first.
    Do you have numbers on the current draw before and after?

    Regards,
    Sigurd Hellesvik

  • I have a nRF9160-DK which has a nRF52480 chip on it and according to the documentation, one of its uarts is always routed to the board's virtual com port. I wanted to use it as my Central device while writing a PC program that would simulate our host for streaming the image. I could see the messages coming from the DK on my PC but nothing I sent arrived at the Central. I selected the nrf9160dk_nrf52840 Nordic board for this build. I guess something is wrong with my hardware, so I could not write and debug the host simulator.

     I also have a nRF52840-DK which it nRF USB does not work (no recognition now on PC but previously had worked) so I could not also use it for the Central.

     I can send you the sensor (peripheral) code in a private session in which I remarked the hardware stuff.

    As for the current drain when compiled with V2.2.0 I will have to recheck the comparison, since I remember that management wanted to up the default tx power.

    Currently I manipulate only the I2C & SPI interfaces. Our LC512 EEPROM is I2C and the LSM6DSL sensor is connected by SPI. I also use the ADC which is used only every 5 to 15 minutes which taking a vibration sample. I use the code below pm_device_action_run() & pm_device_busy_set() & pm_device_busy_clear()

    //-----------------------------------------------------------------------------
    // ami_boardPMActivate
    //  Description
    //    Changes the  I2C's or SPI's PM activate state 
    //  Parameters
    //   which
    //   bActivate  -
    //  Returns
    //    true if OK
    //-----------------------------------------------------------------------------
    bool ami_boardPMActivate(unsigned char which,bool bActivate)
    {
    #ifdef CONFIG_PM_DEVICE
      int err = 1;
      enum pm_device_action action = bActivate?PM_DEVICE_ACTION_TURN_ON:PM_DEVICE_ACTION_TURN_OFF;
      switch (which){
        case AMI_BOARD_DEV_SPI1:
          err = pm_device_action_run((const struct device*)spi_dev,action);
          if (err!=-EALREADY && err!=-ENOTSUP){
              d_printf(LINE_INFO,kDbg_Error|kDbg_Display,"SPI state Err:%d",err);
          }
          break;
        case AMI_BOARD_DEV_I2C0:
          err = pm_device_action_run((const struct device*)i2c_dev,action);
          if (err!=-EALREADY && err!=-ENOTSUP){
              d_printf(LINE_INFO,kDbg_Error|kDbg_Display,"I2C state Err:%d",err);
          }
          break;
      } // switch
      return (err==0 || (err==-EALREADY));
    #endif       
    } // ami_boardPMActivate
    
    //-----------------------------------------------------------------------------
    // ami_boardChangeBusyState
    //  Description
    //    Changes the  I2C's or SPI's PM Busy state 
    //  Parameters
    //   which
    //   bSetBusy  -
    //  Returns
    //-----------------------------------------------------------------------------
    void ami_boardChangeBusyState(unsigned char which,bool bSetBusy)
    {
    #ifdef CONFIG_PM_DEVICE
      switch (which){
        case AMI_BOARD_DEV_SPI1:
          //-------------------------------------------------------------------
          // Mark a device as busy.
          // Devices marked as busy will not be suspended when the system goes into low-power states. 
          // This can be useful if, for example, the device is in the middle of a transaction.
          //-------------------------------------------------------------------
          if (bSetBusy){
            pm_device_busy_set(spi_dev);
          }else{
                pm_device_busy_clear(spi_dev);
          }
          break;
        case AMI_BOARD_DEV_I2C0:
          //-------------------------------------------------------------------
          // Mark a device as busy.
          // Devices marked as busy will not be suspended when the system goes into low-power states. 
          // This can be useful if, for example, the device is in the middle of a transaction.
          //-------------------------------------------------------------------
          if (bSetBusy){
            pm_device_busy_set(i2c_dev);
          }else{
                pm_device_busy_clear(i2c_dev);
          }
          break;
        case AMI_BOARD_DEV_GPIO0:
          if (bSetBusy){
            pm_device_busy_set(gpio_0_dev);
          }else{
                pm_device_busy_clear(gpio_0_dev);
          }
          break;
        case AMI_BOARD_DEV_GPIO1:
          if (bSetBusy){
            pm_device_busy_set(gpio_1_dev);
          }else{
                pm_device_busy_clear(gpio_1_dev);
          }
          break;
      } // switch
       
    #endif
    } // ami_boardChangeBusyState
    

    After not really getting anywhere yesterday on the BLE DFU issue, this morning I had some interesting findings. It seems that the DFU upload reports OK but the code is NOT written anywhere, assuming that readcode reads the whole internal code flash.

    1) Tool Chain V2.2.0 Update SDK
    2) Erase board with programmer
    3) Flash LastUpdate ={"14-Feb-2023 v1.0.0"}; merged file with programmer EraseAll Erase&Write
    4) nrfjprog --family nRF52 --readcode code1.hex
    5) DFU with gateway
    	00> [ami_smp.c: 690] DFU:316800/319026
    	00> [ami_smp.c: 690] DFU:317200/319026
    	00> [ami_smp.c: 690] DFU:317600/319026
    	00> [ami_smp.c: 690] DFU:318000/319026
    	00> [ami_smp.c: 690] DFU:318400/319026
    	00> [ami_smp.c: 690] DFU:318800/319026
    	00> [ami_smp.c: 791] ImageChecksum AF3A0C7A
    	00> [ami_smp.c: 917] SMP UploadOK
    	00> [ami_smp.c:1198] ImageList
    	00>
    	00> -----------PRIMARY IMAGE-----------
    	00>       slot: 0
    	00>       version: 0.0.0
    	00>       hash: 0xb34a6ec0abb87ccee95d838d9dbe4e5c33fae249c4ce955adc9a5297a8655d
    	00>       bootable: true
    	00>       pending: false
    	00>       confirmed: true
    	00>       active: true
    	00>       permanent: false
    	00>
    	00> -----------SECONDARY IMAGE-----------
    	00>       slot: 1
    	00>       version: 0.0.0
    	00>       hash: 0x4165b6dabeb5dfab85e276b4e927b2e32358d38f1ef8d698617c5f449a095
    	00>       bootable: true
    	00>       pending: false
    	00>       confirmed: false
    	00>       active: false
    	00>       permanent: false
    	00> [ami_smp.c:1201] ImageTest
    	00>
    	00> -----------PRIMARY IMAGE-----------
    	00>       slot: 0
    	00>       version: 0.0.0
    	00>       hash: 0xb34a6ec0abb87ccee95d838d9dbe4e5c33fae249c4ce955adc9a5297a8655d
    	00>       bootable: true
    	00>       pending: false
    	00>       confirmed: true
    	00>       active: true
    	00>       permanent: false
    	00>
    	00> -----------SECONDARY IMAGE-----------
    	00>       slot: 1
    	00>       version: 0.0.0
    	00>       hash: 0x4165b6dabeb5dfab85e276b4e927b2e32358d38f1ef8d698617c5f449a095
    	00>       bootable: true
    	00>       pending: true
    	00>       confirmed: false
    	00>       active: false
    	00>       permanent: false
    	00> [ami_smp.c:1204] ImageReset
    	00> 14/02/2023 19:17:31[ami_ble.c: 861] Disconnected: D4:FD:9F:BF:4A:27 (random) (reason 8)
    	00> [ami_ble.c:2639] DFUConnectFinishedErr:0
    6) nrfjprog --family nRF52 --readcode code2.hex
     code1.hex & code2.hex are exactly the same.
     This means that the SMP upload reported OK but did not write anything.
    5) Phone Test only (which works)
     In the sensor code after reset, I confirm the image, so test is like confirm, if the code runs.
      //---------------------------------------------------------------------------
      // DFU upgraded and not confirmed, confirm
      //---------------------------------------------------------------------------
      if (!boot_is_img_confirmed()){
        err = boot_write_img_confirmed();
    	  if (err) {
    		  d_printf(LINE_INFO,kDbg_Error|kDbg_Display,"BootConfirmErr:%d",err);
        }else{
              d_printf(LINE_INFO,kDbg_Error|kDbg_Display,"BootConfirmed");
        }
      }
    4) nrfjprog --family nRF52 --readcode code3.hex
      code3.hex is entirely different from code1.hex and code2.hex which were the same.
    
    

    Thanks

    David

  • This morning I programmed my nRF9160-DK with our sensor code with the hardware specific code commented out. I performed a nRF52840 BLE DFU by SMP which reported that all went well but the unit was not updated. I suggest, if possible, I send the sensor code which runs on the nRF9160-DK and you build two images with different Device Information, one which you flash by the programmer and the other that you program to your Central's flash as you did in the Generic SMP BLE DFU test you performed.

    This way we could pinpoint if the problem is in my Central or Sensor code.

    Using the nRF Connect phone app you can verify the DFU and see in my code if the problem exists in my peripheral sensor code or not. 

    My code uses ncs V2.2.0 with a local ms88sf2 board definition which should run on any nRF52840 board.

    I can only upload my code in a private session.

    Thanks David

    static int settings_runtime_load(void)
    {
      char sTemp[32];	
      eight_bytes unique_64;
      
    #if defined(CONFIG_BT_DIS_SETTINGS)
    #ifdef TBD
    	settings_runtime_set("bt/dis/model",
    			     "Zephyr Model",
    			     sizeof("Zephyr Model"));
    	settings_runtime_set("bt/dis/manuf",
    			     "Zephyr Manufacturer",
    			     sizeof("Zephyr Manufacturer"));
    #endif				 
    #if defined(CONFIG_BT_DIS_SERIAL_NUMBER)
        //-------------------------------------------------------------------------
        // Use nRF52840's DeviceID as serial number
        //-------------------------------------------------------------------------
        unique_64.u32[0] = NRF_FICR->DEVICEID[0];
        unique_64.u32[1] = NRF_FICR->DEVICEID[1];
        sprintf(sTemp,"%08X%08X",unique_64.u32[1],unique_64.u32[0]);
    	settings_runtime_set("bt/dis/serial",
    			     sTemp,
    			     strlen(sTemp));
    #endif
    #if defined(CONFIG_BT_DIS_SW_REV)
        //-------------------------------------------------------------------------
    	// Set the software version
        //-------------------------------------------------------------------------
        sprintf(sTemp,"%u.%u %u.%u",
                AMI_VERSION_MAJOR,AMI_VERSION_MINOR,
                AQUA_DEVEL_VERSION_MAJOR,AQUA_DEVEL_VERSION_MINOR);
    	settings_runtime_set("bt/dis/sw",
    			     sTemp,
    			     strlen(sTemp));
    #endif
    #if defined(CONFIG_BT_DIS_FW_REV)
        //-------------------------------------------------------------------------
    	// Set Date as the Firmware version
        //-------------------------------------------------------------------------
        sprintf(sTemp,"%s",__DATE__);
    	settings_runtime_set("bt/dis/fw",
    			     sTemp,
    			     strlen(sTemp));
    #endif
    #if defined(CONFIG_BT_DIS_HW_REV)
    	settings_runtime_set("bt/dis/hw",
    			     CONFIG_BT_DIS_HW_REV_STR,
    			     sizeof(CONFIG_BT_DIS_HW_REV_STR));
    #endif
    #endif
    	return 0;
    } // settings_runtime_load
    
    

  • Hi David,

    That sounds good to me!

    Please create a new private ticket to upload your project and tag me with in the new ticket.

    Regards,
    Sigurd Hellesvik

  • I will continue here:

    I have now run your project with two nRF52840DKs.

    The DFU uploads fine, but the MCUboot verification of the project fails with the error:

    *** Booting Zephyr OS build v3.2.99-ncs1 ***
    I: Starting bootloader
    I: Primary image: magic=unset, swap_type=0x1, copy_done=0x3, image_ok=0x3
    I: Secondary image: magic=good, swap_type=0x2, copy_done=0x3, image_ok=0x3
    I: Boot source: none
    I: Swap type: test
    E: Image in the secondary slot is not valid!
    I: Bootloader chainload address offset: 0xc000
    *** Booting Zephyr OS build v3.2.99-ncs1 ***
    

    Is this the same error that you get?

    Tomorrow, I will try to do some more testing with this.

    Regards,
    Sigurd Hellesvik

Reply
  • I will continue here:

    I have now run your project with two nRF52840DKs.

    The DFU uploads fine, but the MCUboot verification of the project fails with the error:

    *** Booting Zephyr OS build v3.2.99-ncs1 ***
    I: Starting bootloader
    I: Primary image: magic=unset, swap_type=0x1, copy_done=0x3, image_ok=0x3
    I: Secondary image: magic=good, swap_type=0x2, copy_done=0x3, image_ok=0x3
    I: Boot source: none
    I: Swap type: test
    E: Image in the secondary slot is not valid!
    I: Bootloader chainload address offset: 0xc000
    *** Booting Zephyr OS build v3.2.99-ncs1 ***
    

    Is this the same error that you get?

    Tomorrow, I will try to do some more testing with this.

    Regards,
    Sigurd Hellesvik

Children
  •  This is to me very good news which means you can reproduce my problem so it is most likely not central related or your fix on your central can be easily copied.

     Whenever the DFU works, I will need to change the key and I think a signature.

    On my sensor board I don't have any uart interface. With the SWD debugger interface, I do not see any bootloader messages regarding the bootloader but maybe you added a define.

    Almost always I got some messages dropped.

    *** Booting Zephyr OS build v3.2.99-ncs1 ***
    [00:00:00.036,773] <inf> mcumgr_zephyr_grp: zephyr_basic_mgmt_init: Registering Zephyr basic mgmt group
    00/00/0000 00:00:00[ami_main.c: 628] Startup
    00/00/0000 00:00:00[ami_cfg.c: 256] DeviceID:51
    00/00/0000 00:00:00[ami_lsm6dsl.c:1905] Sensor x:32724 y:32742 z:11246
    00/00/0000 00:00:00[ami_lsm6dsl.c:1931] accel x: ms/2 y: ms/2 z: ms/2
    00/00/0000 00:00:00[ami_led.c: 139] LedThread
    00/00/0000 00:00:00[ami_lsm6dsl.c: 120] RdLSM6DSLThread
    00/00/0000 00:00:00[ami_lsm6dsl.c: 153] NewSample
    00/00/0000 00:00:00[ami_adc.c: 470] RdLSM6DSLThread
    [00:00:03.496,063] <inf> bt_hci_core: hci_vs_init: HW Platform: Nordic Semiconductor (0x0002)
    --- 3 messages dropped ---
    [00:00:03.496,093] <inf> bt_hci_core: hci_vs_init: HW Variant: nRF52x (0x0002)
    [00:00:03.496,124] <inf> bt_hci_core: hci_vs_init: Firmware: Standard Bluetooth controller (0x00) Version 109.16784 Build 2917677098
    [00:00:03.496,582] <inf> bt_[0m
    8
    0m
    

    Thanks David

  • DavidKaplan said:
    Almost always I got some messages dropped.

    This is related to the Zephyr Logging module. If you lof too fast, some of the logs will get dropped. You can fix this by tweaking Logging configurations.

    On to the DFU issue:

    Since DFU works using mobile but not the SMP Client, I figure it must be the SMP Client with the error.
    So I added some logging to the mcumgr receiving end to compare messages received from mobile vs SMP Client:

    diff --git a/subsys/mgmt/mcumgr/lib/cmd/img_mgmt/src/img_mgmt.c b/subsys/mgmt/mcumgr/lib/cmd/img_mgmt/src/img_mgmt.c
    index 8c7dc330db..c5b7818bb8 100644
    --- a/subsys/mgmt/mcumgr/lib/cmd/img_mgmt/src/img_mgmt.c
    +++ b/subsys/mgmt/mcumgr/lib/cmd/img_mgmt/src/img_mgmt.c
    @@ -371,6 +371,20 @@ img_mgmt_upload(struct mgmt_ctxt *ctxt)
            ok = zcbor_map_decode_bulk(zsd, image_upload_decode,
                    ARRAY_SIZE(image_upload_decode), &decoded) == 0;
     
    +    static int once = 1;
    +    if(once){
    +        once = 0;
    +        printk("ARRAY_SIZE(image_upload_decode): [%d]\n",ARRAY_SIZE(image_upload_decode));
    +        printk("req.off [%d]\n", req.off);
    +        printk("req.size [%ld]\n", req.size);
    +        printk("req.upgrade [%d]\n", req.upgrade);
    +        printk("req.image [%d]\n", req.image);
    +        printk("req.img_data.len [%d]\n", req.img_data.len);
    +        printk("req.img_data.value [%d]\n", req.img_data.value);
    +        printk("req.data_sha.len [%d]\n", req.data_sha.len);
    +        printk("req.data_sha.value [%d]\n", req.data_sha.value);
    +    }
    +
            IMG_MGMT_UPLOAD_ACTION_SET_RC_RSN(&action, NULL);
     
            if (!ok) {
    

    I found that the upload size/len in the smp message is the most significant difference here.

    So I changed this in the SMP Client to use the actual size and not Simon's static number.
    Now DFU works from the SMP Client to your sample:

    *** Booting Zephyr OS build v3.2.99-ncs1 ***
    I: Starting bootloader
    I: Primary image: magic=good, swap_type=0x2, copy_done=0x1, image_ok=0x1
    I: Secondary image: magic=good, swap_type=0x2, copy_done=0x3, image_ok=0x3
    I: Boot source: none
    I: Swap type: test
    I: Starting swap using move algorithm.
    I: Bootloader chainload address offset: 0xc000
    *** Booting Zephyr OS build v3.2.99-ncs1 ***
    [00:00:00.000,610] <inf> mcumgr_zephyr_grp: zephyr_basic_mgmt_init: Registering Zephyr basic mgmt group
    FFFFFFFFFFFFFFFFFFFFF
    00/00/0000 00:00:00[ami_main.c: 635] Startup
    00/00/0000 00:00:00[ami_cfg.c: 256] DeviceID:0
    00/00/0000 00:00:00[ami_main.c: 448] MainInitErr:4096
    [00:00:00.106,719] <inf> bt_hci_core: hci_vs_init: HW Platform: Nordic Semiconductor (0x0002)
    --- 3 messages dropped ---
    [00:00:00.106,750] <inf> bt_hci_core: hci_vs_init: HW Variant: nRF52x (0x0002)
    

    I put the change that I made in git:

    https://github.com/hellesvik-nordic/samples_for_nrf_connect_sdk/commit/f593bf073f609d76038f2b668783e5b0f485138e

    Can you try this change and see if it also fixes the DFU for you?

    Regards,
    Sigurd Hellesvik

  • I tried to duplicate your changes in my central code, but it did not help for some reason.

    So, I changed this in the SMP Client to use the actual size and not Simon's static number.

    In your code you use the constant slot start & end addresses from the pm.

    The flash_read() function will return, I think, when there is nothing more to read from the actual image.

    The upload_chunk is not changed from  UPLOAD_CHUNK during the upload.

    The length you write seems to be the size of the slot and not the image size.

    I could be wrong here.

    In any case doing something similar did not give an error but did not work.

    I did not add anything in the sensor code to try to see what is happening in the log yet.

    I changed only the central code.

    I hope to continue on this tomorrow.

    So I should use the slot size or the image size in the first packet?

    In the last packet show which is not divisible by upload_chunk, should I pad it by 0xFFs or 0x00 or does it matter?

    Thank you, David

    if(off == 0){
      zcbor_tstr_put_lit(zse, "len");
      zcbor_uint64_put(zse, (uint64_t)last_addr-start_addr);

      // ?!? 

      //  PM_MCUBOOT_SECONDARY_END_ADDRESS- PM_MCUBOOT_SECONDARY_ADDRESS
    }

    int last_addr = PM_MCUBOOT_SECONDARY_END_ADDRESS;
    int start_addr = PM_MCUBOOT_SECONDARY_ADDRESS;

  • DavidKaplan said:
    So I should use the slot size or the image size in the first packet?

    From SMP: Image upload:

    "“len”: optional length of an image, it only appears in the first packet of request, where “off” is 0"

    DavidKaplan said:
    So, I changed this in the SMP Client to use the actual size and not Simon's static number.

    Yes, I think that is how we want to do it in the end. For now, I just set len to the entire length of the Secondary Slot (PM_MCUBOOT_SECONDARY_END_ADDRESS - PM_MCUBOOT_SECONDARY_ADDRESS), in case there is some footer set at the end of the slot.
    Then when we get the full upload to work, we can try decreasing the length.

    DavidKaplan said:
    In the last packet show which is not divisible by upload_chunk, should I pad it by 0xFFs or 0x00 or does it matter?

    I think this is handled by the code already?

    		if(curr_addr+UPLOAD_CHUNK > last_addr){
    			upload_chunk = last_addr - curr_addr;
    			update_complete = true;
    		}
    

    Regards,
    Sigurd Hellesvik

  • OK, you are of course correct about the last block and upload_chuck being updated.

    My Central code reports that the DFU goes well but the nRF9160-DK and my custom end units still do not upgrade.

     The image checksum compared to my harddrive is the same.

    [ami_smp.c: 676] DFU:317200/319026
    [ami_smp.c: 676] DFU:317600/319026
    [ami_smp.c: 676] DFU:318000/319026
    [ami_smp.c: 676] DFU:318400/319026
    [ami_smp.c: 676] DFU:318800/319026
    [ami_smp.c: 777] ImageChecksum AF3A0C7A
    [ami_smp.c: 911] SMP UploadOK
    [ami_smp.c:1192] ImageList
    
    -----------PRIMARY IMAGE-----------
          slot: 0
          version: 0.0.0
          hash: 0x76d196d413b84fe1177ba6c33a79744f579a07298a6a282d97ffd7a73d82ee6
          bootable: true
          pending: false
          confirmed: true
          active: true
          permanent: false
    
    -----------SECONDARY IMAGE-----------
          slot: 1
          version: 0.0.0
          hash: 0x4165b6dabeb5dfab85e276b4e927b2e32358d38f1ef8d698617c5f449a095
          bootable: true
          pending: false
          confirmed: false
          active: false
          permanent: false
    [ami_smp.c:1195] ImageTest
    
    -----------PRIMARY IMAGE-----------
          slot: 0
          version: 0.0.0
          hash: 0x76d196d413b84fe1177ba6c33a79744f579a07298a6a282d97ffd7a73d82ee6
          bootable: true
          pending: false
          confirmed: true
          active: true
          permanent: false
    
    -----------SECONDARY IMAGE-----------
          slot: 1
          version: 0.0.0
          hash: 0x4165b6dabeb5dfab85e276b4e927b2e32358d38f1ef8d698617c5f449a095
          bootable: true
          pending: true
          confirmed: false
          active: false
          permanent: false
    [ami_smp.c:1198] ImageReset
    22/02/2023 20:49:50[ami_ble.c: 861] Disconnected: C0:F1:EE:C6:31:44 (random) (reason 8)
    [ami_ble.c:2639] DFUConnectFinishedErr:0
    

    #define UPLOAD_CHUNK		400 // (50 worked) This has to be at least 32 bytes, since first it has to send the whole header (which is 32 bytes)
    void send_upload2(void)
    {
            uint8_t       data[UPLOAD_CHUNK+1]; // One more byte, to store '/0'
    	    zcbor_state_t zse[2];
      	    size_t        payload_len;
    		int           start_addr   = 0; // AMI_VIBEBT_PM_MCUBOOT_SECONDARY_ADDRESS; 
    		int           last_addr    = 0; // AMI_VIBEBT_PM_MCUBOOT_SECONDARY_ADDRESS+ami_state->dfu.ImageSize.ulong; 
    		int           curr_addr    = 0; // AMI_VIBEBT_PM_MCUBOOT_SECONDARY_ADDRESS;
    		int           upload_chunk = UPLOAD_CHUNK;
    		int           err;
            uint64_t      off = 0;
    	    bool          update_complete = false;
            uint8_t       encode_len;
    
    		ami_state->DFUErr                 = AMI_SMP_DFU_ERR_OK;
            ami_state->dfu.uAddChecksum.word  = 0;
            ami_state->dfu.uXORChecksum       = 0;
    		while (!update_complete){
    			struct smp_buffer smp_cmd;
    			zcbor_new_encode_state(zse, ARRAY_SIZE(zse), smp_cmd.payload,sizeof(smp_cmd.payload), 0);
    			//-----------------------------------------------------------------
    			// Wait until response is received until sending the next chunk
    			//-----------------------------------------------------------------
    			// ?!? err = k_sem_take(&upload_sem, K_MSEC(AMI_DFU_MAX_SEND_ACK_MS));		    
    			k_sem_take(&upload_sem, K_FOREVER);
    			last_addr    = ami_state->dfu.ImageSize.ulong;
                err = 0;
    			if (ami_state->DFUErr){
    			  d_printf(LINE_INFO,kDbg_Error|kDbg_Host,"SMPErr:%u",ami_state->DFUErr);
    			  update_complete = true;
    			  break;
    			}
    			//-------------------------------------------------------
    			// Disconnected?
    			//-------------------------------------------------------
    			if (!atomic_get(&ble_connected)){
    			  ami_state->DFUErr = AMI_DFU_ERR_DISCONNECTED;
    			  update_complete = true;
    			  break;
    			}
    			//-----------------------------------------------------------------
    			// No Error but semiphore times out!
    			//-----------------------------------------------------------------
    			if (err){
    			  ami_state->DFUErr = AMI_SMP_DFU_ERR_LOOP_TIMEOUT;
    			  update_complete = true;
    			  break;
    			}
    			//-----------------------------------------------------------------
    			// Last block?
    			//-----------------------------------------------------------------
    			if ((curr_addr+UPLOAD_CHUNK) > last_addr){
    				upload_chunk = last_addr - curr_addr;
    				update_complete = true;
    			}
    			progress_print(curr_addr-start_addr,last_addr-start_addr);
    			//-----------------------------------------------------------------
    			// Get the data block from ringbuffer
    			//-----------------------------------------------------------------
    			ami_state->DFUErr = ami_smp_RetDataBlock(data,upload_chunk);
    			if (ami_state->DFUErr){ 
    			  update_complete = true;
    			  break;
    			}
    			//-----------------------------------------------------------------
    			// First block add image size
    			//-----------------------------------------------------------------
    			off = curr_addr - start_addr;
    			if (off == 0){
    				encode_len = 8;
    			} else {
    				encode_len = 6;
    			}
    			data[upload_chunk] = '\0';
    			zse->constant_state->stop_on_error = true;
    			zcbor_map_start_encode(zse, encode_len);
    			zcbor_tstr_put_lit(zse, "image");
    			zcbor_int64_put(zse, 0);
    			zcbor_tstr_put_lit(zse, "data");
    			zcbor_bstr_put_lit(zse, data);
    			if(off == 0){
    				zcbor_tstr_put_lit(zse, "len");
    				zcbor_uint64_put(zse, (uint64_t)last_addr-start_addr);
    			}
    			zcbor_tstr_put_lit(zse, "off");
    			zcbor_uint64_put(zse, off);
    			if(off == 0){
    				zcbor_tstr_put_lit(zse, "sha");
    				zcbor_bstr_put_lit(zse, "12345");
    			}
    			zcbor_tstr_put_lit(zse, "upgrade");
    			zcbor_bool_put(zse, false);
    			zcbor_map_end_encode(zse, encode_len);
    
    			if (!zcbor_check_error(zse)) {
    				d_printf(LINE_INFO,kDbg_Error|kDbg_Host,"Failed to encode SMP test packet, err: %d", zcbor_pop_error(zse));
    				ami_state->DFUErr = AMI_SMP_DFU_ERR_UPLOAD_ENCODE;
    				break;
    			}
    			curr_addr+=upload_chunk;
    			payload_len = (size_t)(zse->payload - smp_cmd.payload);
    			smp_cmd.header.op = 2; /* write request */
    			smp_cmd.header.flags = 0;
    			smp_cmd.header.len_h8 = (uint8_t)((payload_len >> 8) & 0xFF);
    			smp_cmd.header.len_l8 = (uint8_t)((payload_len >> 0) & 0xFF);
    			smp_cmd.header.group_h8 = 0;
    			smp_cmd.header.group_l8 = 1; /* IMAGE */
    			smp_cmd.header.seq = 0;
    			smp_cmd.header.id  = 1; /* UPLOAD */
    			//-----------------------------------------------------------------
    			// ZCBOR error?
    			//-----------------------------------------------------------------
    			err = bt_dfu_smp_command(&dfu_smp,smp_upload_rsp_proc,sizeof(smp_cmd.header)+payload_len,&smp_cmd); 
    			if (err){
    			  d_printf(LINE_INFO,kDbg_Error|kDbg_Host,"bt_dfu_smp_command failed with %d", err);
    			  ami_state->DFUErr = AMI_SMP_DFU_ERR_SEND;
    			  break;
    			}
    		} // while
    		if (!ami_state->DFUErr){
    		  ami_smp_PrintChecksums();
    		  d_printf(LINE_INFO,kDbg_General|kDbg_Host,"SMP UploadOK");
    		}
      	    atomic_set(&smp_finished,true);
    } // send_upload2
    

    Could you please send me your nRF9160-Dk or other board's child mcuboot.conf file and the prg.conf file that you tested?

    Is the child mcuboot.conf file just additions to the default mcuboot prog.conf file?

     I still can't get the bootloader to output anything in the sensor's RTT log, but I see the additional printks

    00> ARRAY_SIZE(image_upload_decode): [6]
    00> req.off [0]
    00> req.size [319026]
    00> req.upgrade [0]
    00> req.image [0]
    00> req.img_data.len [400]
    00> req.img_data.value [536969252]
    00> req.data_sha.len [5]
    00> req.data_sha.value [536969671]

    (Connection lost)
    00> SEGGER J-Link V7.66a - Real time terminal output
    00> J-Link OB-K22-NordicSemi compiled Nov  7 2022 16:21:34 V1.0, SN=960005601
    00> Process: JLinkGDBServerCL.exe
    00> [00:00:00.035,827] <err> LSM6DSL: lsm6dsl_init: Failed to initialize chip
    00> *** Booting Zephyr OS build v3.2.99-ncs1 ***
    00> [00:00:00.036,529] <inf> mcumgr_zephyr_grp: zephyr_basic_mgmt_init: Registering Zephyr basic mgmt group
    00> 00/00/0000 00:00:00[ami_main.c: 631] Startup
    00> 00/00/0000 00:00:00[ami_cfg.c: 256] DeviceID:0
    00> 00/00/0000 00:00:00[ami_main.c: 448] MainInitErr:4096
    00> 00/00/0000 00:00:00[ami_main.c: 657] VaporBLE#0 23-Feb-2023 v1.0.0 1.0 2.23
    00> build time: Feb 23 2023 08:27:22
    00> [00:00:00.141,448] <inf> sdc_hci_driver: hci_driver_open: SoftDevice Controller build revision:
    00>                                          6d 90 41 2a 38 e8 ad 17  29 a5 03 38 39 27 d7 85 |m.A*8... )..89'..
    00>                                          1f 85 d8 e1                                      |....
    00> [00:00:00.145,721] <inf> bt_hci_core: hci_vs_init: HW Platform: Nordic Semiconductor (0x0002)
    00> [00:00:00.146,240] <inf> bt_hci_core: hci_vs_init: HW Variant: nRF52x (0x0002)
    00> [00:00:00.146,728] <inf> bt_hci_core: hci_vs_init: Firmware: Standard Bluetooth controller (0x00) Version 109.16784 Build 2917677098
    00> [00:00:00.147,827] <inf> bt_hci_core: bt_init: No ID address. App must call settings_load()
    00> 00/00/0000 00:00:00[ami_ble.c: 506] ActualTxPwr:8
    00> 00/00/0000 00:00:00[ami_ble.c: 788] Bluetooth initialized
    00> [00:00:00.149,383] <wrn> bt_hci_core: bt_set_name: Unable to store name
    00> [00:00:00.150,299] <inf> bt_hci_core: bt_dev_show_info: Identity: C0:F1:EE:C6:31:44 (random)
    00> [00:00:00.150,817] <inf> bt_hci_core: bt_dev_show_info: HCI: version 5.3 (0x0c) revision 0x11fa, manufacturer 0x0059
    00> [00:00:00.151,458] <inf> bt_hci_core: bt_dev_show_info: LMP: version 5.3 (0x0c) subver 0x11fa
    00> [00:00:00.152,191] <wrn> bt_hci_core: bt_set_name: Unable to store name
    00> 00/00/0000 00:00:00[ami_ble.c: 555] UpdateAdv x:0 y:0 z:0 Tmp:0 F:0x20
    00> 00/00/0000 00:00:00[ami_ble.c: 593] AdvertisingStarted
    00> 00/00/0000 00:00:00[ami_main.c: 676] BootConfirmed
    00> 00/00/0000 00:00:00[ami_main.c: 683] ResetCause:1
    00> [00:00:00.169,036] <err> bt_gatt: db_hash_store: Failed to save Database Hash (err -2)
    00> 01/01/2004 00:00:01[ami_adc.c: 470] RdLSM6DSLThread
    00> 01/01/2004 00:00:26[ami_main.c: 143] Connected
    00> 01/01/2004 00:00:26[ami_main.c: 198] LE PHY updated: TX PHY LE 2M, RX PHY LE 2M
    00> 01/01/2004 00:00:31[ami_main.c: 175] Connection parameters updated.
    00>  interval: 40, latency: 0, timeout: 42
    00> 01/01/2004 00:00:34[ami_main_serv.c:  58] Received data, handle 0, conn 0x20002860
    00> 22/02/2023 20:30:10[ami_main.c: 153] Disconnected reason:19
    00> 22/02/2023 20:30:10[ami_ble.c: 555] UpdateAdv x:0 y:0 z:0 Tmp:0 F:0x0
    00> 22/02/2023 20:30:10[ami_ble.c: 593] AdvertisingStarted
    00> 22/02/2023 20:30:11[ami_ble.c: 555] UpdateAdv x:0 y:0 z:0 Tmp:0 F:0x0
    00> 22/02/2023 20:30:35[ami_main.c: 601] NewMin
    00> 22/02/2023 20:31:24[ami_main.c: 143] Connected
    00> 22/02/2023 20:31:25[ami_main.c: 198] LE PHY updated: TX PHY LE 2M, RX PHY LE 2M
    00> 22/02/2023 20:31:29[ami_main.c: 175] Connection parameters updated.
    00>  interval: 40, latency: 0, timeout: 42
    00> ARRAY_SIZE(image_upload_decode): [6]
    00> req.off [0]
    00> req.size [319026]
    00> req.upgrade [0]
    00> req.image [0]
    00> req.img_data.len [400]
    00> req.img_data.value [536969252]
    00> req.data_sha.len [5]
    00> req.data_sha.value [536969671]
    00> 22/02/2023 20:31:34[ami_main.c: 175] Connection parameters updated.
    00>  interval: 9, latency: 0, timeout: 42
    00> 22/02/2023 20:31:35[ami_main.c: 601] NewMin
    00> 22/02/2023 20:32:35[ami_main.c: 601] NewMin
    00> [00:00:00.035,827] <err> LSM6DSL: lsm6dsl_init: Failed to initialize chip
    00> *** Booting Zephyr OS build v3.2.99-ncs1 ***
    00> [00:00:00.036,499] <inf> mcumgr_zephyr_grp: zephyr_basic_mgmt_init: Registering Zephyr basic mgmt group
    00> 00/00/0000 00:00:00[ami_main.c: 631] Startup
    00> 00/00/0000 00:00:00[ami_cfg.c: 256] DeviceID:0
    00> 00/00/0000 00:00:00[ami_main.c: 448] MainInitErr:4096
    00> 00/00/0000 00:00:00[ami_main.c: 657] VaporBLE#0 23-Feb-2023 v1.0.0 1.0 2.23
    00> build time: Feb 23 2023 08:27:22
    00> [00:00:00.141,448] <inf> sdc_hci_driver: hci_driver_open: SoftDevice Controller build revision:
    00>                                          6d 90 41 2a 38 e8 ad 17  29 a5 03 38 39 27 d7 85 |m.A*8... )..89'..
    00>                                          1f 85 d8 e1                                      |....
    00> [00:00:00.145,721] <inf> bt_hci_core: hci_vs_init: HW Platform: Nordic Semiconductor (0x0002)
    00> [00:00:00.146,240] <inf> bt_hci_core: hci_vs_init: HW Variant: nRF52x (0x0002)
    00> [00:00:00.146,728] <inf> bt_hci_core: hci_vs_init: Firmware: Standard Bluetooth controller (0x00) Version 109.16784 Build 2917677098
    00> [00:00:00.147,827] <inf> bt_hci_core: bt_init: No ID address. App must call settings_load()
    00> 00/00/0000 00:00:00[ami_ble.c: 506] ActualTxPwr:8
    00> 00/00/0000 00:00:00[ami_ble.c: 788] Bluetooth initialized
    00> [00:00:00.149,383] <wrn> bt_hci_core: bt_set_name: Unable to store name
    00> [00:00:00.150,299] <inf> bt_hci_core: bt_dev_show_info: Identity: C0:F1:EE:C6:31:44 (random)
    00> [00:00:00.150,817] <inf> bt_hci_core: bt_dev_show_info: HCI: version 5.3 (0x0c) revision 0x11fa, manufacturer 0x0059
    00> [00:00:00.151,458] <inf> bt_hci_core: bt_dev_show_info: LMP: version 5.3 (0x0c) subver 0x11fa
    00> [00:00:00.152,191] <wrn> bt_hci_core: bt_set_name: Unable to store name
    00> 00/00/0000 00:00:00[ami_ble.c: 555] UpdateAdv x:0 y:0 z:0 Tmp:0 F:0x20
    00> 00/00/0000 00:00:00[ami_ble.c: 593] AdvertisingStarted
    00> 00/00/0000 00:00:00[ami_main.c: 676] BootConfirmed
    00> 00/00/0000 00:00:00[ami_main.c: 683] ResetCause:1
    00> [00:00:00.169,036] <err> bt_gatt: db_hash_store: Failed to save Database Hash (err -2)
    00> 01/01/2004 00:00:01[ami_adc.c: 470] RdLSM6DSLThread

     

    Thanks David

Related