Drastic Reduction in Firmware Update Speed with MCUboot in Serial Recovery Mode

I implemented MCUboot in Serial Recovery mode on a custom USB stick to enable firmware updates via MCUmgr. Initially, everything was working correctly, and the image transfer speed was high, with the entire update taking just over a minute. Over time, I made changes to the application firmware, assuming that the Serial Recovery part was complete. However, when retesting the update via MCUmgr, I discovered that the transfer speed had drastically decreased to just a few bytes per second, making the entire update process take over two hours.

The commands I’ve been using with MCUmgr have always been the same:

mcumgr conn add LABEL type="serial" connstring="COMx,baud=1000000,mtu=128"
mcumgr -c LABEL image upload Path\of\file\new_firmware.bin
mcumgr -c LABEL reset

I’ve tried changing the baud rate and MTU in the first command, but it doesn’t seem to make a difference.
Do you have any suggestions about what the issue might be?

Parents
  • Hello,

    The serial recovery functionality in MCUBoot should not be affected by configurations in your application, and there should not be any configuration that causes the throughput to drop to only a few bytes per second. Please ensure that nothing else is connected to the COM port when uploading the image with mcumgr (e.g., close the serial terminal in VS Code if it is open).

    Best regards,

    Vidar

  • I discovered the change that caused the drastic reduction in image transfer speed during the firmware update. Initially, I added Serial Recovery to my application by following this example, which sets up the system with a single partition and uses the configuration:

    CONFIG_SINGLE_APPLICATION_SLOT=y

    Everything worked fine up to that point. However, later on, I needed to add an SMP client to enable BLE updates for devices connected to my dongle. So, I had to recreate the system with two partitions and changed the configuration to:

    CONFIG_SINGLE_APPLICATION_SLOT=n

    This change caused the transfer speed to decrease significantly. If I restore the initial configuration, the speed returns to normal, but I lose the ability to implement the SMP client because it relies on macros derived from:

    CONFIG_SINGLE_APPLICATION_SLOT=n

    How can I solve this problem, considering the need to have both Serial Recovery and the SMP client at the same time?

Reply
  • I discovered the change that caused the drastic reduction in image transfer speed during the firmware update. Initially, I added Serial Recovery to my application by following this example, which sets up the system with a single partition and uses the configuration:

    CONFIG_SINGLE_APPLICATION_SLOT=y

    Everything worked fine up to that point. However, later on, I needed to add an SMP client to enable BLE updates for devices connected to my dongle. So, I had to recreate the system with two partitions and changed the configuration to:

    CONFIG_SINGLE_APPLICATION_SLOT=n

    This change caused the transfer speed to decrease significantly. If I restore the initial configuration, the speed returns to normal, but I lose the ability to implement the SMP client because it relies on macros derived from:

    CONFIG_SINGLE_APPLICATION_SLOT=n

    How can I solve this problem, considering the need to have both Serial Recovery and the SMP client at the same time?

