Unable to mount fat FS using external partition manager using pm_static.yml file

Hi,

I am trying to mount Fat FS using pm_static.yml instead of devicetree overlay fixed partition. I can generate a memory report, but when I try to mount file system I get the following mount errors. 

Errors:

winbondw25q02@0 SPI flash testing
==========================

Perform test on single sector
Test 1: Flash erase
*** Booting nRF Connect SDK v2.7.0-5cb85570ca43 ***
*** Using Zephyr OS v3.6.99-100befc70c74 ***
[00:00:00.257,232] <err> usb_msc: Storage init ERROR !!!! - Aborting USB init
Flash erase succeeded!

Test 2: Flash write
Attempting to write zu bytes
Data read matches data written. Good!!
[00:00:00.380,065] <err> fs: fs mount error (-5)
Error mounting FATFS: -5. Formatting now...
[00:00:00.380,126] <err> fs: fs not mounted (mp == 0x200000d0)
Error unmounting FATFS: -22
Error formatting FATFS: 3
[00:00:00.380,218] <err> fs: fs mount error (-5)
Error mounting FATFS after formatting: -5
[00:00:00.380,249] <err> fs: mount point not found!!
[00:00:00.380,279] <err> flash_test: Failed to open file /NAND:/test.txt (err: -2)
[00:00:00.380,279] <err> fs: mount point not found!!
[00:00:00.380,310] <err> flash_test: Failed to open file /NAND:/test.txt (err: -2)
[00:00:00.380,401] <dbg> flash_test: enable_usb_device: USB mass storage enabled
[00:00:00.380,432] <inf> flash_test: USB mass storage enabled.

Prj.Conf

# Copyright (c) 2018 Nordic Semiconductor
#
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
#

# Enable the UART driver
CONFIG_UART_ASYNC_API=y
CONFIG_NRFX_UARTE0=y

# print
CONFIG_NEWLIB_LIBC=y
CONFIG_NEWLIB_LIBC_FLOAT_PRINTF=y

# I2C
CONFIG_I2C=y
CONFIG_I2C_NRFX=y
CONFIG_NRFX_TWIM1=y
CONFIG_NFCT_PINS_AS_GPIOS=y

#SPI
CONFIG_SPI=y
CONFIG_SPI_ASYNC=y
CONFIG_SPI_SLAVE=y

CONFIG_HEAP_MEM_POOL_SIZE=2048
# Enable DK LED and Buttons library
CONFIG_DK_LIBRARY=y
CONFIG_STDOUT_CONSOLE=y

#USB related configs
CONFIG_USB_DEVICE_STACK=y
CONFIG_USB_DEVICE_PRODUCT="Zephyr MSC sample"
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_DEVICE_INITIALIZE_AT_BOOT=n
CONFIG_APP_MSC_STORAGE_FLASH_FATFS=y
CONFIG_MAIN_STACK_SIZE=10240
CONFIG_FILE_SYSTEM=y
CONFIG_FILE_SYSTEM_LITTLEFS=n

CONFIG_SPI_NOR=y
CONFIG_FLASH_JESD216_API=y
CONFIG_SPI_NRFX=y
CONFIG_SPI_NOR_IDLE_IN_DPD=y

#FLASH Config ##############################################
CONFIG_DISK_ACCESS=y
CONFIG_FAT_FILESYSTEM_ELM=y
CONFIG_FS_FATFS_LFN=y

CONFIG_FLASH=y
CONFIG_FLASH_MAP=y
CONFIG_FLASH_LOG_LEVEL_ERR=y
CONFIG_MPU_ALLOW_FLASH_WRITE=y
CONFIG_DISK_DRIVER_FLASH=y
CONFIG_PM_OVERRIDE_EXTERNAL_DRIVER_CHECK=y

overlay file:

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

/* Disable conflicting buttons and UART */
&button2 {
	status = "disabled";
};

&button3 {
	status = "disabled";
};

&gpio_fwd {
	status = "disabled";
};

