nRF5340DK External Flash FatFs with Sysbuild

Hi, we have recently started developing with the nRF5340DK. We encountered several issues while configuring a FATFS on the external flash (mx25r64).
1. The sample code located here [zephyrproject-fs_sample](github.com/.../fs_sample) fails to build out of the box.
    nRF52840 fails with the warning:
    No SOURCES given to Zephyr library: drivers__disk
    nRF5340 fails with the error:
    C:/ncs/v2.9.0/zephyr/drivers/disk/flashdisk.c:533:1:
    error: return type defaults to 'int'   [-Werror=implicit-int] 533
    PM_FOREACH_AFFILIATED_TO_disk(DEFINE_FLASHDISKS_CACHE)
    The solution for this is to add the following config options to the prj.conf:
    CONFIG_FLASH=ys
    CONFIG_FLASH_MAP=y
    It will likely affect some of the other board samples, but I have not had time to look into it more. It would be great if this issue could be fixed upstream so it will work out of the box for others.
2. As the nRF5340 is a multicore SoC, it defaults to using sysbuild, which requires [partition manager](docs.nordicsemi.com/.../partition_manager.html).
    After creating pm_static.yml and overlay files as follows:

  mx25r64:
    affiliation:
      - disk
    region: external_flash
    size: 0x800000
    address: 0x000000
    end_address: 0x7FFFFF
    extra_params: {
      disk_name: "SD",
      disk_cache_size: 4096,
      disk_sector_size: 4096,
      disk_read_only: 0
    }


  / {
     chosen {
         nordic,pm-ext-flash = &mx25r64;
     };
  };

    Attempting to compile results in the following warning:
    warning: DISK_DRIVER_FLASH (defined at drivers/disk/Kconfig.flash:4)
    was assigned the value 'y' but got the value 'n'.
    Check these unsatisfied dependencies: DT_HAS_ZEPHYR_FLASH_DISK_ENABLED (=n).
    and/or look up DISK_DRIVER_FLASH in the menuconfig/guiconfig interface.
    The Application Development Primer, Setting Configuration Values, and Kconfig
    Tips and Best Practices sections of the manual might be helpful too.
    This seems to imply the flash disk driver is not being loaded, as this is usually done by:
    `msc_disk0 { compatible = "zephyr,flash-disk" }`
    Adding it as follows does seem to resolve this issue:

  / {
     chosen {
         nordic,pm-ext-flash = &mx25r64;
     };
     msc_disk0 {
         status="okay";
         compatible = "zephyr,flash-disk";
         // What is the correct way to refer to a
         // Partition Manager partition here?
         partition = <&mx25r64>;
         disk-name = "SD";
         cache-size = <4096>;
     };
  };

    Setting `DT_HAS_ZEPHYR_FLASH_DISK_ENABLED` does not seem like a good idea, so is this the best way to resolve this? If correct, how can I reference a partition manager partition from the device tree, as the docs are unclear? I feel `partition = <&mx25r64>;` likely is not the correct way to do this. However, adding the partition in the device tree also seems wrong, as the device tree ignores it since the partition manager is enabled.

  &mx25r64 {
     partitions {
         compatible = "fixed-partitions";
         external_partition: partition@0 {
             reg = <0x00000000 0x00020000>;
         };
     };
  };

    So, what is the best way to configure this?
3. While the sample code now appears to run correctly, enabling multithreading resulted in random hard faults. After much debugging, I traced this back to FatFs reading a 4096-byte sector from the mx25r64 into the 512-byte default sector buffer in FatFS. This overruns the stack, causing other threads, such as the logging thread, to hard fault and access invalid memory addresses.
    I would have assumed that setting `cache-size = <4096>;` in the device tree or `disk_sector_size: 4096` in the partition manager would correctly update this value in the FatFs config. However, this does not seem to be the case, and it seems necessary to set `CONFIG_FS_FATFS_MAX_SS=4096` in the prj.conf.
    If this is the intended behavior, this should already be set for the nRF board examples, including the mx25r64. It would also be great to see this somewhere in the docs instead of digging through the kconfig tool to find it. It is also relatively simple to make the sample code throw an error if the sector size is not set correctly.

  if (disk_access_ioctl(disk_pdrv,
         DISK_IOCTL_GET_SECTOR_SIZE, &block_size)) {
     LOG_ERR("Unable to get sector size");
     break;
  } else if (block_size > sizeof(fat_fs.win)) {
     LOG_ERR("Sector size %u is larger than FF_MAX_SS %u\n\
             set CONFIG_FS_FATFS_MAX_SS=%u\n",
             block_size, sizeof(fat_fs.win), block_size);
     break;
  } else {
     printk("Sector size %u\n", block_size);
  }

    Ideally, the device tree and partition manager settings should set the FatFs settings correctly, as I'm not sure what else these values would be used for.
Parents
  • Hi,

    It is unfortunate that the sample does not work out of the box in our SDK. Until we have a common solution with upstream for managing the memory layout for multi-image, I'm afraid it is difficult to completely avoid situations like these. 

        I would have assumed that setting `cache-size = <4096>;` in the device tree or `disk_sector_size: 4096` in the partition manager would correctly update this value in the FatFs config. However, this does not seem to be the case, and it seems necessary to set `CONFIG_FS_FATFS_MAX_SS=4096` in the prj.conf.

    I think it is reasonable to expect the disk sector size from the partitioning file to be applied. I will report this internally. I recently did something similar for the nRF52840 DK and its external flash in the demo I posted here:  RE: Using the Mass example on my custom board, but first getting it running on the nRF52840dk QSPI flash . But I didn't encounter any buffer overruns as I was using the default 512 sector size.

    Best regards,

    Vidar

