MCUboot clash with USB Mass Device Littlefs Partition

Hi everyone,

I am trying to run a Zephyr application (NRF52833 device) which has external flash accessed via SPI. On the external flash, there is a second image (MCUboot) and a Littlefs partition.

The Zephyr application is configured to be a USB Mass storage device where the littlefs partition can be accessed either via LittleFS explorer (Windows) or Littlefs_fuse (Linux).

If I have MCUboot disabled, the application works fine and I can access/read/write to the littlefs partition fine in both Windows and Linux. If I enable MCUboot – I cannot access the littlefs partition via USB (see littlefs_fuse screenshot).

I have attached the relevant the .conf files and the .dts file for the nrf52833 board.

MCUBoot.conf

CONFIG_MAIN_STACK_SIZE=10240

CONFIG_DEBUG_OPTIMIZATIONS=y

# Enable flash operations
CONFIG_FLASH=y

# This must be increased to accommodate the bigger images.
CONFIG_BOOT_MAX_IMG_SECTORS=4096

CONFIG_PM_PARTITION_SIZE_MCUBOOT=0x20000

# Disable UART Console and enable the RTT console
CONFIG_UART_CONSOLE=n
CONFIG_RTT_CONSOLE=y
CONFIG_USE_SEGGER_RTT=y

# Config logger
CONFIG_LOG_BACKEND_RTT=y
CONFIG_LOG_BACKEND_UART=n
CONFIG_LOG_MODE_MINIMAL=y
CONFIG_LOG=y
CONFIG_LOG_DEFAULT_LEVEL=0

CONFIG_MULTITHREADING=y

CONFIG_SIZE_OPTIMIZATIONS=y

# MCUBoot serial
CONFIG_MCUBOOT_SERIAL=y
CONFIG_BOOT_SERIAL_CDC_ACM=y
CONFIG_MCUBOOT_INDICATION_LED=y
CONFIG_BOOT_SERIAL_DETECT_DELAY=10

# USB
CONFIG_USB_DEVICE_STACK=y
CONFIG_USB_DEVICE_PRODUCT="MCUBOOT"
CONFIG_USB_CDC_ACM=y
CONFIG_USB_COMPOSITE_DEVICE=n
CONFIG_USB_MASS_STORAGE=n

Proj.conf

CONFIG_CPLUSPLUS=y
CONFIG_NEWLIB_LIBC=y
CONFIG_LIB_CPLUSPLUS=y

CONFIG_SOC_SERIES_NRF52X=y
CONFIG_SOC_NRF52833_QIAA=y

CONFIG_DEBUG_OPTIMIZATIONS=y

CONFIG_RESET_ON_FATAL_ERROR=n

CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=4096
CONFIG_MAIN_STACK_SIZE=2048 

# Enable MPU
CONFIG_ARM_MPU=y

# Enable hardware stack protection
CONFIG_HW_STACK_PROTECTION=y

# Enable RTT
CONFIG_USE_SEGGER_RTT=y
CONFIG_RTT_CONSOLE=y

# enable GPIO
CONFIG_GPIO=y

# enable uart driver
CONFIG_SERIAL=y

# enable console
CONFIG_CONSOLE=y
CONFIG_UART_CONSOLE=n

# additional board options
CONFIG_GPIO_AS_PINRESET=y

CONFIG_PINCTRL=y
CONFIG_ASSERT=y

CONFIG_LOG=y
CONFIG_LOG_MODE_DEFERRED=y # Using deferred for time being as immediate casues hang due to interaction with shell
CONFIG_LOG_SPEED=y

CONFIG_PRINTK=y 

# K Events
CONFIG_EVENTS=y

# Perpherials 
CONFIG_I2C=y
CONFIG_GPIO=y
CONFIG_SPI=y

# AEM
CONFIG_HEAP_MEM_POOL_SIZE=2048
CONFIG_APP_EVENT_MANAGER=y
CONFIG_APP_EVENT_MANAGER_LOG_LEVEL_OFF=y # Logs disabled unless required for debugging


# CAF
CONFIG_CAF=y

# Buttons
CONFIG_CAF_BUTTON_EVENTS=y
CONFIG_CAF_BUTTONS_LOG_LEVEL_WRN=y

# Click
CONFIG_CAF_CLICK_EVENTS=y
CONFIG_CAF_CLICK_DETECTOR_LOG_LEVEL_WRN=y

#########################