&pinctrl {
		spi_master_default: spi_master_default {
				group1 {
						psels = <NRF_PSEL(SPIM_SCK, 0, 2)>,
										<NRF_PSEL(SPIM_MOSI, 0, 9)>,
										<NRF_PSEL(SPIM_MISO, 0, 3)>;
				};
		};

		spi_master_sleep: spi_master_sleep {
				group1 {
						psels = <NRF_PSEL(SPIM_SCK, 0, 2)>,
										<NRF_PSEL(SPIM_MOSI, 0, 9)>,
										<NRF_PSEL(SPIM_MISO, 0, 3)>;
						low-power-enable;
				};
		};
};

&spi4 {
		compatible = "nordic,nrf-spim";
		pinctrl-0 = <&spi_master_default>;
		pinctrl-1 = <&spi_master_sleep>;
		pinctrl-names = "default", "sleep";
		cs-gpios = <&gpio0 11 GPIO_ACTIVE_LOW>;	
		status = "okay";
		winbond:winbondw25q02@0 {
			compatible = "jedec,spi-nor";
			reg = <0>;
			spi-max-frequency = <32000000>;
			jedec-id = [ ef 70 22 ];
			size = <268435456>;
			has-dpd;
		};
};

pm_static.yml and memory report

app:
  address: 0x00010200
  end_address: 0x00E4000
  region: flash_primary
  size: 0x00D3E00

external_flash:
  address: 0x00000000
  device: DT_CHOSEN(nordic_pm_ext_flash)
  end_address: 0x10000000  # 256MB
  region: external_flash
  size: 0x10000000

mcuboot:
  address: 0x00000000
  end_address: 0x00010000
  region: flash_primary
  size: 0x00010000

mcuboot_pad:
  address: 0x00010000
  end_address: 0x00010200
  region: flash_primary
  size: 0x00000200

mcuboot_primary:
  address: 0x00010000
  end_address: 0x00E4000
  orig_span: &id001
    - mcuboot_pad
    - app
  region: flash_primary
  size: 0x00D4000
  span: *id001

mcuboot_secondary:
  address: 0x00000000
  device: DT_CHOSEN(nordic_pm_ext_flash)
  end_address: 0x00D4000
  region: external_flash
  size: 0x00D4000

mcuboot_secondary_1:
  address: 0x00D4000
  device: DT_CHOSEN(nordic_pm_ext_flash)
  end_address: 0x0114000
  region: external_flash
  size: 0x0040000

EMPTY_1:
  address: 0x0114000
  device: DT_CHOSEN(nordic_pm_ext_flash)
  end_address: 0x0120000
  region: external_flash
  size: 0x000C000

mcuboot_primary_2:
  address: 0x0120000
  device: DT_CHOSEN(nordic_pm_ext_flash)
  end_address: 0x0160000
  region: external_flash
  size: 0x0040000

mcuboot_secondary_2:
  address: 0x0160000
  device: DT_CHOSEN(nordic_pm_ext_flash)
  end_address: 0x01A0000
  region: external_flash
  size: 0x0040000

storage_partition:
  address: 0x01A0000  # Start of FATFS storage partition after mcuboot_secondary_2
  device: DT_CHOSEN(nordic_pm_ext_flash)
  end_address: 0x10000000  # End of storage partition (remaining memory)
  region: external_flash
  size: 0x0FE50000  # Remaining memory for storage (260416KB or approx 254MB)
  type: storage

msc_disk0:
  address: 0x01A0000  # Place MSC Disk inside storage_partition
  device: DT_CHOSEN(nordic_pm_ext_flash)
  end_address: 0x01B0000  # 0x01A0000 + 0x10000 (64KB for disk with cache)
  region: storage_partition  
  type: cache
  cache_size: 0x10000  # 64KB cache size
  disk_name: "NAND"
 external_flash (0x10000000 - 262144kB):
+----------------------------------------------------+
| 0x0: external_flash (0x10000000 - 262144kB)        |
| 0x0: mcuboot_secondary (0xd4000 - 848kB)           |
| 0xd4000: mcuboot_secondary_1 (0x40000 - 256kB)     |
| 0x114000: EMPTY_1 (0xc000 - 48kB)                  |
| 0x120000: mcuboot_primary_2 (0x40000 - 256kB)      |
| 0x160000: mcuboot_secondary_2 (0x40000 - 256kB)    |
| 0x1a0000: storage_partition (0xfe50000 - 260416kB) |
+----------------------------------------------------+

  flash_primary (0x100000 - 1024kB):
