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

  • I started to check this when I was pulled back off it for other critical things.

    Maybe tomorrow.

    I have three questions

    1) send_smp_reset

     In the Github code it looks like the fix you made to this function was not updated:

    Fix:
    smp_cmd.header.len_h8 = (uint8_t)((payload_len >> 8) & 0xFF);
    smp_cmd.header.len_l8 = (uint8_t)((payload_len >> 0) & 0xFF);

     GitHub;

    smp_cmd.header.len_h8 = 0;
    smp_cmd.header.len_l8 = 0;

    2) send_upload2

     In the packet format, the len should be always 0x5B68?

     I thought it was the image length but your image size in the example is not this.

       zcbor_tstr_put_lit(zse, "len");
       // zcbor_uint64_put(zse, (uint64_t)ami_state->dfu.ImageSize.ulong);
        zcbor_uint64_put(zse, (uint64_t)0x5B68);
    3) When I compile, I get a warning when string compare is used with a word and not a string.
    I guess this is OK from my previous debugging, I just try to get rid of warning so I will notice new ones.

    ami_smp.c:752:35: warning: multi-character character constant [-Wmultichar]
    752 | } else if(!strncmp(value.value, 'rc', 2)){


    zcbor_uint64_put(zse, (uint64_t)0x5B68);

    Thanks David

  • Another question.

    In send_upload2(), the start and last addresses are taken from the bootloader partisan.

    The image uploaded is of variable size.

    Does the current code just return with "flash_read failed with error:" ?

    Or where is the image file length used?

    int last_addr = PM_MCUBOOT_SECONDARY_END_ADDRESS;
    int start_addr = PM_MCUBOOT_SECONDARY_ADDRESS;

    ...

    err = flash_read(flash_dev, curr_addr, data, upload_chunk);
    if (err != 0) {
      printk("flash_read failed with error: %d\n", err);
      return;
    }

    Thanks David

  • Thanks for the feedback!

    DavidKaplan said:
     In the Github code it looks like the fix you made to this function was not updated:

    I forgot this, but I have now added a fix in https://github.com/hellesvik-nordic/samples_for_nrf_connect_sdk/commit/5ef3f25e179bb92c218433b95f0ebb874d66dfd5.

    DavidKaplan said:

    2) send_upload2

     In the packet format, the len should be always 0x5B68?

    I copied this example from Simon.
    Therefore, I do not know what the length is supposed to be.
    I suspect that he just set it to something for testing.
    Likely, the len should be found dynamically from the image.

    DavidKaplan said:
    3) When I compile, I get a warning when string compare is used with a word and not a string.
    I guess this is OK from my previous debugging, I just try to get rid of warning so I will notice new ones.

    ami_smp.c:752:35: warning: multi-character character constant [-Wmultichar]
    752 | } else if(!strncmp(value.value, 'rc', 2)){

    Should compare with "rc" instead of 'rc'.

    Fixed in https://github.com/hellesvik-nordic/samples_for_nrf_connect_sdk/commit/39946de56c0c325d5833fd581ba2a40f14267491

    DavidKaplan said:

    Does the current code just return with "flash_read failed with error:" ?

    Or where is the image file length used?

    You are right, we should be able to find the size of the uploaded image somehow, but I do not know how yet.

    I will look for it.
    Let me know if you figure out how.

    Regards,
    Sigurd Hellesvik

  • I am using ncsv2.0.2 and not ncsv2.2.0 so I tried to upgrade the projects and as usual, have a million compile errors. I just wish Zephyr understood that "improvements" should be backwards compatible or have a compatibility layer.

    I thought I got the sensor (smp server end unit to be upgraded) to compile and run (not checking current consumption).

    In my central code (smp client), I could not get the img_mgmt_impl_write_image_data() & img_mgmt_impl_erase_slot() to link. I use them when updating the central itself by uart serial connection. I did not see any new CONFIG defines. I commented out this code.

    I tried to perform an upgrade and the first time it seemed to upload the image without error but

    the test function returned an error.

    02-05 07:21 05/02/2023 05:21:20 |  04/02/2023 19:20:59[.ami_vibe.c:1941] ...[ami_smp.c:1249] DFU:374450/374648
    02-05 07:21 05/02/2023 05:21:20 |  04/02/2023 19:20:59[.ami_vibe.c:1941] ...[ami_smp.c:1249] DFU:374550/374648
    02-05 07:21 05/02/2023 05:21:20 |  04/02/2023 19:20:59[.ami_vibe.c:1941] ...[ami_smp.c:1692] ImageList
    02-05 07:21 05/02/2023 05:21:20 |  04/02/2023 19:20:59[.ami_vibe.c:1941] ...[ami_smp.c:1695] ImageTest
    02-05 07:21 05/02/2023 05:21:20 |  04/02/2023 19:20:59[.ami_vibe.c:1941] ...[ami_ble.c:2578] DFUConnectFinishedErr:11
    

    My error 11 is in the smp_list_rsp_proc() function when called by Test.

    		memcpy(images_key, value.value, value.len);
    		images_key[value.len] = '\0';
    		//d_printf(LINE_INFO,kDbg_Error,"Images key: %s",images_key);
    		ok = zcbor_list_start_decode(zsd);
    		if (!ok) {
    			d_printf(LINE_INFO,kDbg_Error,"Decoding error, start_decode images->list  (err: %d)", zcbor_pop_error(zsd));
    			ami_state->DFUErr = AMI_SMP_DFU_ERR_LIST_IMAGE_LIST;
    			goto smp_list_rsp_proc_end;
    		}
    

    The problem is also that I could not reproduce the upload success.

    When I run my v2.0.2 code setup and connect the debugged to the sensor, I get a hard fault.

     01/01/2004 00:03:11[ami_main.c: 142] Connected
    00> 
    00> 01/01/2004 00:03:12[ami_main.c: 197] LE PHY updated: TX PHY LE 2M, RX PHY LE 2M
    00> 
    00> [00:03:57.440,734] <err> bt_keys: Failed to save keys (err -2)
    00> 01/01/2004 00:03:12[ami_main.c: 258] Pairing completed:F5:62:56:E5:1A:0C (random), bonded:1
    00> 
    00> 01/01/2004 00:03:12[ami_main.c: 226] Security changed: F5:62:56:E5:1A:0C (random) level:2
    00> 
    00> 01/01/2004 00:03:17[ami_main.c: 174] Connection parameters updated.
    00> 
    00>  interval: 40, latency: 0, timeout: 42
    00> 
    00> 01/01/2004 00:03:21[ami_main.c: 174] Connection parameters updated.
    00> 
    00>  interval: 9, latency: 0, timeout: 42
    00> 
    00> [00:04:07.005,218] <inf> mcumgr_img_mgmt: Erased 0x6000 bytes of image slot
    00> [00:04:07.117,706] <inf> mcumgr_img_mgmt: Erased 0x1000 bytes of image slot trailer
    00> [00:04:07.117,736] <err> os: ***** BUS FAULT *****
    00> [00:04:07.117,736] <err> os:   Precise data bus error
    00> [00:04:07.117,767] <err> os:   BFAR Address: 0x2c6972cc
    00> [00:04:07.117,797] <err> os: r0/a1:  0x20017288  r1/a2:  0x00000df4  r2/a3:  0x0c680044
    00> [00:04:07.117,797] <err> os: r3/a4:  0x00000010 r12/ip:  0x00000046 r14/lr:  0x0004b2b9
    00> [00:04:07.117,828] <err> os:  xpsr:  0x01000000
    00> [00:04:07.117,828] <err> os: s[ 0]:  0x00000000  s[ 1]:  0x00000000  s[ 2]:  0x00000000  s[ 3]:  0x00000000
    00> [00:04:07.117,858] <err> os: s[ 4]:  0x00000000  s[ 5]:  0x00000000  s[ 6]:  0x00000000  s[ 7]:  0x00000000
    00> [00:04:07.117,889] <err> os: s[ 8]:  0x00000000  s[ 9]:  0x00000000  s[10]:  0x00000000  s[11]:  0x00000000
    00> [00:04:07.117,889] <err> os: s[12]:  0x00000000  s[13]:  0x00000000  s[14]:  0x00000000  s[15]:  0x00000000
    00> [00:04:07.117,919] <err> os: fpscr:  0x0004bb9f
    00> [00:04:07.117,919] <err> os: Faulting instruction address (r15/pc): 0x0004b1f2
    00> [00:04:07.117,950] <err> os: >>> ZEPHYR FATAL ERROR 0: CPU exception on CPU 0
    00> [00:04:07.117,950] <err> os: Current thread: 0x200036a8 (sysworkq)
    00> [00:04:07.710,906] <err> fatal_error: Resetting system
    00> *** Booting Zephyr OS build v3.0.99-ncs1-1  ***
    00> 
    00> 

    Since I transfer the image serially from my cellular host to the central, I know the actual image size if that is what I am supposed to use.

    Thanks David

  • DavidKaplan said:
    I am using ncsv2.0.2 and not ncsv2.2.0

    I think it also works for me in 2.0.2, so for the record: I do not think you have to upgrade the version for this feature.¨

    I will help you make it work for v2.2.0 as well, though.

    DavidKaplan said:
    My error 11 is in the smp_list_rsp_proc() function when called by Test.

    Error 11 looks like ZCBOR_ERR_WRONG_VALUE.
    This is what the patch fixes, I think. Are you sure that the patch is still there after your update?

    DavidKaplan said:
    The problem is also that I could not reproduce the upload success.

    To check if I understand correctly:
    So it works the first time, but the upload fails if you already have an image in the secondary slot?

    Do you get the debugging error when uploading the first time?

    DavidKaplan said:
    Since I transfer the image serially from my cellular host to the central, I know the actual image size if that is what I am supposed to use.

    That would make sense to me.

    Regards,
    Sigurd Hellesvik

Reply
  • DavidKaplan said:
    I am using ncsv2.0.2 and not ncsv2.2.0

    I think it also works for me in 2.0.2, so for the record: I do not think you have to upgrade the version for this feature.¨

    I will help you make it work for v2.2.0 as well, though.

    DavidKaplan said:
    My error 11 is in the smp_list_rsp_proc() function when called by Test.

    Error 11 looks like ZCBOR_ERR_WRONG_VALUE.
    This is what the patch fixes, I think. Are you sure that the patch is still there after your update?

    DavidKaplan said:
    The problem is also that I could not reproduce the upload success.

    To check if I understand correctly:
    So it works the first time, but the upload fails if you already have an image in the secondary slot?

    Do you get the debugging error when uploading the first time?

    DavidKaplan said:
    Since I transfer the image serially from my cellular host to the central, I know the actual image size if that is what I am supposed to use.

    That would make sense to me.

    Regards,
    Sigurd Hellesvik

Children
  • I tried some things today with my v2.2.0 sensor and central code with the default bootloader keys.

    1) In smp_upload_rsp_proc(), I changed the 'rc' comparison line from

     if(!strncmp(value.value, "rc", 2)){
    			printk("Invalid data received (rc key). String '%.2s' is not equal to 'rc'\n", value.value);
    			return;
    		}

    to

            if(memcmp(value.value,"rc", 2)){
    			printk("Invalid data received (rc key). String '%.2s' is not equal to 'rc'\n", value.value);
    			return;
    		}
    

    Evidently the way it was written was not correct as it says !strncmp(), so if it matched 'rc' it would return.

    I was previously 'rc' which gave an error, so I just used memcmp.

    2) In smp_list_rsp_proc(), I had to increase these array sizes as the retuned values exceed what was allocated.

    char version_key[16]; // ?!? len =7
     char version_value[16]; // ?!? len=5 was [5]

    3) I verified the zcbor_decode.c changes in C:\ncs\v2.2.0\modules\lib\zcbor\src.

     Do I need to update also the file in C:\ncs\v2.2.0\bootloader\mcuboot\boot\boot_serial\src?

    4) I uploaded a app_update.bin sensor file to my host's external flash and streamed it to the Central and on to the sensor. I was connected to the central by the debugger and its print outs showed the following which seemed OK but the image did not update. (DFUConnectFinishedErr:0 means OK).

    I upload,list and then test.

    07/02/2023 04:05:19[ami_local_pc.c: 152] Rx Op:B Len:21
    [ami_local_pc.c:1050] ImageDownloadFinished
    07/02/2023 04:05:19[ami_com.c:  89] MsgReply:a Len:10
    [ami_smp.c:1265] DFU:318800/319012
    [ami_smp.c:1455] SMP UploadOK
    [ami_smp.c:1736] ImageList
    
    -----------PRIMARY IMAGE-----------
          slot: 0
          version: 0.0.0
          hash: 0x5112e3513cac5b8cdf9935bda9d8342c7d226e1abdf9c38afbae28e37b1ec
          bootable: true
          pending: false
          confirmed: true
          active: true
          permanent: false
    
    -----------SECONDARY IMAGE-----------
          slot: 1
          version: 0.0.0
          hash: 0x158917e21a8a8eb83acf3c74988b1c72d207e7063865f589f4e88581146eeac
          bootable: true
          pending: false
          confirmed: false
          active: false
          permanent: false
    07/02/2023 04:05:20[ami_local_pc.c: 152] Rx Op:B Len:9
    07/02/2023 04:05:20[ami_com.c:  89] MsgReply:a Len:10
    [ami_smp.c:1739] ImageTest
    
    -----------PRIMARY IMAGE-----------
          slot: 0
          version: 0.0.0
          hash: 0x5112e3513cac5b8cdf9935bda9d8342c7d226e1abdf9c38afbae28e37b1ec
          bootable: true
          pending: false
          confirmed: true
          active: true
          permanent: false
    
    -----------SECONDARY IMAGE-----------
          slot: 1
          version: 0.0.0
          hash: 0x158917e21a8a8eb83acf3c74988b1c72d207e7063865f589f4e88581146eeac
          bootable: true
          pending: true
          confirmed: false
          active: false
          permanent: false
    [ami_smp.c:1742] ImageReset
    07/02/2023 04:05:22[ami_ble.c: 861] Disconnected: D4:FD:9F:BF:4A:27 (random) (reason 8)
    [ami_ble.c:2588] DFUConnectFinishedErr:0
    

    Is there a way for more debug info maybe on the sensor ?

    I moved the debugger to the central but maybe the debug output cleared when resetting.

    Thanks David

  • DavidKaplan said:
    I was previously 'rc' which gave an error, so I just used memcmp.

    Nice!

    DavidKaplan said:
    2) In smp_list_rsp_proc(), I had to increase these array sizes as the retuned values exceed what was allocated.

    Good to know

    DavidKaplan said:

    3) I verified the zcbor_decode.c changes in C:\ncs\v2.2.0\modules\lib\zcbor\src.

     Do I need to update also the file in C:\ncs\v2.2.0\bootloader\mcuboot\boot\boot_serial\src?

    Only zcbor_decode.c in modules\lib\zcbor\src needs to be changed, as far as I know.

    DavidKaplan said:
    Is there a way for more debug info maybe on the sensor ?

    My MCUboot SMP Sample feat Bluetooth Low Energy sample has logs from MCUboot:

    *** 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=unset, swap_type=0x1, copy_done=0x3, image_ok=0x3
    I: Boot source: none
    I: Swap type: none
    I: Bootloader chainload address offset: 0xc000
    *** Booting Zephyr OS build v3.2.99-ncs1 ***
    Change this to see it change.
    

    Is this what you are looking for?

    Regards,
    Sigurd Hellesvik

  • Our peripheral sensor has no uart interfaces, unlike the SDKs, and is in a waterproof container.

    I can maybe try to comment out the Central's SMP sensor reset command and see start up from the debugger.

    From the SMP test reply it looks like slot#1 is pending.

    I use the swap move define.

     

    ### ?!? 18-Dec-2022 Without this swap is used which limits upgrades 10000 / (150 / 4) ~ 267
    CONFIG_BOOT_SWAP_USING_MOVE=y

    Can you think of any reason the new image is not swapped.

    I can also try to send SMP confirm instead of SMP test.

    Thanks David

  • DavidKaplan said:
    Our peripheral sensor has no uart interfaces, unlike the SDKs, and is in a waterproof container.

    Do you have debugger access to the waterproof sensor?

    Your "image list" lists the image as "pending: true".
    This should make MCUboot swap the images.
    Does it still list "pending:true" after multiple resets of the peripheral sensor?
    Are you able to upload a new image from your mobile phone to update the peripheral sensor now?

    Regards,
    Sigurd Hellesvik

  • Yes, I have a bare board which I debug. 

    Yes, the phone app updates correctly the image.

    The RTT log does not show bootloader information on reset.

    This is the sensor RTT log from the DFU connection till reset:

    00> 08/02/2023 19:18:35[ami_main.c: 598] NewMin
    00> 08/02/2023 19:19:35[ami_main.c: 598] NewMin
    00> 08/02/2023 19:20:04[ami_main.c: 142] Connected
    00> 08/02/2023 19:20:05[ami_main.c: 197] LE PHY updated: TX PHY LE 2M, RX PHY LE 2M
    00> 08/02/2023 19:20:09[ami_main.c: 174] Connection parameters updated.
    00>  interval: 40, latency: 0, timeout: 42
    00> 08/02/2023 19:20:14[ami_main.c: 174] Connection parameters updated.
    00>  interval: 9, latency: 0, timeout: 42
    00> 08/02/2023 19:20:35[ami_main.c: 598] NewMin
    00> 08/02/2023 19:21:35[ami_main.c: 598] NewMin
    00> *** Booting Zephyr OS build v3.2.99-ncs1 ***
    00> [00:00:00.037,292] <inf> mcumgr_zephyr_grp: zephyr_basic_mgmt_init: Registering Zephyr basic mgmt group
    00> 00/00/0000 00:00:00[ami_main.c: 628] Startup
    00> 00/00/0000 00:00:00[ami_cfg.c: 256] DeviceID:51

    How can I read the bootloader flags in my code? Would this help?

    I copied the default mcuboot.conf file into the child_image folder and added the swap move directive.

    I tried in that file to change log minimal to n and log level to 4 but that did not help.

    I see threads on bootloader RTT in the forum but mainly for non zephyr builds.

    I decided not to use other than the default bootloader keys till the DFU works.

    CONFIG_PM=n
    
    CONFIG_MAIN_STACK_SIZE=10240
    CONFIG_MBEDTLS_CFG_FILE="mcuboot-mbedtls-cfg.h"
    
    CONFIG_BOOT_SWAP_SAVE_ENCTLV=n
    CONFIG_BOOT_ENCRYPT_RSA=n
    CONFIG_BOOT_ENCRYPT_EC256=n
    CONFIG_BOOT_ENCRYPT_X25519=n
    
    CONFIG_BOOT_UPGRADE_ONLY=n
    CONFIG_BOOT_BOOTSTRAP=n
    
    CONFIG_FLASH=y
    CONFIG_FPROTECT=y
    
    CONFIG_LOG=y
    CONFIG_LOG_MODE_MINIMAL=y # former CONFIG_MODE_MINIMAL
    ### Ensure Zephyr logging changes don't use more resources
    CONFIG_LOG_DEFAULT_LEVEL=0
    ### Decrease footprint by ~4 KB in comparison to CBPRINTF_COMPLETE=y
    CONFIG_CBPRINTF_NANO=y
    CONFIG_NRF_RTC_TIMER_USER_CHAN_COUNT=0
    
    ### ?!? 18-Dec-2022 Without this swap is used which limits upgrades 10000 / (150 / 4) ~ 267
    CONFIG_BOOT_SWAP_USING_MOVE=y
    

Related