# Debug
CONFIG_THREAD_STACK_INFO=y
CONFIG_KERNEL_SHELL=y
CONFIG_THREAD_MONITOR=y
CONFIG_BOOT_BANNER=n
CONFIG_THREAD_NAME=y
CONFIG_INIT_STACKS=y
CONFIG_POSIX_CLOCK=y
CONFIG_DATE_SHELL=y
CONFIG_STATS=y
CONFIG_THREAD_RUNTIME_STATS=y
CONFIG_THREAD_RUNTIME_STATS_USE_TIMING_FUNCTIONS=y

# Toolchain
CONFIG_NEWLIB_LIBC=y

# Bootloader
CONFIG_BOOTLOADER_MCUBOOT=y

# Shell
CONFIG_SHELL=y
CONFIG_SHELL_CMDS=y
CONFIG_SHELL_LOG_BACKEND=y
CONFIG_SHELL_BACKEND_RTT=y
CONFIG_I2C_SHELL=y
CONFIG_DEVICE_SHELL=y
CONFIG_SHELL_BACKENDS=y
CONFIG_SHELL_GETOPT=y
CONFIG_STATS_SHELL=y
CONFIG_SHELL_CMD_ROOT="login"
CONFIG_SHELL_CMDS_SELECT=y
CONFIG_SHELL_START_OBSCURED=n

# Buttons
CONFIG_CAF_BUTTONS=y
CONFIG_CAF_BUTTONS_DEF_PATH="custom/buttons_def.h"
CONFIG_CAF_BUTTONS_POLARITY_INVERSED=y

# Click
CONFIG_CAF_CLICK_DETECTOR=y
CONFIG_CAF_CLICK_DETECTOR_DEF_PATH="custom/click_detector_def.h"

# USB CDC
CONFIG_STDOUT_CONSOLE=y
CONFIG_USB_DEVICE_STACK=y
CONFIG_USB_DEVICE_PRODUCT="CUSTOM MASS DEVICE"
CONFIG_USB_DRIVER_LOG_LEVEL_ERR=y
CONFIG_USB_DEVICE_LOG_LEVEL_ERR=y
CONFIG_USB_CDC_ACM_LOG_LEVEL_ERR=y
CONFIG_SERIAL=y
CONFIG_UART_INTERRUPT_DRIVEN=y
CONFIG_UART_LINE_CTRL=y
CONFIG_SHELL_BACKEND_SERIAL=y
CONFIG_ISR_STACK_SIZE=4096
CONFIG_USB_NRFX_WORK_QUEUE_STACK_SIZE=2048
CONFIG_LOG_PROCESS_THREAD_STACK_SIZE=4096

## SHELL to Uart interface
CONFIG_SHELL_BACKEND_SERIAL_INIT_PRIORITY=51
CONFIG_SHELL_PROMPT_UART="uart: "

# FLASH Driver
CONFIG_FLASH=y
CONFIG_NORDIC_QSPI_NOR=y

# Setup Little Fs system
CONFIG_SPI_NOR=y
CONFIG_SPI_NOR_FLASH_LAYOUT_PAGE_SIZE=4096  

CONFIG_FLASH_MAP=y
CONFIG_FLASH_PAGE_LAYOUT=y

CONFIG_FILE_SYSTEM=y
CONFIG_FILE_SYSTEM_LITTLEFS=y

CONFIG_FS_LOG_LEVEL_WRN=y

CONFIG_PM_PARTITION_REGION_LITTLEFS_EXTERNAL=y
CONFIG_PM_PARTITION_SIZE_LITTLEFS=0x0200000

# USB Composite device + littleFS MSC Config
CONFIG_USB_COMPOSITE_DEVICE=y
CONFIG_USB_MASS_STORAGE=y
CONFIG_USB_MASS_STORAGE_LOG_LEVEL_ERR=y
CONFIG_USB_DEVICE_INITIALIZE_AT_BOOT=n



CONFIG_DISK_DRIVER_FLASH=y
CONFIG_MASS_STORAGE_DISK_NAME="NAND"

Custom_Board.dts

/dts-v1/;
#include <nordic/nrf52833_qiaa.dtsi>
#include <zephyr/dt-bindings/adc/adc.h>
#include <zephyr/dt-bindings/adc/nrf-adc.h>
#include <zephyr/dt-bindings/led/led.h>
#include "custom-pinctrl.dtsi"