+----------------------------------------------+
| 0x0: mcuboot (0x10000 - 64kB)                |
+---0x10000: mcuboot_primary (0xd4000 - 848kB)-+
| 0x10000: mcuboot_pad (0x200 - 512B)          |
| 0x10200: app (0xefe00 - 959kB)               |
+----------------------------------------------+

  otp (0x2fc - 764B):
+------------------------------+
| 0xff8100: otp (0x2fc - 764B) |
+------------------------------+

  sram_primary (0x80000 - 512kB):
+--------------------------------------------+
| 0x20000000: sram_primary (0x80000 - 512kB) |
+--------------------------------------------+

main.c

#include <sample_usbd.h>
#include <zephyr/kernel.h>
#include <zephyr/drivers/flash.h>
#include <zephyr/device.h>
#include <zephyr/devicetree.h>
#include <stdio.h>
#include <string.h>
#include <zephyr/fs/fs.h>
#include <zephyr/storage/disk_access.h>
#include <zephyr/logging/log.h>
#include <ff.h>  // FATFS definition
#include <zephyr/usb/usb_device.h>
#include <zephyr/usb/usbd.h>
#include <zephyr/usb/class/usbd_msc.h>

#define STORAGE_PARTITION		storage_partition
#define STORAGE_PARTITION_ID		DEVICE_DT_GET(DT_CHOSEN_nordic_pm_ext_flash)

LOG_MODULE_REGISTER(flash_test, LOG_LEVEL_DBG);

#if defined(CONFIG_BOARD_ADAFRUIT_FEATHER_STM32F405)
#define SPI_FLASH_TEST_REGION_OFFSET 0xf000
#else
#define SPI_FLASH_TEST_REGION_OFFSET 0xff000
#endif

#define SPI_FLASH_SECTOR_SIZE 4096
#define FATFS_MOUNT_POINT "/NAND:"
static FATFS fat_fs;

static struct fs_mount_t fatfs_mount = {
    .type = FS_FATFS,
    .fs_data = &fat_fs,
    .mnt_point = FATFS_MOUNT_POINT,
};

// Define a LUN for USB MSC (similar to your original code)
USBD_DEFINE_MSC_LUN(NAND, "Zephyr", "FlashDisk", "0.00");

// Declare the "erased" array
const uint8_t erased[] = { 0xff, 0xff, 0xff, 0xff };

// Function to enable USB device for mass storage
static int enable_usb_device(void)
{
    int err = usb_enable(NULL);  // Use standard Zephyr USB enable function
    if (err != 0) {
        LOG_ERR("Failed to enable USB device support: %d", err);
        return err;
    }
    LOG_DBG("USB mass storage enabled");
    return 0;
}

void format_fatfs(void)
{
    struct fs_mount_t *mp = &fatfs_mount;
    int res = fs_unmount(mp);  // Unmount before formatting
    if (res != 0) {
        printk("Error unmounting FATFS: %d\n", res);
    }

    MKFS_PARM fs_options = {
        .fmt = FM_FAT,  // FAT format
        .n_fat = 1,     // Number of FATs (1 or 2)
        .align = 0,     // Alignment (0 for default)
        .n_root = 0,    // Number of root directory entries (0 for default)
        .au_size = 0    // Allocation unit size (0 for default)
    };

    res = f_mkfs("", &fs_options, NULL, 0);  // Format the filesystem
    if (res == FR_OK) {
        printk("FATFS format successful.\n");
    } else {
        printk("Error formatting FATFS: %d\n", res);
    }
}

void mount_fatfs(void)
{
    int res = fs_mount(&fatfs_mount);
    if (res == 0) {
        printk("FATFS mounted successfully.\n");
    } else {
        printk("Error mounting FATFS: %d. Formatting now...\n", res);
        format_fatfs();  // Format the flash if mounting fails
        res = fs_mount(&fatfs_mount);  // Try to mount again after formatting
        if (res == 0) {
            printk("FATFS mounted successfully after formatting.\n");
        } else {
            printk("Error mounting FATFS after formatting: %d\n", res);
        }
    }
}