Children
  • I don't see how CONFIG_SINGLE_APPLICATION_SLOT=y could cause this reduction in transfer speed. Can you try enabling CONFIG_MCUBOOT_SERIAL_DIRECT_IMAGE_UPLOAD in your application? Also, which SDK version are you using?

  • Sorry for replying only now. So, I want to let you know that your suggestion to enable CONFIG_MCUBOOT_SERIAL_DIRECT_IMAGE_UPLOAD worked. However, I have some clarifications to ask and I would like to explain myself better.

    I’m working on a custom dongle equipped with an nRF52840. The SDK version is 2.6.1. This dongle connects to other BLE devices as peripherals to exchange data. Assuming that in the future, I want to implement an SMP Client on the dongle to update the firmware of the connected devices via BLE. Following the example, the SMP Client requires a main partition (slot-0), a secondary partition to load the new firmware to be sent to the connected device (slot-1). Then, I don’t know if it’s necessary for this purpose, but the example is based on the 52840DK development board whose DTS defines a third partition (scratch). Based on these lines, I have defined the partitions for my device as follows:

    &flash0 {
    	partitions {
    		compatible = "fixed-partitions";
    		#address-cells = <1>;
    		#size-cells = <1>;
    
    		boot_partition: partition@0 {
    			label = "mcuboot";
    			reg = <0x00000000 0x0000C000>;
    		};
    		slot0_partition: partition@c000 {
    			label = "image-0";
    			reg = <0x0000C000 0x00067000>;
    		};
    		slot1_partition: partition@73000 {
    			label = "image-1";
    			reg = <0x00073000 0x00067000>;
    		};
    		scratch_partition: partition@da000 {
    			label = "image-scratch";
    			reg = <0x000da000 0x0001e000>;
    		};		
    		storage_partition: partition@f8000 {
    			label = "storage";
    			reg = <0x000f8000 0x00008000>;
    		};
    	};
    };

    As mentioned earlier, the dongle has Serial Recovery enabled for updating its firmware. To implement this, I found that in the mcuboot.conf file, I need to enable CONFIG_SINGLE_APPLICATION_SLOT:

    ################################################
    ### SYSTEM CONFIGURATION #######################
    ################################################
    CONFIG_SIZE_OPTIMIZATIONS=y
    CONFIG_SINGLE_APPLICATION_SLOT=y
    
    ################################################
    ### ENABLE MCUBOOT SERIAL RECOVERY 
    ################################################
    CONFIG_MCUBOOT_SERIAL=y
    CONFIG_UART_CONSOLE=n
    CONFIG_MCUBOOT_INDICATION_LED=y
    CONFIG_BOOT_SIGNATURE_TYPE_RSA=y
    CONFIG_BOOT_SIGNATURE_TYPE_ECDSA_P256=n
    CONFIG_BOOT_SIGNATURE_KEY_FILE="C:/ncsapps/gravity/cruise_dongle/custom_keys/cruise_dongle_private_key.pem"

    So far, so good: the dongle’s firmware update has an acceptable speed of several kilobytes. However, when I compile, the flash size in use doesn’t seem to take the DTS partitioning into account! And here is my first doubt:

    1. What does enabling CONFIG_SINGLE_APPLICATION_SLOT entail? Does it modify the flash partitioning, or is what I’m seeing during compilation misleading?

    Now, to implement the SMP Client in parallel following the example, I need to disable CONFIG_SINGLE_APPLICATION_SLOT to use macros present in some functions, such as PM_MCUBOOT_SECONDARY_ADDRESS. Therefore, my mcuboot.conf becomes:

    ################################################
    ### SYSTEM CONFIGURATION #######################
    ################################################
    CONFIG_SIZE_OPTIMIZATIONS=y
    CONFIG_SINGLE_APPLICATION_SLOT=n
    
    ################################################
    ### ENABLE MCUBOOT SERIAL RECOVERY 
    ################################################
    CONFIG_MCUBOOT_SERIAL=y
    CONFIG_UART_CONSOLE=n
    CONFIG_MCUBOOT_INDICATION_LED=y
    CONFIG_BOOT_SIGNATURE_TYPE_RSA=y
    CONFIG_BOOT_SIGNATURE_TYPE_ECDSA_P256=n
    CONFIG_BOOT_SIGNATURE_KEY_FILE="C:/ncsapps/gravity/cruise_dongle/custom_keys/cruise_dongle_private_key.pem"

    But this configuration causes the Serial Recovery to have a very low transfer speed of only a few bytes. However, if I follow your advice and enable CONFIG_MCUBOOT_SERIAL_DIRECT_IMAGE_UPLOAD, things return to normal:

    ################################################
    ### SYSTEM CONFIGURATION #######################
    ################################################
    CONFIG_SIZE_OPTIMIZATIONS=y
    CONFIG_SINGLE_APPLICATION_SLOT=n
    
    ################################################
    ### ENABLE MCUBOOT SERIAL RECOVERY 
    ################################################
    CONFIG_MCUBOOT_SERIAL=y
    CONFIG_UART_CONSOLE=n
    CONFIG_MCUBOOT_INDICATION_LED=y
    CONFIG_MCUBOOT_SERIAL_DIRECT_IMAGE_UPLOAD=y
    CONFIG_BOOT_SIGNATURE_TYPE_RSA=y
    CONFIG_BOOT_SIGNATURE_TYPE_ECDSA_P256=n
    CONFIG_BOOT_SIGNATURE_KEY_FILE="C:/ncsapps/gravity/cruise_dongle/custom_keys/cruise_dongle_private_key.pem"

    With this configuration, the speed goes back to a few kilobytes rather than just a few bytes.

    1. Can you explain what CONFIG_MCUBOOT_SERIAL_DIRECT_IMAGE_UPLOAD actually does?

    Additionally, I have one last question.

    1. Although a few kilobytes is better, the speed still feels too low. I would expect at least 10KB. Am I expecting too much, or is there a way to increase the speed?

    Anyway, thank you because it seems your advice has temporarily resolved the initial problem.

    EDIT: Never mind: the problem still persists. Initially, it seemed to be resolved on the dongle I use for development, but after loading the application onto a new dongle, the issue is still there. I’ve reset the DTS configuration as follows:

    &flash0 {
    	partitions {
    		compatible = "fixed-partitions";
    		#address-cells = <1>;
    		#size-cells = <1>;
    
    		boot_partition: partition@0 {
    			label = "mcuboot";
    			reg = <0x00000000 0x0000C000>;
    		};
    		slot0_partition: partition@c000 {
    			label = "image-0";
    			reg = <0x0000C000 0x000EC000>;
    		};	
    		storage_partition: partition@f8000 {
    			label = "storage";
    			reg = <0x000f8000 0x00008000>;
    		};
    	};
    };

    And the mcuboot.conf:

    ################################################
    ### SYSTEM CONFIGURATION #######################
    ################################################
    CONFIG_SIZE_OPTIMIZATIONS=y
    CONFIG_SINGLE_APPLICATION_SLOT=y
    
    ################################################
    ### ENABLE MCUBOOT SERIAL RECOVERY 
    ################################################
    CONFIG_MCUBOOT_SERIAL=y
    CONFIG_UART_CONSOLE=n
    CONFIG_MCUBOOT_INDICATION_LED=y
    CONFIG_BOOT_SIGNATURE_TYPE_RSA=y
    CONFIG_BOOT_SIGNATURE_TYPE_ECDSA_P256=n
    CONFIG_BOOT_SIGNATURE_KEY_FILE="C:/ncsapps/gravity/cruise_dongle/custom_keys/cruise_dongle_private_key.pem"

    For now, I’ll leave it like this because it seems to resolve the issue, but I’m starting to doubt whether this is the definitive solution. I’ll keep asking you for advice on how to proceed.

  • CONFIG_MCUBOOT_SERIAL_DIRECT_IMAGE_UPLOAD enables support for multiple mcuboot slots in serial recovery mode. But it is not clear why this affects the upload speed.

    Andrea Verdecchia said:
    Although a few kilobytes is better, the speed still feels too low. I would expect at least 10KB. Am I expecting too much, or is there a way to increase the speed?

    To improve the speed, you may consider building mcumgr from source with the patch proposed here:  RE: MCUBOOT slow with nRF52840 / Zephyr / USB CDC_ACM protocol  

  • EDIT: Never mind: the problem still persists.

    Sorry, but did you read my edit?

  • I missed your edit. It sounds like an intermittent problem. Could you upload the generated .config for your mcuboot build so I can go through it? The file is located in build/mcuboot/zephyr.

Related