/ {
	model = "Custom Rig";
	compatible = "company,custom";
	zephyr,user {
		io-channels = <&adc 0>, <&adc 1>, <&adc 2>, <&adc 3>, <&adc 4>, <&adc 6>;	
	};

	chosen {
		zephyr,console = &uart1;
		zephyr,shell-uart = &cdc_acm_uart0;
		zephyr,uart-mcumgr = &uart1;
		zephyr,bt-mon-uart = &uart1;
		zephyr,bt-c2h-uart = &uart1;
		zephyr,sram = &sram0;
		zephyr,flash = &flash0;
		zephyr,code-partition = &slot0_partition;
		nordic,pm-ext-flash = &spi_flash0;
	};

	aliases {
		statusled = &left_right_led;
		mcuboot-button0 = &startbutton;
		mcuboot-led0 = &left_right_led;
	};

	
	fstab {
		compatible = "zephyr,fstab";
		lfs1: lfs1 {
			compatible = "zephyr,fstab,littlefs";
			mount-point = "/lfs";
			partition = <&storage>;
			//automount;
			read-size = <16>;
			prog-size = <16>;
			cache-size = <64>;
			lookahead-size = <32>;
			block-cycles = <512>;
		};
	};

	msc_disk0 {
		compatible = "zephyr,flash-disk";
		partition = <&storage>;
		disk-name = "NAND";
		cache-size = <4096>;
	};

	leds {
		compatible = "gpio-leds";
		left_right_led: leftrightled {
			gpios = <&gpio0 31 GPIO_ACTIVE_HIGH>;
			label = "Power LED";
		};
	};
	
	pwm {
		compatible = "pwm-leds";
		pump0: pump_0 {
			pwms = <&pwm0 0 PWM_MSEC(20) PWM_POLARITY_NORMAL>;
		};
	};
	
	buttons {
		compatible = "gpio-keys";
		powerbutton: power_button {
			gpios = <&gpio0 11 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>;
			label = "Power Button";
		};
		
		leftrightbutton: left_right_button {
			gpios = <&gpio0 30 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>;
			label = "Left Righ button";
		};
		
		startbutton: start_button {
			gpios = <&gpio1 5 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>;
			label = "Start Button button";
		};
	};

	
};

&gpiote {
	status = "okay";
};

&gpio0 {
	status = "okay";
};

&gpio1 {
	status = "okay";
};






&spi1 {
	compatible = "nordic,nrf-spi";
	status = "disabled";
};

&spi2 {
	compatible = "nordic,nrf-spi";
	status = "okay";
	cs-gpios = <&gpio0 8 GPIO_ACTIVE_LOW>; // Flash SPI CS pin
	pinctrl-0 = <&spi2_default>;
	pinctrl-1 = <&spi2_sleep>;
	pinctrl-names = "default", "sleep";

	spi_flash0: w25q01jvzeiq@0 {
		compatible = "jedec,spi-nor";
		reg = <0>;
		spi-max-frequency = <133000000>;
		jedec-id = [ef 40 17]; 
		size = <0x4000000>; // 32MBits
		has-dpd; // Device Power Down 
		t-enter-dpd = <3500>;  // used tdp value (page 66) - 3us, used 3.5us for increased time 
		t-exit-dpd = <20000>;  // used tvsl value (page 62) - 20us before first read delay
	};
	


};




&flash0 {

	partitions {
		compatible = "fixed-partitions";
		#address-cells = <1>;
		#size-cells = <1>;

		boot_partition: partition@0 {
			reg = <0x00000000 0xC000>;
		};
		slot0_partition: partition@c000 {
			reg = <0x0000C000 0x32000>;
		};

		scratch_partition: partition@70000 {
			reg = <0x00070000 0xA000>;
		};
	
		};
	};


 zephyr_udc0: &usbd {
	compatible = "nordic,nrf-usbd";
	status = "okay";

	cdc_acm_uart0: cdc_acm_uart0 {
		compatible = "zephyr,cdc-acm-uart";
	};
}; 

&spi_flash0 {
	partitions {
		compatible = "fixed-partitions";
		#address-cells = <1>;
		#size-cells = <1>;

		slot1_partition: partition@0 {
			reg = <0x00000000 0x60000>;
		};
		
		storage: partition@60000 {
			reg = <0x00060000 0x0200000>;
		};

	};
};





I have also attached the compiled partition.yaml which seems to show all partitions are in the right place.

Partitions.yaml

app:
  address: 0x20200
  end_address: 0x80000
  region: flash_primary
  size: 0x5fe00
external_flash:
  address: 0x260000
  end_address: 0x800000
  region: external_flash
  size: 0x5a0000
