Mass Example with External Flash not working with CONFIG_BOOTLOADER_MCUBOOT=y

Hi,

I have got the sample "samples/subsys/usb/mass" working on a nrf52840dk using the external flash, but as soon as I enable the mcuboot bootloader (CONFIG_BOOTLOADER_MCUBOOT=y) it does not work anymore. Has anyone got a MSD example working with the mcuboot bootloader enabled using the external flash as the storage device?

I use the NRF CONNECT SDK version v.2.3.0. Any help would be appreciated.

Kind Regards

Julian

  • Hi Julian,

    I am not very familiar with the USB Mass Storage sample but let's figure this out.

    I gave what you are doing a try and see that with APP_MSC_STORAGE_FLASH_LITTLEFS and CONFIG_BOOTLOADER_MCUBOOT enabled at the same time, my PC cannot format the drive. At the same time, I don't think it is using external flash, as I would expect from the documentation. Is this the kind of issue you are having?

    If not, could you please give some information on what kind of problems you are seeing?

    Hieu

  • Hi Hieu,

    Thank you so much for assisting with this. Apologies, I see I did not give a lot of details. I am trying to use 

    CONFIG_APP_MSC_STORAGE_FLASH_FATFS=y and CONFIG_BOOTLOADER_MCUBOOT=y together. So I am trying to let the external NOR flash look like a USB flashdrive. Like mentioned I can do this without using CONFIG_BOOTLOADER_MCUBOOT using the external flash, but I soon as I enable CONFIG_BOOTLOADER_MCUBOOT it seems the partition manager starts to mess things up. So my device tree overlay looks like this: 
    / {
    	chosen {
    		nordic,pm-ext-flash = &mx25r64;
    	};
    };
    
    /delete-node/ &storage_partition;
    
    &mx25r64 {
    	partitions {
    		compatible = "fixed-partitions";
    		#address-cells = <1>;
    		#size-cells = <1>;
    
            storage_partition: partition@73000 {
                 label = "storage";
                 reg = <0x000073000 0x00080000>;
            };
    	};
    };
    
     / {
         msc_disk0 {
             compatible = "zephyr,flash-disk";
             partition = <&storage_partition>;
             disk-name = "NAND";
             cache-size = <4096>;
         };
     };
    
    My prj.conf looks like this:
    CONFIG_STDOUT_CONSOLE=y
    
    #USB related configs
    CONFIG_USB_DEVICE_STACK=y
    CONFIG_USB_DEVICE_PRODUCT="Pager Dongle"
    CONFIG_USB_DEVICE_PID=0x0008
    CONFIG_LOG=y
    CONFIG_USB_DRIVER_LOG_LEVEL_ERR=y
    CONFIG_USB_MASS_STORAGE=y
    CONFIG_USB_DEVICE_LOG_LEVEL_ERR=y
    CONFIG_USB_MASS_STORAGE_LOG_LEVEL_ERR=y
    CONFIG_USB_CDC_ACM=n
    CONFIG_USB_DEVICE_INITIALIZE_AT_BOOT=n
    CONFIG_APP_MSC_STORAGE_FLASH_FATFS=y
    CONFIG_MAIN_STACK_SIZE=10240
    CONFIG_APP_WIPE_STORAGE=y
    
    CONFIG_FLASH=y
    
    # Enable mcumgr.
    CONFIG_MCUMGR=y
    
    # Enable most core commands.
    CONFIG_MCUMGR_CMD_IMG_MGMT=y
    CONFIG_MCUMGR_CMD_OS_MGMT=y
    
    # Ensure an MCUboot-compatible binary is generated.
    CONFIG_BOOTLOADER_MCUBOOT=y
    CONFIG_PM_PARTITION_REGION_SETTINGS_STORAGE_EXTERNAL=y
    CONFIG_MCUMGR_SMP_UART=y
    
    CONFIG_MCUBOOT_IMAGE_VERSION="0.1.1+4"
    
    CONFIG_FCB=y
    CONFIG_SETTINGS=y
    CONFIG_SETTINGS_FCB=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_MULTITHREADING=y
    
    # Some command handlers require a large stack.
    CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=8096
    and my pm_static.yml looks like this:
    app:
      address: 0xc200
      end_address: 0x85000
      region: flash_primary
      size: 0x78e00
    settings_storage:
      address: 0
      device: DT_CHOSEN(nordic_pm_ext_flash)
      end_address: 0x0800000
      placement:
        align:
          start: 0x73000
      region: external_flash
      size: 0x0800000
    mcuboot:
      address: 0x0
      end_address: 0xc000
      placement:
        before:
        - mcuboot_primary
      region: flash_primary
      size: 0xc000
    mcuboot_pad:
      address: 0xc000
      end_address: 0xc200
      placement:
        before:
        - mcuboot_primary_app
      region: flash_primary
      size: 0x200
    mcuboot_primary:
      address: 0xc000
      end_address: 0x85000
      orig_span: &id001
      - app
      - mcuboot_pad
      region: flash_primary
      sharers: 0x1
      size: 0x79000
      span: *id001
    mcuboot_primary_app:
      address: 0xc200
      end_address: 0x85000
      orig_span: &id002
      - app
      region: flash_primary
      size: 0x78e00
      span: *id002
    mcuboot_secondary:
      address: 0x85000
      end_address: 0xfe000
      placement:
        after:
        - mcuboot_primary
        align:
          start: 0x1000
      region: flash_primary
      share_size:
      - mcuboot_primary
      size: 0x79000
    my_storage:
      address: 0xfe000
      end_address: 0x100000
      placement:
        align:
          start: 0x1000
        before:
        - end
      region: flash_primary
      size: 0x2000
    sram_primary:
      address: 0x20000000
      end_address: 0x20040000
      region: sram_primary
      size: 0x40000
    And from the partition manager report it looks like this:
      external_flash (0x800000 - 8192kB): 
    +-------------------------------------------+
    | 0x0: settings_storage (0x800000 - 8192kB) |
    | 0x800000: external_flash (0x0 - 0B)       |
    +-------------------------------------------+
    
      flash_primary (0x100000 - 1024kB): 
    +-------------------------------------------------+
    | 0x0: mcuboot (0xc000 - 48kB)                    |
    +---0xc000: mcuboot_primary (0x79000 - 484kB)-----+
    | 0xc000: mcuboot_pad (0x200 - 512B)              |
    +---0xc200: mcuboot_primary_app (0x78e00 - 483kB)-+
    | 0xc200: app (0x78e00 - 483kB)                   |
    +-------------------------------------------------+
    | 0x85000: mcuboot_secondary (0x79000 - 484kB)    |
    | 0xfe000: my_storage (0x2000 - 8kB)              |
    +-------------------------------------------------+
    
      sram_primary (0x40000 - 256kB):
    +--------------------------------------------+
    | 0x20000000: sram_primary (0x40000 - 256kB) |
    +--------------------------------------------+
    And the output:
    But as can be seen in 1 the disk gets initialized way before the main starts (Powered up! is the first line after main) using the internal flash and then it seems the external flash gets initialized, but I can confirm all is just done in the internal flash and not the external flash. I say I know it is only internal flash as I copied some pictures onto the flash drive and then performed a serial dfu and the pictures got corrupted as I intentionally made the address the same as the slot 1 address to see if it is using the external or internal flash.
    Like mentioned all works well if I remove "nordic,pm-ext-flash = &mx25r64;" from the overlay and not us the mcuboot bootloader as I was able to create a 2MB flash drive and copy files over which should not be possible if I used the internal memory which is only 1MB big. (I also had to remove things like CONFIG_PM_PARTITION_REGION_SETTINGS_STORAGE_EXTERNAL=y from the prj.conf and the pm_static.yml file, etc)
    Thank you again for assisting me with this and please let me know if you need anymore detail.
    Kind Regards
    Julian
     
  • Hi Julian,

    JulianWilmot said:
    but I soon as I enable CONFIG_BOOTLOADER_MCUBOOT it seems the partition manager starts to mess things up.

    You are right. It looks like FAT FS on External Flash is not working with Partition Manager at the moment.

    I found this DevZone question on the same topic:  How to use FATFS with partition manager? .

    The root cause seems to be that the Disk subsystem of Zephyr and the Partition Manager are incompatible. The Partition Manager overrides DTS-based partitioning completely, while the Disk subsystem relies on the DTS definition to work. Thus, we have this issue.

    I have an idea about swapping things around and have MCUboot Secondary on the External Flash and the FAT FS partition on internal flash instead. I didn't get to actually test if this is possible yet, but is this something that, if worked, you can use?

    Best regards,

    Hieu

    P.s: The hope for that workaround is not very high, as fundamentally the Disk subsystem and the Partition Manager still have to be around each other. However, there is a chance that we can manipulate the DTS part somehow if it is on internal flash.

  • Hi Hieu,

    Hope you are doing well. Thanks for coming back to me with this. You are 100% correct and great suggestion, that was my original idea is to have either the secondary image on external flash or the flashdrive. As the problem is just that there is not enough internal flash to do both for my purpose. 

    On the secondary image on external flash, I followed this example but it is not working either:

    https://github.com/simon-iversen/sdk-zephyr/tree/serial_dfu_ext_flash_hello_world/samples/hello_world

    I can see that the secondary image gets copied over to the external flash with mcumgr cli, but I cannot confirm nor test the secondary image (it says pending, but cannot switch to it), it always just boots up with the primary image when I reset. Also how would this work as it needs to run the secondary test image and unless it runs in XIP how would it be possible? I must mention that my images are not signed, but I can do the firmware upgrade via mcumgr cli when both images are on the internal flash without problems, it just does not want to switch to the secondary images when using external flash. Any ideas what I am doing wrong?

    B.T.W I got my original question working a couple of minutes ago so I can get the flashdrive to work with the external memory using mcuboot, and will share the details how shortly. But I still would like the secondary image to work with external flash for incase my codebase grows.

    So if you can assist me with that please?

    Kind Regards

    Julian

  • Hi Julian,

    JulianWilmot said:
    B.T.W I got my original question working a couple of minutes ago so I can get the flashdrive to work with the external memory using mcuboot, and will share the details how shortly.

    Excellent news. I look forwards to the details.

    Now onto the "new" issue in Plan B.

    JulianWilmot said:

    On the secondary image on external flash, I followed this example but it is not working either:

    https://github.com/simon-iversen/sdk-zephyr/tree/serial_dfu_ext_flash_hello_world/samples/hello_world

    Does it not work out of the box? Or are you trying to replicate the steps in that sample onto the USB Mass storage sample?

    JulianWilmot said:
    Also how would this work as it needs to run the secondary test image and unless it runs in XIP how would it be possible?

    It swaps the images in primary and secondary. Please refer to: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/2.3.0/mcuboot/design.html#image-swapping.

    Direct-XiP is also theoretically possible. However, to my knowledge, that solution is unfinished.

    JulianWilmot said:

    But I still would like the secondary image to work with external flash for incase my codebase grows.

    So if you can assist me with that please?

    Sure, I am on board. However, if this is not urgent, I hope you don't mind if I return in 1~1.5 week. My team is facing high loading due to some unavailability, and I am also out of office for the majority of the time until the end of the next week.

    My apology for the inconvenience.

    Best regards,

    Hieu

Related