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

  • 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

  •  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

Related