littlefs_storage:
  address: 0x60000
  device: DT_CHOSEN(nordic_pm_ext_flash)
  end_address: 0x260000
  placement:
    before:
    - tfm_storage
    - end
  region: external_flash
  size: 0x200000
mcuboot:
  address: 0x0
  end_address: 0x20000
  placement:
    before:
    - mcuboot_primary
  region: flash_primary
  size: 0x20000
mcuboot_pad:
  address: 0x20000
  end_address: 0x20200
  placement:
    before:
    - mcuboot_primary_app
  region: flash_primary
  size: 0x200
mcuboot_primary:
  address: 0x20000
  end_address: 0x80000
  orig_span: &id001
  - mcuboot_pad
  - app
  region: flash_primary
  size: 0x60000
  span: *id001
mcuboot_primary_app:
  address: 0x20200
  end_address: 0x80000
  orig_span: &id002
  - app
  region: flash_primary
  size: 0x5fe00
  span: *id002
mcuboot_secondary:
  address: 0x0
  device: DT_CHOSEN(nordic_pm_ext_flash)
  end_address: 0x60000
  placement:
    align:
      start: 0x4
  region: external_flash
  share_size:
  - mcuboot_primary
  size: 0x60000
sram_primary:
  address: 0x20000000
  end_address: 0x20020000
  region: sram_primary
  size: 0x20000

I must be missing something however I am not sure what direction to proceed in.

I have read that enabling mcuboot ignores the board.dts and uses the partition manager however the partition.yaml suggests this is okay? (maybe not..)

Has anyone come across this before?

Thanks,