void create_write_file(const char *file_path)
{
    struct fs_file_t file;
    int res;

    fs_file_t_init(&file);
    res = fs_open(&file, file_path, FS_O_CREATE | FS_O_RDWR);
    if (res < 0) {
        LOG_ERR("Failed to open file %s (err: %d)", file_path, res);
        return;
    }

    const char *sample_data = "Hello FATFS on SPI Flash!";
    res = fs_write(&file, sample_data, strlen(sample_data));
    if (res < 0) {
        LOG_ERR("Failed to write to file %s (err: %d)", file_path, res);
        fs_close(&file);
        return;
    }

    fs_close(&file);
    printk("File write successful!\n");
}

void read_file(const char *file_path)
{
    struct fs_file_t file;
    int res;
    char buffer[64];

    fs_file_t_init(&file);
    res = fs_open(&file, file_path, FS_O_READ);
    if (res < 0) {
        LOG_ERR("Failed to open file %s (err: %d)", file_path, res);
        return;
    }

    printk("Reading file content:\n");
    while ((res = fs_read(&file, buffer, sizeof(buffer) - 1)) > 0) {
        buffer[res] = '\0';  // Null-terminate the read data
        printk("%s", buffer);  // Print to console
    }

    fs_close(&file);
}

void single_sector_test(const struct device *flash_dev)
{
    const uint8_t expected[] = {0x55, 0xaa, 0x66, 0x99};
    const size_t len = sizeof(expected);
    uint8_t buf[sizeof(expected)];
    int rc;

    printf("\nPerform test on single sector\n");
    printf("Test 1: Flash erase\n");

    rc = flash_erase(flash_dev, SPI_FLASH_TEST_REGION_OFFSET, SPI_FLASH_SECTOR_SIZE);
    if (rc != 0) {
        printf("Flash erase failed! %d\n", rc);
    } else {
        memset(buf, 0, len);
        rc = flash_read(flash_dev, SPI_FLASH_TEST_REGION_OFFSET, buf, len);
        if (rc != 0) {
            printf("Flash read failed! %d\n", rc);
            return;
        }
        if (memcmp(erased, buf, len) != 0) {
            printf("Flash erase failed at offset 0x%x got 0x%x\n",
                SPI_FLASH_TEST_REGION_OFFSET, *(uint32_t *)buf);
            return;
        }
        printf("Flash erase succeeded!\n");
    }

    printf("\nTest 2: Flash write\n");

    printf("Attempting to write %zu bytes\n", len);
    rc = flash_write(flash_dev, SPI_FLASH_TEST_REGION_OFFSET, expected, len);
    if (rc != 0) {
        printf("Flash write failed! %d\n", rc);
        return;
    }

    memset(buf, 0, len);
    rc = flash_read(flash_dev, SPI_FLASH_TEST_REGION_OFFSET, buf, len);
    if (rc != 0) {
        printf("Flash read failed! %d\n", rc);
        return;
    }

    if (memcmp(expected, buf, len) == 0) {
        printf("Data read matches data written. Good!!\n");
    } else {
        printf("Data read does not match data written!!\n");
    }
}

void winbond_begin(void)
{
    const struct device *flash_dev = DEVICE_DT_GET(DT_CHOSEN(nordic_pm_ext_flash));

    if (!device_is_ready(flash_dev)) {
        printk("%s: device not ready.\n", flash_dev->name);
        return;
    }

    printf("\n%s SPI flash testing\n", flash_dev->name);
    printf("==========================\n");

    // Perform a sector test to ensure flash is working
    single_sector_test(flash_dev);

    // Mount the FATFS file system or format if necessary
    mount_fatfs();

    // Perform file operations (create and read a file)
    const char *file_path = FATFS_MOUNT_POINT "/test.txt";
    create_write_file(file_path);
    read_file(file_path);

    // Enable USB for mass storage
    int usb_err = enable_usb_device();
    if (usb_err == 0) {
        LOG_INF("USB mass storage enabled.");
    } else {
        LOG_ERR("Failed to enable USB mass storage.");
    }
}

regards,

