DFU Issue on NCS 2.6.1: First OTA Succeeds, Subsequent Attempts Fail with 'No Free Slot to Place the Image' Error

I am using Bluetooth for DFU in NCS version 2.6.1, but I encountered an issue in Device Manager that says, "There is no free slot to place the image." In the JLINK RTT, I received the following information:




&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 0x00075000>;
		};
		slot1_partition: partition@81000 {
			label = "image-1";
			reg = <0x00081000 0x00075000>;
		};
		scratch_partition: partition@E8000 {
			label = "image-scratch";
			reg = <0x000E8000 0x00010000>;
		};

		/*
		 * The flash starting at 0x000f8000 and ending at
		 * 0x000fffff is reserved for use by the application.
		 */

		/*
		 * Storage partition will be used by FCB/LittleFS/NVS
		 * if enabled.
		 */
		storage_partition: partition@f8000 {
			label = "storage";
			reg = <0x000f8000 0x00008000>;
		};
	};
};

[8/16] Linking C executable zephyr/zephyr.elf Memory region Used Size Region Size %age
Used FLASH: 325820 B 495104 B 65.81%
RAM: 120100 B 256 KB 45.81%
IDT_LIST: 0 GB 32 KB 0.00%
Parents
  • Hello  

    Same issue.

    My secondary slot is on the external QSPI flash.

    When the QSPI flash is blank, I can upload the 2nd firmware to the secondary slot. It showed success:

    But after it reset, the firmware in primary slot and secondary slot are not swapped. It is still running the first image.

    Then I tried to upload the 3rd firmware to the secondary slot. It shows the same error log as this ticket. 

    That is because the 2nd firmware is still in the secondary slot (slot1).

    So, the 3rd firmware can't be upload.

    I believe there are some wrong configurations, but I can't figure them out. Could you help?

    `mcuboot.conf`: I modified this like the Matter MCUBOOT, because I want to reduce the size from 0xC000 to 0x7000 

    #
    # Copyright (c) 2021 Nordic Semiconductor
    #
    # SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
    #
    
    # CONFIG_BOOT_MAX_IMG_SECTORS=240
    # CONFIG_REBOOT=y
    # CONFIG_DISABLE_FLASH_PATCH=y
    
    # # Disable memory guard to avoid false faults in application after boot
    CONFIG_HW_STACK_PROTECTION=n
    
    CONFIG_SYSTEM_CLOCK_NO_WAIT=y
    
    CONFIG_MAIN_STACK_SIZE=10240
    
    CONFIG_BOOT_BOOTSTRAP=n
    
    CONFIG_BOOT_SIGNATURE_TYPE_ECDSA_P256=y
    
    # ## replace the default signing key with your own key before production ##
    # # 
    # # The bootloader private key is generated by:
    # # openssl ecparam -name prime256v1 -genkey -noout -out priv.pem
    # # 
    # # Use the absolute path to the private key file
    # # 
    # # CONFIG_BOOT_SIGNATURE_KEY_FILE="/xxx/xxx/mcuboot_private.pem"
    
    
    # ## the following kCONFIG_is used to make external flash as the secondary slot
    # CONFIG_FLASH=y
    
    # # Required by QSPI
    # CONFIG_MULTITHREADING=y
    
    # CONFIG_NORDIC_QSPI_NOR=y
    # CONFIG_NORDIC_QSPI_NOR_FLASH_LAYOUT_PAGE_SIZE=4096
    # CONFIG_NORDIC_QSPI_NOR_STACK_WRITE_BUFFER_SIZE=16
    
    CONFIG_BOOT_SWAP_SAVE_ENCTLV=n
    
    CONFIG_BOOT_SWAP_USING_MOVE=y
    
    CONFIG_PM=n
    
    CONFIG_FLASH=y
    
    CONFIG_FPROTECT=y
    
    CONFIG_NORDIC_QSPI_NOR=y
    
    CONFIG_NORDIC_QSPI_NOR_FLASH_LAYOUT_PAGE_SIZE=4096
    
    CONFIG_NORDIC_QSPI_NOR_STACK_WRITE_BUFFER_SIZE=16
    
    
    CONFIG_BOOT_MAX_IMG_SECTORS=256
    
    CONFIG_LOG=n
    
    CONFIG_CONSOLE_HANDLER=n
    
    CONFIG_BOOT_BANNER=n
    
    CONFIG_TIMESLICING=n
    
    CONFIG_RESET_ON_FATAL_ERROR=n
    
    CONFIG_MULTITHREADING=n
    
    CONFIG_TICKLESS_KERNEL=n
    
    CONFIG_TIMEOUT_64BIT=n
    
    CONFIG_NRF_ENABLE_ICACHE=n
    
    CONFIG_MBEDTLS_CFG_FILE="mcuboot-mbedtls-cfg.h"
    
    # Bootloader size optimization
    # Disable not used modules that cannot be set in Kconfig.mcuboot.defaults due to overriding
    # in board files.
    CONFIG_GPIO=n
    CONFIG_CONSOLE=n
    CONFIG_SERIAL=n
    CONFIG_UART_CONSOLE=n
    CONFIG_USE_SEGGER_RTT=n
    
    # Use minimal C library instead of the Picolib
    CONFIG_MINIMAL_LIBC=y

    `prj.conf`: I only put the DFU related configurations here.

    # flash partition
    CONFIG_PARTITION_MANAGER_ENABLED=y
    CONFIG_PM_EXTERNAL_FLASH_MCUBOOT_SECONDARY=y
    # same as pm_static.yml
    CONFIG_PM_PARTITION_SIZE_SETTINGS_STORAGE=0x7200
    
    # Bootloader and DFU
    CONFIG_BOOTLOADER_MCUBOOT=y
    CONFIG_NET_BUF=y
    CONFIG_ZCBOR=y
    CONFIG_CRC=y
    CONFIG_MCUMGR=y
    CONFIG_STREAM_FLASH=y
    CONFIG_MCUMGR_TRANSPORT_BT=y
    CONFIG_MCUMGR_TRANSPORT_BT_AUTHEN=n
    CONFIG_MCUMGR_TRANSPORT_BT_CONN_PARAM_CONTROL=y
    # Allow for large Bluetooth data packets.
    CONFIG_BT_L2CAP_TX_MTU=498
    CONFIG_BT_BUF_ACL_RX_SIZE=502
    CONFIG_BT_BUF_ACL_TX_SIZE=502
    # Enable the mcumgr Packet Reassembly feature over Bluetooth and its configuration dependencies.
    # MCUmgr buffer size is optimized to fit one SMP packet divided into five Bluetooth Write Commands,
    # transmitted with the maximum possible MTU value: 498 bytes.
    CONFIG_MCUMGR_TRANSPORT_BT_REASSEMBLY=y
    CONFIG_MCUMGR_TRANSPORT_NETBUF_SIZE=2475
    CONFIG_IMG_MANAGER=y
    CONFIG_MCUMGR_GRP_IMG=y
    CONFIG_MCUMGR_GRP_OS=y
    CONFIG_MCUMGR_GRP_OS_MCUMGR_PARAMS=y
    CONFIG_MCUMGR_TRANSPORT_WORKQUEUE_STACK_SIZE=4608
    CONFIG_BT_CTLR_LE_PING=n
    CONFIG_MCUMGR_LOG_LEVEL_DBG=y
    CONFIG_BT_SMP_LOG_LEVEL_DBG=y
    
    
    # MCUMGR Debug
    # CONFIG_STATS=y
    # CONFIG_STATS_NAMES=y
    # CONFIG_MCUMGR_GRP_STAT=y
    # CONFIG_THREAD_MONITOR=y
    #
    # CONFIG_MCUMGR_GRP_OS_TASKSTAT=y

    pm_static.yml:

    mcuboot:
      address: 0x0
      size: 0x7000
      region: flash_primary
    mcuboot_pad:
      address: 0x7000
      size: 0x200
    app:
      address: 0x7200
      size: 0xf8e00
    mcuboot_primary:
      orig_span: &id001
      - mcuboot_pad
      - app
      span: *id001
      address: 0x7000
      size: 0xf9000
      region: flash_primary
    mcuboot_primary_app:
      orig_span: &id002
      - app
      span: *id002
      address: 0x7200
      size: 0xf8e00
    mcuboot_secondary:
      address: 0x0
      size: 0xf8e00
      device: mx25r80
      region: external_flash
    settings_storage:
      address: 0xf8e00
      size: 0x7200
      device: mx25r80
      region: external_flash  

  • Hello,

    I suspect the same thing here. From your mobile screenshot it looks like the active image is not the permanent image. If you, at this point (the point where that screenshot was captured), reset your device again. Which FW boots up? Is it the original FW or the FW from the first DFU?

    I think the reason you (both of you) end up in this state is because of a mechanism that can be used for testing new firmware without permanently "installing" it. After a DFU, it will boot the new FW once. Then after a new reboot it will boot the old firmware again. 

    There are two ways of making the swap permanent. Either you can do it from software, when you reach a certain point in your application (perhaps some self-check), and you can call boot_is_img_confirmed() to check whether the image is confirmed, and call boot_write_img_confirmed() to confirm it.

    Something like this:

        rc = boot_is_img_confirmed();
        LOG_INF("Image is%s confirmed.", rc ? "" : " not");
        if (!rc) {
            if (boot_write_img_confirmed()) {
                LOG_ERR("Failed to confirm image");
            } else {
                LOG_INF("Marked image as OK");
            }
        }

    Alternatively, you can do this when you upload the image. I don't remember what it is called in the app, but something like "permanent" or "verified", to tell the bootloader that it can erase the old application image once the swap is complete.

    Best regards,

    Edvin

