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 

  • 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

  • Hi Charlie, 

    Tanks for looking in the code, I would indeed be glad if someone could take over while you are away Slight smile

    I also started studying the lwm2m sample, got the FW running on the nRF9160 and the nrf52840. But I had to go back to SDK version 2.5.0 since the sample description didn't match the folder structure in v2.7.0 due to the build tool being sysbuild and the lack of child_image folder. 

    The sample FW seems to work but executing the fota.py script runs into a 403 error when trying to register the new resource for the app_update52.bin image. Is it possible that the behaviour of the coiote server has changed and does no longer match the fota.py script or is the problem on my side? 

    Regarding the lwm2m_client sample: I am interested in the case "LwM2M Firmware Update for external MCU" could you tell me how the SMP transfer is triggerd and how the data flow is? I tried to find the API calls to mcu_mgr but to no avail. 

    Thanks a lot for the support! 

    Cheers 

    Colin 

  • Hi Colin,

    As you might have been notified by email, since a few days ago, I have been assigned to continue supporting you with this issue while Charlie is unavailable.

    To give you an update, I am a little familiar with DFU solutions, but entirely new to using SMP Client, and am still trying to figure things out myself.

    I will continue looking into it and get you a reply probably this Friday or Saturday.

    By the way, have you made any progress since?

    Hieu

Reply
  • Hi Colin,

    As you might have been notified by email, since a few days ago, I have been assigned to continue supporting you with this issue while Charlie is unavailable.

    To give you an update, I am a little familiar with DFU solutions, but entirely new to using SMP Client, and am still trying to figure things out myself.

    I will continue looking into it and get you a reply probably this Friday or Saturday.

    By the way, have you made any progress since?

    Hieu

Children
  • Hi Hieu, 

    Tanks for the support! Yeah I made progress, I tweaked the code I sent you and managed to get some image transfer over UART going with the Interrupt driven transport layer.

    The tweak consists in removing the CONFIG_UART_2_NRF_ASYNC, CONFIG_UART_2_NRF_ASYNC_TIMER and CONFIG_NRFX_TIMER2 statements and 

    Unfortunately, the SMP server which should consume the image always sends answers with the "off" field set to -1. I believe it indicates that no byte of the image was written to flash, is that correct? 

    Switching to the ASYNC transport layer, the transport layer of the SMP client times out although an answer is coming from the SMP server. I recorded the UART traffic with Saleae's logic analyser: here are the traces: 

     Interrupt_driven_no_data_consumed.salAsync_timeouts.sal

    The files can be opened with Saleae's "Logic" tool. Maybe you can look into it and understand better than me, why timeouts happen, when I use the async SMP transport layer and why no bytes are consumed with the interrupt driven SMP transport layer. 

    Thank you for the support! 

    Kind regards 

    Colin 

  • Hi Colin,

    ColinC said:

    I tweaked the code I sent you and managed to get some image transfer over UART going with the Interrupt driven transport layer.

    The tweak consists in removing the CONFIG_UART_2_NRF_ASYNC, CONFIG_UART_2_NRF_ASYNC_TIMER and CONFIG_NRFX_TIMER2 statements and 

    To use interrupt driven mode, you should only need to disable CONFIG_UART_ASYNC_API and enable CONFIG_UART_INTERRUPT_DRIVEN. Were there some issues doing just this?

    ColinC said:
    Unfortunately, the SMP server which should consume the image always sends answers with the "off" field set to -1. I believe it indicates that no byte of the image was written to flash, is that correct? 

    I am not sure what kind of response you are talking about here. What is your response frame?

    The response is defined here: https://docs.nordicsemi.com/bundle/ncs-2.9.0/page/zephyr/services/device_mgmt/smp_protocol.html#minimal_response

    ColinC said:
    Switching to the ASYNC transport layer, the transport layer of the SMP client times out although an answer is coming from the SMP server. I recorded the UART traffic with Saleae's logic analyser: here are the traces: 

    This goes back to the setup of the UART API types. To use async, you should only need to enable CONFIG_UART_ASYNC_API and disable CONFIG_UART_INTERRUPT_DRIVEN. Could you please try this and see if the communication works properly?

    Also, am I right to understand that we are only talking about the nRF5340/SMP Client UART configurations, and the nRF9160's UART configuration is left as default?

    And can I take it you are not using LPUART? It's the default interface between the nRF52840 and nRF9160 in the nRF9160 DK Cellular + BLE setup.

    Please be informed that I will be out of office for a few weeks. If you have any follow-up questions, please just reply and one of our engineers will continue to support you.

    Best regards,

    Hieu

Related