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