David

  • Hi,

     

    Could you share the serial log output of a working and a non-working scenario? 

    It looks like the external_flash area ranges up to 0x80_0000 (8MByte), while the SPI_NOR flash is 32 Mbit. Is there a typo here?

     

    On a separate note:

    You should select "compatible = "nordic,nrf-spim";" to utilize DMA capabilities of the NRF_SPIM peripheral.

     

    Kind regards,

    Håkon

  • Hi Håkon, 

    Thank you for responding, I have looked at the logs and frustratingly they look similar between working and non-working. I have created a NRF52833DK littlefs example project which demonstrate this issue (littlefs is in internal flash instead of external flash) - if have attached this project with this post. If you comment out CONFIG_BOOTLOADER_MCUBOOT the issue disappears. I will collate the logs in the meantime.

    Thanks, 

    Davidmass-nrf52833-mcuboot.zip

  • Hi David,

     

    Here's with MCUBoot enabled:

    *** Booting Zephyr OS build v3.2.99-ncs2 ***
    I: Starting bootloader
    I: Primary image: magic=unset, swap_type=0x1, copy_done=0x3, image_ok=0x3
    I: Secondary image: magic=unset, swap_type=0x1, copy_done=0x3, image_ok=0x3
    I: Boot source: none
    I: Swap type: none
    I: Bootloader chainload address offset: 0xc000
    *** Booting Zephyr OS build v3.2.99-ncs2 ***
    [00:00:00.000,183] <inf> flashdisk: Initialize device NAND
    [00:00:00.000,213] <inf> flashdisk: offset 46000, sector size 512, page size 4096, volume size 237568
    Area 6 at 0x7a000 on flash-controller@4001e000 for 24576 bytes
    [00:00:00.000,549] <inf> littlefs: LittleFS version 2.5, disk version 2.0
    [00:00:00.000,671] <inf> littlefs: FS at flash-controller@4001e000:0x7a000 is 6 0x1000-byte blocks with 512 cycle
    [00:00:00.000,671] <inf> littlefs: sizes: rd 16 ; pr 16 ; ca 64 ; la 32
    [00:00:00.000,793] <err> littlefs: WEST_TOPDIR/modules/fs/littlefs/lfs.c:1234: Corrupted dir pair at {0x0, 0x1}
    [00:00:00.000,823] <wrn> littlefs: can't mount (LFS -84); formatting
    [00:00:00.175,415] <inf> littlefs: /lfs mounted
    Mount /lfs: 0
    /lfs: bsize = 16 ; frsize = 4096 ; blocks = 6 ; bfree = 4
    /lfs opendir: 0
    End of files
    [00:00:00.226,379] <inf> main: The device is put in USB mass storage mode.
    

    And here's with it disabled:

    *** Booting Zephyr OS build v3.2.99-ncs2 ***
    [00:00:00.345,581] <inf> flashdisk: Initialize device NAND
    [00:00:00.345,581] <inf> flashdisk: offset 46000, sector size 512, page size 4096, volume size 237568
    Area 0 at 0x46000 on flash-controller@4001e000 for 237568 bytes
    [00:00:00.345,916] <inf> littlefs: LittleFS version 2.5, disk version 2.0
    [00:00:00.346,069] <inf> littlefs: FS at flash-controller@4001e000:0x46000 is 58 0x1000-byte blocks with 512 cycle
    [00:00:00.346,069] <inf> littlefs: sizes: rd 16 ; pr 16 ; ca 64 ; la 32
    [00:00:00.346,191] <err> littlefs: WEST_TOPDIR/modules/fs/littlefs/lfs.c:1234: Corrupted dir pair at {0x0, 0x1}
    [00:00:00.346,221] <wrn> littlefs: can't mount (LFS -84); formatting
    [00:00:00.520,935] <inf> littlefs: /lfs mounted
    Mount /lfs: 0
    /lfs: bsize = 16 ; frsize = 4096 ; blocks = 58 ; bfree = 56
    /lfs opendir: 0
    End of files
    [00:00:00.571,899] <inf> main: The device is put in USB mass storage mode.
    

     

    The difference is that they pick different areas to use for the disk:

    [00:00:00.346,069] <inf> littlefs: FS at flash-controller@4001e000:0x46000 is 58 0x1000-byte blocks with 512 cycle
    

    vs:

    [00:00:00.000,671] <inf> littlefs: FS at flash-controller@4001e000:0x7a000 is 6 0x1000-byte blocks with 512 cycle
    

     

    If you have a single-image build, then partition manager is not invoked and the DTS "storage_partition" is used:

    					storage_partition: partition@46000 {
    						label = "storage";
    						reg = < 0x46000 0x3a000 >;
    						phandle = < 0x17 >;
    					};
    

    If you have a multi-image build (ie. with mcuboot), then partition manager is invoked and pm_static.yml is used:

    littlefs_storage:
      address: 0x7a000
      end_address: 0x80000
      placement:
        align:
          start: 0x1000
        before:
        - end
      region: flash_primary
      size: 0x6000
    

     

    Kind regards,

    Håkon

  • Hi Håkon,

    Thanks for your response, as you have mentioned - it has become clear to me that you will need a pm_static.yml if partition manager is used. For my original setup where the second mcuboot image and littlefs fs are placed on an external flash device, I have copied the compilation of partitions.tml and made it into a pm_static.yml file.

    One thing I don't understand: is the external flash entry in the pm_static.yml a duplication?

    When I run 

    west build -t partition_manager_report

    I get the following map:
    external_flash (0x4000000 - 65536kB): 
    +-----------------------------------------------------+
    | 0x0: mcuboot_secondary (0x60000 - 384kB)            |
    | 0x60000: littlefs_storage (0x3fa0000 - 65152kB)     |
    | 0x4000000: external_flash (-0x3800000 - -58720256B) |
    +-----------------------------------------------------+
    
      flash_primary (0x80000 - 512kB): 
    +--------------------------------------------------+
    | 0x0: mcuboot (0x20000 - 128kB)                   |
    +---0x20000: mcuboot_primary (0x60000 - 384kB)-----+
    | 0x20000: mcuboot_pad (0x200 - 512B)              |
    +---0x20200: mcuboot_primary_app (0x5fe00 - 383kB)-+
    | 0x20200: app (0x5fe00 - 383kB)                   |
    +--------------------------------------------------+
    
      sram_primary (0x20000 - 128kB): 
    +--------------------------------------------+
    | 0x20000000: sram_primary (0x20000 - 128kB) |
    +--------------------------------------------+
    I don't understand why 0x4000000: external_flash (-0x3800000 - -58720256B)
    is generated.
    Do you know why this is?
    How would you modify the partitions.yml (or pm_static.yml) file?
    Thanks, 
    David 
  • Hi Håkon, 

    I have had a go at replicating my project with a NRF52840DK board (with MCUBoot second image and littlefs on the external flash), and I am able to replicate my error. 

    MCUboot off -> littlefs_fuse (or windows LittleFS-Explorer-for-Windows) - works fine

    MCUboot on-> littlefs_fuse (or windows LittleFS-Explorer-for-Windows) - unable to connect (partition looks corrupted?).

    I have also added a pm_static.yml file to see if that resolves the issue - but unfortunately it does not.

    I have attached the zip project if you could please have a look and point me in the right direction.

    Thanks,

    Davidmass-nrf52840-mcuboot.zip

Related