Speeding up DFU OTA on Linux

Hello,

I am using Linux computer as an update hub for BT device, based on NRF52840. 

The device is set to use Coded PHY, so there is no possibility to use McuMgr - but with Bluez 5.64 and Bleak 0.21.1. The application is compiled using NRF Connect 2.4.2 SDK. 

Negotiated MTU is 495, but some of the capacity is "wasted" by BT headers and SMP message parameters - so I cannot send more than 410 bytes in a first chunk and around 470 in a subsequent ones. I am writing the chunks one by one, without requiring the response - and waiting for a notification to read the next offset. 

Unfortunately, top speed I managed to achieve is 1.4 KB/s - when with Nordic Android app I am easily reaching upload speed of 11.3 kB/s - i.e. 8 times faster. 

What can be improved to speed up the upload?

Thanks,



Parents
  • Hi,

    The device is set to use Coded PHY, so there is no possibility to use McuMgr - but with Bluez 5.64 and Bleak 0.21.1. The application is compiled using NRF Connect 2.4.2 SDK. 

    Do I understand it correctly that you implement your own DFU program using Bluez and Bleak?

    Regards,
    Sigurd Hellesvik

  • Hi,

    Well - kind of. We had an IOT hub, collecting data from and managing sensors. It is written in Python. as all our software -and running on Linux computers located at the remote sites (where sensors are deployed).

    This IOT hub already contained BLE advertisements processing and GATT characteristics read/wrtite/notify functionality - so implementing SMP client on top of it was more or less a matter of adding CBOR library to the project and writing a functions for serialization/deserialization of the SMP payload. And I had NRF Connect Android app - logs of it helped me to see that I am doing the right thing (or not). So I managed to implement the sequential chunk-by-chunk upload, confirmation and reset - so from the fucntional perspective everyhting is ok. 

    Unfortunately - the whole block of image upload in the app doesn't have a detailed logs, neither performance aspect of SMP is documented well in general. I understood that the performance has to do with "SMP reassembly" and three numbers - MTU (which is reported to be 495), SMP buffer size (2475) and number of buffers (4). 

    I have tried to tweak the chunk size, so SMP write command will fit into one packet, MTU or SMP buffer size (latter requires multiple "write" commands in a sequence, as BlueZ cannot write more than MTU). At 2475 bytes - It takes to a device 400-500 ms to respond with the notiifcaton (confirm the new offset), so I can proceed with the next chunk. With any combination - the speed hardly goes above 2 kB/s, when with Android application it is quite stable on 11.3 kB/s.

    Could you advise regarding the algorithm - how to divide the image into a SMP commands/BLE packets so the reassembly will be at least as effective as with the mobile app as a client?

    Thanks!

  • The nRF Device Manager code is public for both android and iOS.
    This implements FOTA, so we can have a look at what that does to be so fast.

    From the android one, Maximum SMP packet length seems to enable longer packets than the MTU, which probably speeds this up. But if BlueZ does not support that, that is not possible I guess.

    here is also something mentioning file transfer speeds.
    Also here.
    Well, you get the jist, Im just reading the comments from that file.

    That is all I can find on this, but I will ask a colleague who is more experienced with BLE to see if they have any suggestions.

  • And after that I got the following:

    Try to tweak DLE as well, maybe that can help you.

    Also, see https://devzone.nordicsemi.com/guides/nrf-connect-sdk-guides/b/software/posts/building-a-bluetooth-application-on-nrf-connect-sdk-part-3-optimizing-the-connection#mcetoc_1ftnic3900 for some tips on speeding up BLE.

    Other than that, if you send a BLE sniffer trace from the DFU, we can have a look at it and see if we find any bottlenecks.

  • Thanks a lot, I will look into this. 

    I believe it is not about just speeding up the transfer of bytes - but somehow sending data in parallel/ahead of confirmation. There are some references to "sliding window" in SMP  - but I am not sure how it has to be implemented and my knowledge in Kotlin/Java is not enough to understand it from the Android mcumgr code (especially based on Android OS APIs, I am not familiar with at all).

    With regard to SMP packet length you mentioned above - yes, even before the special re-assembly mechanism created for DFU images, each SMP command can span over multiple lower-level GATT packets - because latter are limited by MTU, and without this mechanism it will be challenging to deliver, for example, "list images" response. 

    This is exactly what I am looking for - how to combine BLE packet size, MTU, SMP protocol-level re-assembly, SMP image upload-specific re-assembly, buffer size and number of buffers ;) to improve performance. 

    Thanks again!

  • Good to see that I was able to provide helpful help.

    Paskin said:
    my knowledge in Kotlin/Java is not enough to understand it from the Android mcumgr code

    This made me think of our recently implemented SMP Client for microcontrollers, which is implemented in C.

    https://github.com/zephyrproject-rtos/zephyr/pull/56934

    I do not know if this implements the sliding or not, and I have not tested the speed of it.
    But it could be worth having a look at.

Reply Children
No Data
Related