UART DFU of a nRF9160 in recovery mode via nRF5340.

Hello everyone, 

I guess my question is more conceptual rather than a specific issue with the code. 

I am working on a device featuring an nRF5340 chip and an nRF9160 chip which are linked by a UART interfface and 4 gpios. When it comes to DFU, i am able to update the firmware of the nRF5340 without issues. Although it could be possible to update the nRF9160 via LTE, the device might need to be updated in areas where there is no LTE connection available. For the update of the nRF9160 I would like to send the data to the nRF5340 via BLE which should transfer the new image to the nRF9160. While the nRF5340 has two slots in flash, the nRF9160 has only one slot and will be put in recovery mode for the DFU. 

To transmit the images over BLE, an ios app is going to be written. 

I have read the following posts, which tackle similar ideas : 

 nRF91 firmware upgrade over BLE  Here the image is sent via a PC running mcumgr commands and the nRF52 DK simply forwards it to the nRF9160. 

  Example For Using UART DFU on NRF52832 on both sides of communications  This post highlights the fact that mcuboot expects the image to be sent using the smp protocol. Or alternatively to modify the part of mcuboot especially the function boot_serial_input(). 

To preserve compatibility with upcoming versions of mcuboot I don't want to modify the sourcecode of mcuboot otherwise I am tied to that custom version or have to replicate my changes in every new version of mcuboot. 

I am considering basing the ios app on the device manager sample: 

https://github.com/NordicSemiconductor/IOS-nRF-Connect-Device-Manager 

I would like to clarify if it is possible to use the device manager on the ios app to send the nRF9160 image to the nRF5340 over BLE and having the nRF5340 simply forward the data chunks to the nRF9160, which is in recovery mode at that time. 

Hypothesis: 

I assume that, in order for this to work, the data chunks should be formatted using the SMP protocol with a serial transport layer, then each transport layer frame should be transmitted over BLE to a custom service which will simply forward the data as they are already formatted for serial transport. 

Since i am not too familiar with SMP and MCUmgr I am unsure if this is possible, could you confirm that idea? 

If this is a viable solution, are there any pitfalls to be aware of? How would you advise to proceed on the ios app? 

I am developping with the SDK version V2.7.0 and the Toolchain V2.7.0 

I am looking forward to reading your responses. 

Kind regards 

Colin 

Parents
  • Of course, thank you for sharing your findings in advance, other developers will definitely benefit from your contribution.

    I will keep this ticket open.

    Best regards,

    Charlie

  • Hi, I am back with some more insights and questions on the usage of the img_mgmt_client. The API usage seems to  be restricted to the test code. 

    The project I am working on is confidential so I can't share the whole code.  Here is a short snippet that shows how I use the img_mgmt_client API : 

    struct mcumgr_image_upload res_buf; 
    struct img_mgmt_client img_mgr_cli;
    struct smp_client_object smp_client;
    struct mcumgr_image_data img_data[1];
    
    #define READ_SIZE 124 
    
    //Initialize the smp_client and the img_mgmt_client
    smp_client_object_init(&smp_client, SMP_SERIAL_TRANSPORT);
    img_mgmt_client_init(&img_mgr_cli, &smp_client, 1, img_data);
    
    //Initialise the image upload
    err = img_mgmt_client_upload_init(&img_mgr_cli, image_size, 0, NULL);
    if(err != 0){
        LOG_ERR("Failed to initialise the image upload");
    }
    
    //Upload one chunk to the nRF9160
    err = img_mgmt_client_upload(&img_mgr_cli, image_data, READ_SIZE, &res_buf);
    

    The execution of 

    img_mgmt_client_upload() fails due to an Attribution unit violation, the call stack is as follows: 

     

    sys_dlist_remove(sys_dnode_t * node) (ncs\v2.7.0\zephyr\include\zephyr\sys\dlist.h:506) 
    
    sys_dlist_get(sys_dlist_t * list) (ncs\v2.7.0\zephyr\include\zephyr\sys\dlist.h:530) 
    
    handle_poll_events(uint32_t state, struct k_queue * queue) (ncs\v2.7.0\zephyr\kernel\queue.c:90) 
    
    queue_insert(struct k_queue * queue, void * prev, void * data, _Bool alloc, _Bool is_append) (ncs\v2.7.0\zephyr\kernel\queue.c:170) 
    
    net_buf_put(struct k_fifo * fifo, struct net_buf * buf) (ncs\v2.7.0\zephyr\subsys\net\buf.c:450) 
    
    smp_client_send_cmd(struct smp_client_object * smp_client, struct net_buf * nb, smp_client_res_fn cb, void * user_data, int timeout_in_sec) (ncs\v2.7.0\zephyr\subsys\mgmt\mcumgr\smp_client\src\client.c:322) 
    
    img_mgmt_client_upload(struct img_mgmt_client * client, const uint8_t * data, size_t length, struct mcumgr_image_upload * res_buf) (ncs\v2.7.0\zephyr\subsys\mgmt\mcumgr\grp\img_mgmt_client\src\img_mgmt_client.c:420) 
    
    perform_nrf9160_dfu(struct k_work * work) (Application Level Function, Top of callstack)

     

    It seems that the FIFO element in the SMP_client struct makes an illegal access. But I don't understand why, as I have initialized the SMP_client. 

    Right now I am still unsure if using the img_mgmt_client API directly from Application level code the correct way is or what I am missing. 

    Based on this update, do you have more inputs that could help me advance with the DFU implementation? 

    Thank you for the support 

    Cheers, Colin 