Reply
  • Hello,

    I suspect the same thing here. From your mobile screenshot it looks like the active image is not the permanent image. If you, at this point (the point where that screenshot was captured), reset your device again. Which FW boots up? Is it the original FW or the FW from the first DFU?

    I think the reason you (both of you) end up in this state is because of a mechanism that can be used for testing new firmware without permanently "installing" it. After a DFU, it will boot the new FW once. Then after a new reboot it will boot the old firmware again. 

    There are two ways of making the swap permanent. Either you can do it from software, when you reach a certain point in your application (perhaps some self-check), and you can call boot_is_img_confirmed() to check whether the image is confirmed, and call boot_write_img_confirmed() to confirm it.

    Something like this:

        rc = boot_is_img_confirmed();
        LOG_INF("Image is%s confirmed.", rc ? "" : " not");
        if (!rc) {
            if (boot_write_img_confirmed()) {
                LOG_ERR("Failed to confirm image");
            } else {
                LOG_INF("Marked image as OK");
            }
        }

    Alternatively, you can do this when you upload the image. I don't remember what it is called in the app, but something like "permanent" or "verified", to tell the bootloader that it can erase the old application image once the swap is complete.

    Best regards,

    Edvin

Children
  • Hello Edvin,

    You're right, the application should CONFIRM the new image after DFU.

    I have fixed this issue. In my case, I use SMP DFU over BLE, so it seems that the nRF Connect APP on smart phone will help to confirm the new image. So, I don't need to call the `boot_write_img_confirmed()` explicitly.

    Let's talk about the DFU failed issue. The root cause seems to be that my partition is not aligned for 4k Bytes, which is the minimal erase unit size (Sector size) of th QSPI flash:

    Here is my latest `pm_static.yml`. It is for MX25R80F (1M Bytes QSPI Flash):

    mcuboot:
      address: 0x0
      size: 0x7000
      region: flash_primary
    mcuboot_pad:
      address: 0x7000
      size: 0x200
    app:
      address: 0x7200
      size: 0xf8e00
    mcuboot_primary:
      orig_span: &id001
      - mcuboot_pad
      - app
      span: *id001
      address: 0x7000
      size: 0xf9000
      region: flash_primary
    mcuboot_primary_app:
      orig_span: &id002
      - app
      span: *id002
      address: 0x7200
      size: 0xf8e00
    mcuboot_secondary:
      address: 0x0
      size: 0xf9000
      device: mx25r80
      region: external_flash
    settings_storage:
      address: 0xf9000
      size: 0x7000
      device: mx25r80
      region: external_flash  

    Related devicetree overlay:

    /{
        chosen {
            // necessary for the partition manager
            nordic,pm-ext-flash = &mx25r80;
        };
    };
    
    
    &qspi {
    	status = "okay";
    	pinctrl-0 = <&qspi_default>;
    	pinctrl-1 = <&qspi_sleep>;
    	pinctrl-names = "default", "sleep";
    	/delete-node/ mx25r6435f@0;
    	mx25r80: mx25r8035f@0 {
    		compatible = "nordic,qspi-nor";
    		reg = <0>;
    		/* MX25R64 supports only pp and pp4io */
    		writeoc = "pp4io";
    		/* MX25R64 supports all readoc options */
    		readoc = "read4io";
    		sck-frequency = <8000000>;
    		jedec-id = [c2 28 14];
    		sfdp-bfp = [
                e5 20 f1 ff  ff ff 7f 00  44 eb 08 6b  08 3b 04 bb
                ee ff ff ff  ff ff 00 ff  ff ff 00 ff  0c 20 0f 52
                10 d8 00 ff  23 72 f5 00  82 ed 04 b7  44 83 38 44
                30 b0 30 b0  f7 c4 d5 5c  00 be 29 ff  f0 d0 ff ff
            ]; 
    		size = <0x800000>; // 8M Bits
    		has-dpd;
    		t-enter-dpd = <10000>;
    		t-exit-dpd = <35000>;
    	};
    };

    Related config (You may need to add some dependency by yourself):

    # flash partition
    CONFIG_PARTITION_MANAGER_ENABLED=y
    CONFIG_PM_EXTERNAL_FLASH_MCUBOOT_SECONDARY=y
    
    # Bootloader
    CONFIG_BOOTLOADER_MCUBOOT=y
    
    ### DFU Supported by mcumgr
    CONFIG_NET_BUF=y
    CONFIG_ZCBOR=y
    CONFIG_MCUMGR=y
    
    # DFU Transport
    CONFIG_MCUMGR_TRANSPORT_BT=y
    CONFIG_MCUMGR_TRANSPORT_BT_AUTHEN=n
    CONFIG_MCUMGR_TRANSPORT_BT_CONN_PARAM_CONTROL=y
    # Allow for large Bluetooth data packets.
    CONFIG_BT_L2CAP_TX_MTU=498
    CONFIG_BT_BUF_ACL_RX_SIZE=502
    CONFIG_BT_BUF_ACL_TX_SIZE=502
    # Enable the mcumgr Packet Reassembly feature over Bluetooth and its configuration dependencies.
    # MCUmgr buffer size is optimized to fit one SMP packet divided into five Bluetooth Write Commands,
    # transmitted with the maximum possible MTU value: 498 bytes.
    CONFIG_MCUMGR_TRANSPORT_BT_REASSEMBLY=y
    CONFIG_MCUMGR_TRANSPORT_NETBUF_SIZE=2475
    CONFIG_BT_CTLR_LE_PING=n
    
    # DFU Storage and erase
    CONFIG_STREAM_FLASH=y
    CONFIG_IMG_MANAGER=y
    CONFIG_MCUMGR_GRP_IMG=y
    CONFIG_MCUMGR_GRP_ZBASIC=y
    CONFIG_MCUMGR_GRP_ZBASIC_STORAGE_ERASE=y
    
    # OS control by mcumgr
    CONFIG_MCUMGR_GRP_OS=y
    CONFIG_MCUMGR_GRP_OS_MCUMGR_PARAMS=y
    CONFIG_MCUMGR_GRP_OS_BOOTLOADER_INFO=y
    CONFIG_MCUMGR_GRP_OS_INFO=y
    CONFIG_MCUMGR_GRP_OS_ECHO=y
    CONFIG_MCUMGR_GRP_OS_TASKSTAT=n

Related