Barsha

  • Hi

    How are you powering the SD card/reader on your end. The VDD on the nRF5340 DK is too low for some SD cards, so you can try using a 3.3V external power source and see if that changes anything.

    Are you using any of the Filesystem samples available in Zephyr as a template here or have you developed this project yourself? https://docs.nordicsemi.com/bundle/ncs-latest/page/zephyr/samples/subsys/fs/fs.html File systems documentation can also be found here: https://docs.nordicsemi.com/bundle/ncs-latest/page/zephyr/services/file_system/index.html 

    If you're not able to get anywhere, try finding out what function in your project is returning this error 5 when running. Error message 5 points to an I/O error, so my first guess would be that the power source isn't suficient, if not it is likely due to how the SD card is connected to the nRF5340 or that the pins used for communicating aren't set up correctly.

    Best regards,

    Simon

  • Hi Simonr,

    When I try to build the same code without this pm_static.yml and add fixed partition part in the overlay file I can mount the Fat FS into my winbond NOR storage and even write into it:

    overlay file:

     / {
    	chosen {
    		nordic,pm-ext-flash = &winbond;
    	};
    };
    
    /* Disable conflicting buttons and UART */
    &button2 {
    	status = "disabled";
    };
    
    &button3 {
    	status = "disabled";
    };
    
    &gpio_fwd {
    	status = "disabled";
    };
    
    &pinctrl {
    		spi_master_default: spi_master_default {
    				group1 {
    						psels = <NRF_PSEL(SPIM_SCK, 0, 2)>,
    										<NRF_PSEL(SPIM_MOSI, 0, 9)>,
    										<NRF_PSEL(SPIM_MISO, 0, 3)>;
    				};
    		};
    
    		spi_master_sleep: spi_master_sleep {
    				group1 {
    						psels = <NRF_PSEL(SPIM_SCK, 0, 2)>,
    										<NRF_PSEL(SPIM_MOSI, 0, 9)>,
    										<NRF_PSEL(SPIM_MISO, 0, 3)>;
    						low-power-enable;
    				};
    		};
    };
    
    &spi4 {
    		compatible = "nordic,nrf-spim";
    		pinctrl-0 = <&spi_master_default>;
    		pinctrl-1 = <&spi_master_sleep>;
    		pinctrl-names = "default", "sleep";
    		cs-gpios = <&gpio0 11 GPIO_ACTIVE_LOW>;	
    		status = "okay";
    		winbond:winbondw25q02@0 {
    			compatible = "jedec,spi-nor";
    			reg = <0>;
    	//      irq-gpios = <&gpio0 21 0>;
    			spi-max-frequency = <32000000>;
    			//label = "WINBOND";
    			jedec-id = [ ef 70 22 ];
    			size = <0x10000000>;
    			has-dpd;
    			// sfdp-bfp = [
    		 	// 	e5 20 f1 ff  ff ff ff 03  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 cc  44 83 68 44
    		 	// 	30 b0 30 b0  f7 c4 d5 5c  00 be 29 ff  f0 d0 ff ff
    		 	// ];
    		};
    };
    
    /delete-node/ &storage_partition;
    
    &winbond {
    	partitions {
    		compatible = "fixed-partitions";
    		#address-cells = <1>;
    		#size-cells = <1>;
    
    		storage_partition: partition@0 {
    			label = "storage";
    			reg = <0x00000000 0x01000000>;
    		};
    	};
    };
    
    / {
    	msc_disk0 {
    		compatible = "zephyr,flash-disk";
    		partition = <&storage_partition>;
    		disk-name = "NAND";
    		cache-size = <65536>;
    	};
    };

    output terminal:

    winbondw25q02@0 SPI flash testing
    ==========================
    
    Perform test on single sector
    Test 1: Flash erase
    *** Booting nRF Connect SDK v2.7.0-5cb85570ca43 ***
    *** Using Zephyr OS v3.6.99-100befc70c74 ***
    Flash erase succeeded!
    
    Test 2: Flash write
    Attempting to write 4 bytes
    Data read matches data written. Good!!
    [00:00:00.378,845] <inf> flashdisk: Initialize device NAND
    [00:00:00.378,875] <inf> flashdisk: offset 0, sector size 512, page size 4096, volume size 16777216
    [00:00:00.386,016] <inf> flashdisk: Initialize device NAND
    [00:00:00.386,047] <inf> flashdisk: offset 0, sector size 512, page size 4096, volume size 16777216
    [00:00:01.456,390] <inf> flashdisk: Initialize device NAND
    [00:00:01.456,420] <inf> flashdisk: offset 0, sector size 512, page size 4096, volume size 16777216
    FATFS mounted successfully.
    File write successful!
    Reading file content:
    Hello FATFS on SPI Flash!
    


    But my application also requires bluetooth functionality, and when I add CONFIG_BT=y in project config, it says "partition manager enabled and all partitions of devicetree will now be ignored" and I get the following build error:


    C:/ncs/v2.7.0/zephyr/drivers/disk/flashdisk.c:484:1: error: return type defaults to 'int' [-Werror=implicit-int]
    484 | PM_FOREACH_AFFILIATED_TO_disk(DEFINE_FLASHDISKS_CACHE)
    | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~


    That is why I thought pm_static.yml would fix this problem, but its still the same. However, with CONFIG_BT=n I can at least build and generate the memory report but still cant mount.

  • Hi

    I see you're using pins P0.02 and P0.03 for SPI pins here. These are configured as NFC pins by default, and you need to configure these as GPIOs if you want to use them as such. Depending on the SDK version you're using, you need to set either CONFIG_NFCT_PINS_AS_GPIOS (for older than NCS v2.5.0), or you need to set it in the .dts file with

    &uicr { nfct-pins-as-gpios; };

    Best regards,

    Simon

  • I have already done that, you can see it on my prj.conf. The only issues I am having is with the partitions and mounting

  • I have a similar setup on a custom PCB using nrf5340 with external flash chip.

    See  RE: DFU using USB file system (not serial emulation)? 

    in that thread is my pm_static.yml - btw I define staticallly all the partitions on the internal and external flash to ensure that future builds don't move them, and break mcuboot DFU...

    For mounting the FAT FS, I use the ELM FAT subsystem also. I don't actually do a mkfs at all, but it works...

    My init code (you'll need to replace my log_X calls...also I decided to call my fatfs flash area a different name to ensure no interaction with any other random code zephyr/nrf decide to pull in...)

    #include <zephyr/kernel.h>
    #include <zephyr/logging/log.h>
    #include <zephyr/usb/usb_device.h>
    #include <zephyr/usb/usbd.h>
    #include <zephyr/usb/class/usbd_msc.h>
    #include <zephyr/fs/fs.h>
    #include <stdio.h>
    #include <stdlib.h>
    
    #include "util/wutils.h"
    
    #if CONFIG_DISK_DRIVER_FLASH
    #include <zephyr/storage/flash_map.h>
    #endif
    
    #if CONFIG_FAT_FILESYSTEM_ELM
    #include <ff.h>
    #endif
    
    #include "usb_fs.h"
    
    //#define STORAGE_PARTITION		storage_partition
    #define STORAGE_PARTITION		fatfs_storage
    #define STORAGE_PARTITION_ID		FIXED_PARTITION_ID(STORAGE_PARTITION)
    
    static struct fs_mount_t _fs_mnt;
    
    static int _erase_flash(unsigned int id) {
    	const struct flash_area *pfa;
    	int rc = -1;
    
    	rc = flash_area_open(id, &pfa);
    	if (rc<0) {
    		log_warn("Erasing flash area ... failed to open it (%d)",rc);
    		return rc;
    	}
    	log_warn("Opened flash area (%d) -> trying to erase it....",rc);
    	rc = flash_area_erase(pfa, 0, pfa->fa_size);
    	if (rc<0) {
    		log_warn("Erasing flash area ... failed! (%d)",rc);
    	} else {
    		log_warn("Erased flash area OK.");
    	}
    	flash_area_close(pfa);
    	return rc;
    }
    static int _setup_flash(unsigned int id, struct fs_mount_t *mnt)
    {
    	int rc = -1;
    #if CONFIG_DISK_DRIVER_FLASH
    	const struct flash_area *pfa;
    
    	mnt->storage_dev = (void *)id;
    	rc = flash_area_open(id, &pfa);
    	if (rc < 0) {
    		log_warn("Failed to open flash area (%d) -> trying to erase it....",rc);
    		rc = flash_area_erase(pfa, 0, pfa->fa_size);
    		if (rc<0) {
    			log_warn("Erasing flash area ... failed! (%d)",rc);
    			flash_area_close(pfa);
    			return rc;
    		} 
    		log_warn("Erased flash area OK.");
    		rc = flash_area_open(id, &pfa);
    		if (rc<0) {
    			log_warn("Erasing flash area ... didn't help, still can't open it! (%d)",rc);
    			flash_area_close(pfa);
    			return rc;
    		} 
    	}
    	log_info("Flash USB mass storage opened : area %u at 0x%x on %s for %u bytes\n",
    		id, (unsigned int)pfa->fa_off, pfa->fa_dev->name,
    		(unsigned int)pfa->fa_size);
    #endif
    	return pfa->fa_size;
    }
    
    static int _mount_app_fs(struct fs_mount_t *mnt, char* mnt_point)
    {
    	int rc;
    
    #if CONFIG_FAT_FILESYSTEM_ELM
    	static FATFS fat_fs;
    
    	mnt->type = FS_FATFS;
    	mnt->fs_data = &fat_fs;
    	mnt->mnt_point = mnt_point;
    #else
    	log_warn("no file system type defined in firmware build, no FS mount available.");
    	return -1;
    #endif
    	rc = fs_mount(mnt);
    
    	return rc;
    }
    
    static bool _setup_disk(struct fs_mount_t *mp, char* mnt_point) {
    	int rc;
    	int flash_partition_size = 0;
    	if (IS_ENABLED(CONFIG_DISK_DRIVER_FLASH)) {
    		// _erase_flash(STORAGE_PARTITION_ID);		// Only do this if created a FATFS on partition of wrong size initially...
    		flash_partition_size = _setup_flash(STORAGE_PARTITION_ID, mp);
    		if (flash_partition_size < 0) {
    			log_error("Failed to setup flash area");
    			return false;
    		}
    	} else {
    		log_error("No flash driver enabled");
    		return false;
    	}
    
    	if (!IS_ENABLED(CONFIG_FAT_FILESYSTEM_ELM)) {
    		log_error("No file system enabled");
    		return false;
    	}
    
    	rc = _mount_app_fs(mp, mnt_point);
    	if (rc < 0) {
    		log_error("Failed to mount filesystem on %s", mnt_point);
    		return false;
    	}
    	// If fatfs size is not the partition size, then we need to erase the partition and start again
    	struct fs_statvfs fvol;
    	rc = fs_statvfs(mnt_point, &fvol);
    	log_info("statvfs says block size %d, total blocks %d -> %u bytes volume size", fvol.f_blocks, fvol.f_frsize, fvol.f_blocks*fvol.f_frsize);
    	if (abs((fvol.f_blocks*fvol.f_frsize)-flash_partition_size)>100000) {		// approx
    		log_warn("File system size (%u) not equal to flash zone size (%u) -> wiping and reformatting", (fvol.f_blocks*fvol.f_frsize), flash_partition_size);
    		_erase_flash(STORAGE_PARTITION_ID);		// Only do this if created a FATFS on partition of wrong size initially...
    		// And redo?
    		// Need to close parition, unmountfs?
    		fs_unmount(mp);
    		flash_partition_size = _setup_flash(STORAGE_PARTITION_ID, mp);
    		rc = _mount_app_fs(mp, mnt_point);
    		if (rc < 0) {
    			log_error("Failed to mount filesystem on %s", mnt_point);
    			return false;
    		}
    	}
    	/* Allow log messages to flush to avoid interleaved output */
    	k_sleep(K_MSEC(50));
    
    	return true;
    }
    
    And then call during init phase:
    	if (_setup_disk(&_fs_mnt, "/NAND:")) {
    		log_info("USB mass storage mode enabled.\n");
    	} else {
        	log_warn("USB mass storage mode FS failed!");
        }

    Hopefully this will help you... it took me a while to get to this point...

Related