Reply
  • Hi, I am back with some more insights and questions on the usage of the img_mgmt_client. The API usage seems to  be restricted to the test code. 

    The project I am working on is confidential so I can't share the whole code.  Here is a short snippet that shows how I use the img_mgmt_client API : 

    struct mcumgr_image_upload res_buf; 
    struct img_mgmt_client img_mgr_cli;
    struct smp_client_object smp_client;
    struct mcumgr_image_data img_data[1];
    
    #define READ_SIZE 124 
    
    //Initialize the smp_client and the img_mgmt_client
    smp_client_object_init(&smp_client, SMP_SERIAL_TRANSPORT);
    img_mgmt_client_init(&img_mgr_cli, &smp_client, 1, img_data);
    
    //Initialise the image upload
    err = img_mgmt_client_upload_init(&img_mgr_cli, image_size, 0, NULL);
    if(err != 0){
        LOG_ERR("Failed to initialise the image upload");
    }
    
    //Upload one chunk to the nRF9160
    err = img_mgmt_client_upload(&img_mgr_cli, image_data, READ_SIZE, &res_buf);
    

    The execution of 

    img_mgmt_client_upload() fails due to an Attribution unit violation, the call stack is as follows: 

     

    sys_dlist_remove(sys_dnode_t * node) (ncs\v2.7.0\zephyr\include\zephyr\sys\dlist.h:506) 
    
    sys_dlist_get(sys_dlist_t * list) (ncs\v2.7.0\zephyr\include\zephyr\sys\dlist.h:530) 
    
    handle_poll_events(uint32_t state, struct k_queue * queue) (ncs\v2.7.0\zephyr\kernel\queue.c:90) 
    
    queue_insert(struct k_queue * queue, void * prev, void * data, _Bool alloc, _Bool is_append) (ncs\v2.7.0\zephyr\kernel\queue.c:170) 
    
    net_buf_put(struct k_fifo * fifo, struct net_buf * buf) (ncs\v2.7.0\zephyr\subsys\net\buf.c:450) 
    
    smp_client_send_cmd(struct smp_client_object * smp_client, struct net_buf * nb, smp_client_res_fn cb, void * user_data, int timeout_in_sec) (ncs\v2.7.0\zephyr\subsys\mgmt\mcumgr\smp_client\src\client.c:322) 
    
    img_mgmt_client_upload(struct img_mgmt_client * client, const uint8_t * data, size_t length, struct mcumgr_image_upload * res_buf) (ncs\v2.7.0\zephyr\subsys\mgmt\mcumgr\grp\img_mgmt_client\src\img_mgmt_client.c:420) 
    
    perform_nrf9160_dfu(struct k_work * work) (Application Level Function, Top of callstack)

     

    It seems that the FIFO element in the SMP_client struct makes an illegal access. But I don't understand why, as I have initialized the SMP_client. 

    Right now I am still unsure if using the img_mgmt_client API directly from Application level code the correct way is or what I am missing. 

    Based on this update, do you have more inputs that could help me advance with the DFU implementation? 

    Thank you for the support 

    Cheers, Colin 

