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