Reply
  • Hi,

    It is unfortunate that the sample does not work out of the box in our SDK. Until we have a common solution with upstream for managing the memory layout for multi-image, I'm afraid it is difficult to completely avoid situations like these. 

        I would have assumed that setting `cache-size = <4096>;` in the device tree or `disk_sector_size: 4096` in the partition manager would correctly update this value in the FatFs config. However, this does not seem to be the case, and it seems necessary to set `CONFIG_FS_FATFS_MAX_SS=4096` in the prj.conf.

    I think it is reasonable to expect the disk sector size from the partitioning file to be applied. I will report this internally. I recently did something similar for the nRF52840 DK and its external flash in the demo I posted here:  RE: Using the Mass example on my custom board, but first getting it running on the nRF52840dk QSPI flash . But I didn't encounter any buffer overruns as I was using the default 512 sector size.

    Best regards,

    Vidar

Children
  • Hi, thank you for your quick response. 

    It is unfortunate that the sample does not work out of the box in our SDK. Until we have a common solution with upstream for managing the memory layout for multi-image, I'm afraid it is difficult to completely avoid situations like these. 

    This makes a lot of sense, are there currently plans for a common solution between nRF and zephyr? If so, is there an issue tracker or something where progress towards this is being tracked?

    Also do you have any input about what the correct way to configure the device tree overlay is, as per question 2 above?

    I'm aware the default sector size for FatFS is 512 Bytes but the samples and the data sheet for the MX25R6435F made it seem like the default was 4096 bytes. I would be fine using 512 Byte sector size. However, it's not clear what config value controls this. The sample does set the FatFS sector size to 512 Bytes but then attempts to read a 4096 Byte sector into it.

    MX25R6435F, Wide Range, 64Mb, v1.6.pdf

  • Hi, 

    Unfortunately, there is no public issue to track this yet, and I'm not aware of any concrete plans I can share. I just know that we are currently exploring alternative solutions. I previously thought we were waiting for system device tree support (github issue), but after asking about it internally I found out that we are actually not dependent on it.

    Michael Wagner said:
    Also do you have any input about what the correct way to configure the device tree overlay is, as per question 2 above?

    I had to do the same in the example I posted in order to get DT_HAS_ZEPHYR_FLASH_DISK_ENABLED selected in Kconfig:

    /* 
     * NOTE: Actual partition placement and size is controlled
     * by the partition manager. DT entries below is to enable
     * flash disk support.
     * 
     * https://docs.nordicsemi.com/bundle/ncs-2.9.0/page/nrf/app_dev/bootloaders_dfu/mcuboot_nsib/bootloader_partitioning.html 
     */
    
    &mx25r64 {
    	partitions {
    		compatible = "fixed-partitions";
    		#address-cells = <1>;
    		#size-cells = <1>;
    
    		external_partition: partition@0 {
    			reg = <0x00000000 0x00020000>;
    		};
    	};
    };
    
    / {
    	msc_disk0 {
    		status="okay";
    		compatible = "zephyr,flash-disk";
    		partition = <&external_partition>;
    		disk-name = "SD";
    		/* cache-size == page erase size */
    		cache-size = <4096>;
    	};
    };

    Michael Wagner said:
    I'm aware the default sector size for FatFS is 512 Bytes but the samples and the data sheet for the MX25R6435F made it seem like the default was 4096 bytes. I would be fine using 512 Byte sector size. However, it's not clear what config value controls this. The sample does set the FatFS sector size to 512 Bytes but then attempts to read a 4096 Byte sector into it.

    Got some comments to this ticket from one of the developers who has been working on this code:

    Depends on what they want. If they want to be able to mount this partition, via USB for example, to Windows/Linux it is advised to use 512 byte, mostly by urban legend that FS drivers are not that well written and usually work best with 512 byte sectors... leftover from floppy disk times. But, if they do not want to mount this thing externally, then 4kiB sector would be preferred, because sector writes would be then aligned with size of erase-page (or secotr) of a device. Note though, that FAT requires 128 sectors to function, so if you choose 512 byte sector, that means you have 128kiB minimal partition, if you choose 4096, then 512KiB. The cache, as mentioned in the user post, is used to avoid multiple erases into one sector.
    Normally to write to any NOR device, the place to write has to be erased; the erase can only happen at specific size, here 4096bytes.
    It does not mean that you have to erase the 4096 bytes every time you want to write within it, because write alignment is something like 4 bytes, which means that you can write any 4 bytes at any time - as long as it has not been already written after last erase.
    FAT writes data in sector size chunks, 512 by default; so you can probably see that it can do 8 of such writes to 4096, independently, keeping alignment to 512 sector size.
    But FAT is done for floppies and it is used to just write anywhere it wants and how many times it wants, for example it will write FAT table any time it needs to update it, that is it will write some one sector every time you update file.
    If it does updates in 512 byte sectors then, device that is hampered by 4096 erase sectors size, needs to erase that 4096, put back all the data and write it back with that new 512 byte sector replacing the one that has been on 4096 prior to erase. Without cache, consecutive writes to one page, like you are trying to write 8 * 512 byte sectors, would means 8 erases, because disk access does not really know when the sector was last erased. With chache, it does writes to cache first and does not erase next page untill all write operations leave cache

  • Thanks for your reply again. Please keep me updated if there is any progress for the issues with multi-image support between nRF and zephyr.

  • I will try to update the ticket here when I know more.

Related