Children
  • Hi Colin,

    In addition to the usage demonstrated in v2.8.0\nrf\tests\subsys\net\lib\mcumgr_smp_client, I found the following sample and guidance that showcase the mcumgr client with the img_mgmt_client API:

    https://docs.nordicsemi.com/bundle/ncs-2.8.0/page/nrf/samples/cellular/lwm2m_client/sample_description.html#mcumgr_client_for_external_fota 

    Exercise 1 - DFU over UART - Nordic Developer Academy

    I recommend closely comparing the usage of the img_mgmt_client API in these samples to ensure your implementation aligns with the demonstrated best practices.

    If the issue persists, I encourage you to share a minimal version of your mcumgr client implementation, excluding any confidential code. This will help us analyze and troubleshoot the problem more effectively.

    Best regards,

    Charlie

  • Hi Charlie, 

    Tanks for the reply, I am working on a small example with a nRF5340 DK and a nRF9160 DK, based on the serial recovery DFU sample for the 9160 and the BLE FOTA sample for the 5340 (in the Academy Lesson 8 exercises 1 and 3) I will share them as soon as I have something. 

    In the FW I managed to get rid of the Attribution unit violation. The issue was that no transport layer was assigned and thus the smp_client_object_init() could not be called properly. 

    Now I am able to call img_mgmt_client_upload(). This indeed results in traffic on the TX uart line as the first few transport frames get sent out. The nRF9160 responds with a 35 byte SMP packet after 90 ms. Which looks as follows:

    First 64 bytes of the image sent as SMP frames (nRF5340 -> nRF9160): 

    06 09 41 47 67 43 41 41 42 65 41 41 45 41 41 62 
    39 6C 61 57 31 68 5A 32 55 41 5A 47 52 68 64 47 
    46 59 51 44 32 34 38 35 59 41 41 41 41 41 41 41 
    49 41 41 44 6A 56 41 67 41 41 41 41 41 41 41 51 
    41 41 41 41 41 41 41 41 41 41 41 41 41 41 2F 2F 
    2F 2F 2F 2F 2F 2F 2F 2F 2F 2F 2F 2F 2F 2F 2F 2F 
    2F 2F 2F 2F 2F 2F 2F 2F 2F 2F 2F 2F 2F 2F 2F 2F 
    2F 2F 2F 2F 2F 2F 2F 2F 39 6A 62 32 5A 6D 0A 04 
    14 41 47 4E 73 5A 57 34 61 41 41 4C 58 7A 2F 39 
    4C 58 67 3D 3D 0A 

    Response fom (nRF9160-> nRF5340): 

    06 09 41 42 59 44 41 41 41 4D 41 41 45 41 41 62 
    39 69 63 6D 4D 41 59 32 39 6D 5A 68 6A 51 2F 37 
    47 53 0A 

    Unfortunately I am unable to parse it to verify for error codes. This could confirm whether or not the nRF9160 accepts the incoming traffic. 

    The issue is that the nRF5340 does not react to the incoming response. No uart handlers get triggered despite uart_rx_enable() having been called, a handler registered with uart_callback_set() and the Following interrupts being enabled 

    For the MCUMGR configuration I use the following kconfig settings : 

    #Enable DFU SMP Target for nRF9160 DFU  
    CONFIG_DFU_TARGET=y
    CONFIG_MCUMGR_GRP_OS_CLIENT=y
    CONFIG_DFU_TARGET_SMP=y
    CONFIG_CONSOLE=y
    CONFIG_UART_MCUMGR=y
    CONFIG_MCUMGR_TRANSPORT_UART=y
    CONFIG_MCUMGR_TRANSPORT_UART_ASYNC=y
    CONFIG_SHELL=y
    CONFIG_BASE64=y
    
    # Enable SMP Server
    CONFIG_MCUMGR=y
    CONFIG_MCUMGR_GRP_IMG=y
    # CONFIG_MCUMGR dependencies
    CONFIG_NET_BUF=y
    CONFIG_ZCBOR=y
    # CONFIG_MCUMGR_GRP_IMG dependencies
    CONFIG_SMP_CLIENT=y
    CONFIG_IMG_MANAGER=y
    CONFIG_MCUMGR_GRP_IMG_CLIENT=y
    # CONFIG_IMG_MANAGER dependencies
    CONFIG_STREAM_FLASH=y
    CONFIG_MCUMGR_MGMT_NOTIFICATION_HOOKS=y
    CONFIG_MCUMGR_SMP_COMMAND_STATUS_HOOKS=y
    CONFIG_MCUMGR_GRP_IMG_UPLOAD_CHECK_HOOK=y
    CONFIG_MCUMGR_GRP_IMG_STATUS_HOOKS=y

    Do you see anything wrong about my uart config or why the response gets ignored by the nRF5340? 

    Thanks a lot for your support 

    Kind regards 

    Colin Cina 

  • Hi Colin,

    It seems that your nRF5340 SMP client configuration does not fully reference the nrf\samples\cellular\lwm2m_client\overlay-mcumgr_client.conf file. To ensure the setup is correct, I recommend trying to use the original nrf\samples\cellular\lwm2m_client as an SMP client on the nRF9160 to perform DFU for another nRF9160 configured as an SMP server.

    This should serve as a solid preliminary study before attempting to implement and run an SMP client on the nRF5340.

    Best regards,

    Charlie

  • Hi Charlie, 

    Thanks for the reply, I'll give it a go. 

    In the meantime I have worked on some code I can share with you. It shows exactly how I intend to Pass the new nRF9160 image around, furtther details are explained in the README file. Please look if you manage to get it going on your DKs (I am available for further information). Maybe you can also give me feedback on the concept I present in the readme regarding the upating of the nRF9160. 

    8371.Firmware.zip

    Kind Regards 

    Colin  

  • Hi Colin,

    I spent some time reviewing your codes today but, unfortunately, wasn’t able to make any progress.

    I’ll be on leave until next Tuesday, but I’ll continue looking into it once I’m back. In the meantime, if there’s capacity within our team, someone else may be able to take a look.

    Thank you for your patience, and feel free to reach out if there are any updates or additional information to share.

    Best regards,
    Charlie

Related