Zephyr MSC example fails with 'PM_storage_partition_ID' undeclared on nRF52840DK

I'm trying to add MSC functionality to my project, but I'm encountering the following error:

error: 'PM_storage_partition_ID' undeclared (first use in this function)

To understand the cause of the error, I tried creating a new application from the Zephyr MSC example using the 52840DK board. However, without making any changes to the code or configurations, I still get the same error.

In the example, the only modification I made was adding the following line to prj.conf:

CONFIG_APP_MSC_STORAGE_FLASH_FATFS=y

What am I missing?

prj.conf

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_MAIN_STACK_SIZE=1536
CONFIG_APP_MSC_STORAGE_FLASH_FATFS=y

main.c

/*
 * Copyright (c) 2016 Intel Corporation.
 * Copyright (c) 2019-2020 Nordic Semiconductor ASA
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <sample_usbd.h>

#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>

LOG_MODULE_REGISTER(main);

#if CONFIG_DISK_DRIVER_FLASH
#include <zephyr/storage/flash_map.h>
#endif

#if CONFIG_FAT_FILESYSTEM_ELM
#include <ff.h>
#endif

#if CONFIG_FILE_SYSTEM_LITTLEFS
#include <zephyr/fs/littlefs.h>
FS_LITTLEFS_DECLARE_DEFAULT_CONFIG(storage);
#endif

#if !defined(CONFIG_DISK_DRIVER_FLASH) && \
	!defined(CONFIG_DISK_DRIVER_RAM) && \
	!defined(CONFIG_DISK_DRIVER_SDMMC)
#error No supported disk driver enabled
#endif

#define STORAGE_PARTITION		storage_partition
#define STORAGE_PARTITION_ID		FIXED_PARTITION_ID(STORAGE_PARTITION)

static struct fs_mount_t fs_mnt;

#if defined(CONFIG_USB_DEVICE_STACK_NEXT)
static struct usbd_context *sample_usbd;

#if CONFIG_DISK_DRIVER_RAM
USBD_DEFINE_MSC_LUN(ram, "RAM", "Zephyr", "RAMDisk", "0.00");
#endif

#if CONFIG_DISK_DRIVER_FLASH
USBD_DEFINE_MSC_LUN(nand, "NAND", "Zephyr", "FlashDisk", "0.00");
#endif

#if CONFIG_DISK_DRIVER_SDMMC
USBD_DEFINE_MSC_LUN(sd, "SD", "Zephyr", "SD", "0.00");
#endif

static int enable_usb_device_next(void)
{
	int err;

	sample_usbd = sample_usbd_init_device(NULL);
	if (sample_usbd == NULL) {
		LOG_ERR("Failed to initialize USB device");
		return -ENODEV;
	}

	err = usbd_enable(sample_usbd);
	if (err) {
		LOG_ERR("Failed to enable device support");
		return err;
	}

	LOG_DBG("USB device support enabled");

	return 0;
}
#endif /* defined(CONFIG_USB_DEVICE_STACK_NEXT) */

static int setup_flash(struct fs_mount_t *mnt)
{
	int rc = 0;
#if CONFIG_DISK_DRIVER_FLASH
	unsigned int id;
	const struct flash_area *pfa;

	mnt->storage_dev = (void *)STORAGE_PARTITION_ID;
	id = STORAGE_PARTITION_ID;

	rc = flash_area_open(id, &pfa);
	printk("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);

	if (rc < 0 && IS_ENABLED(CONFIG_APP_WIPE_STORAGE)) {
		printk("Erasing flash area ... ");
		rc = flash_area_flatten(pfa, 0, pfa->fa_size);
		printk("%d\n", rc);
	}

	if (rc < 0) {
		flash_area_close(pfa);
	}
#endif
	return rc;
}

static int mount_app_fs(struct fs_mount_t *mnt)
{
	int rc;

#if CONFIG_FAT_FILESYSTEM_ELM
	static FATFS fat_fs;

	mnt->type = FS_FATFS;
	mnt->fs_data = &fat_fs;
	if (IS_ENABLED(CONFIG_DISK_DRIVER_RAM)) {
		mnt->mnt_point = "/RAM:";
	} else if (IS_ENABLED(CONFIG_DISK_DRIVER_SDMMC)) {
		mnt->mnt_point = "/SD:";
	} else {
		mnt->mnt_point = "/NAND:";
	}

#elif CONFIG_FILE_SYSTEM_LITTLEFS
	mnt->type = FS_LITTLEFS;
	mnt->mnt_point = "/lfs";
	mnt->fs_data = &storage;
#endif
	rc = fs_mount(mnt);

	return rc;
}

static void setup_disk(void)
{
	struct fs_mount_t *mp = &fs_mnt;
	struct fs_dir_t dir;
	struct fs_statvfs sbuf;
	int rc;

	fs_dir_t_init(&dir);

	if (IS_ENABLED(CONFIG_DISK_DRIVER_FLASH)) {
		rc = setup_flash(mp);
		if (rc < 0) {
			LOG_ERR("Failed to setup flash area");
			return;
		}
	}

	if (!IS_ENABLED(CONFIG_FILE_SYSTEM_LITTLEFS) &&
	    !IS_ENABLED(CONFIG_FAT_FILESYSTEM_ELM)) {
		LOG_INF("No file system selected");
		return;
	}

	rc = mount_app_fs(mp);
	if (rc < 0) {
		LOG_ERR("Failed to mount filesystem");
		return;
	}

	/* Allow log messages to flush to avoid interleaved output */
	k_sleep(K_MSEC(50));

	printk("Mount %s: %d\n", fs_mnt.mnt_point, rc);

	rc = fs_statvfs(mp->mnt_point, &sbuf);
	if (rc < 0) {
		printk("FAIL: statvfs: %d\n", rc);
		return;
	}

	printk("%s: bsize = %lu ; frsize = %lu ;"
	       " blocks = %lu ; bfree = %lu\n",
	       mp->mnt_point,
	       sbuf.f_bsize, sbuf.f_frsize,
	       sbuf.f_blocks, sbuf.f_bfree);

	rc = fs_opendir(&dir, mp->mnt_point);
	printk("%s opendir: %d\n", mp->mnt_point, rc);

	if (rc < 0) {
		LOG_ERR("Failed to open directory");
	}

	while (rc >= 0) {
		struct fs_dirent ent = { 0 };

		rc = fs_readdir(&dir, &ent);
		if (rc < 0) {
			LOG_ERR("Failed to read directory entries");
			break;
		}
		if (ent.name[0] == 0) {
			printk("End of files\n");
			break;
		}
		printk("  %c %u %s\n",
		       (ent.type == FS_DIR_ENTRY_FILE) ? 'F' : 'D',
		       ent.size,
		       ent.name);
	}

	(void)fs_closedir(&dir);

	return;
}

int main(void)
{
	int ret;

	setup_disk();

#if defined(CONFIG_USB_DEVICE_STACK_NEXT)
	ret = enable_usb_device_next();
#else
	ret = usb_enable(NULL);
#endif
	if (ret != 0) {
		LOG_ERR("Failed to enable USB");
		return 0;
	}

	LOG_INF("The device is put in USB mass storage mode.\n");
	return 0;
}

overlay

/*
 * Copyright (c) 2019 Peter Bigot Consulting, LLC
 *
 * SPDX-License-Identifier: Apache-2.0
 */

/delete-node/ &storage_partition;

&mx25r64 {
	partitions {
		compatible = "fixed-partitions";
		#address-cells = <1>;
		#size-cells = <1>;

		storage_partition: partition@0 {
			label = "storage";
			reg = <0x00000000 0x00020000>;
		};
	};
};

/ {
	msc_disk0 {
		compatible = "zephyr,flash-disk";
		partition = <&storage_partition>;
		disk-name = "NAND";
		cache-size = <4096>;
	};
};

Parents
  • Hi,

    How did you build the sample? The sample only works without sysbuild (so either check the "No sysbuild" radio button at the bottom when making a build configuration in VS Code, or use --no-sysbuild if building with west direclty from the command line.

    Also, you need to specify the storage as explained in the sample documentation.

    Here is an example configuration from VS Code:

  • Hi,

    Regarding specifying the storage, I believe what I have already set with

    CONFIG_APP_MSC_STORAGE_FLASH_FATFS=y

    should be sufficient.

    As for compiling without sysbuild (since it is not mentioned on the example page), this indeed solves the compilation issue. However, I would like to ask: how can I use MSC with sysbuild, considering that it is expected to be the default in the future?

    I also have a curiosity: why does the code use the term NAND when the external flashes supported by Zephyr are NOR (I asked about it in the past)?

  • Hi,

    Sysbuild is used by default for nrf samples, but this sample is part of vanilla Zephyr, and there sysbild is not yet supported by default. (Nordic contributes extensively to vanilla Zephyr (including this specific sample), but the Zephyr samples are not officially supported in the same way as the samples under the nrf repository is.)

    Regarding the term "NAND", I agree that is odd and misleading, as the internal flash is "NOR" (at the same time newer devices use other technologies than flash enteirly, so that could also become misleading at some point). This has been used for a long time in this sample though, and I am not able to find out why. 

  • Sysbuild is used by default for nrf samples, but this sample is part of vanilla Zephyr, and there sysbild is not yet supported by default. (Nordic contributes extensively to vanilla Zephyr (including this specific sample), but the Zephyr samples are not officially supported in the same way as the samples under the nrf repository is.)

    So, if I wanted to implement MSC using sysbuild, where can I find an example, tutorial, or reference guide?

    Regarding the term "NAND", I agree that is odd and misleading, as the internal flash is "NOR" (at the same time newer devices use other technologies than flash enteirly, so that could also become misleading at some point). This has been used for a long time in this sample though, and I am not able to find out why. 

    Okay, I got it.

Reply
  • Sysbuild is used by default for nrf samples, but this sample is part of vanilla Zephyr, and there sysbild is not yet supported by default. (Nordic contributes extensively to vanilla Zephyr (including this specific sample), but the Zephyr samples are not officially supported in the same way as the samples under the nrf repository is.)

    So, if I wanted to implement MSC using sysbuild, where can I find an example, tutorial, or reference guide?

    Regarding the term "NAND", I agree that is odd and misleading, as the internal flash is "NOR" (at the same time newer devices use other technologies than flash enteirly, so that could also become misleading at some point). This has been used for a long time in this sample though, and I am not able to find out why. 

    Okay, I got it.

Children
  • Hi,

    I am not aware of any sample or specific intructions on this. That said, it seems the main issue is that the MSC sample does not work with the partition manager, and when building with sysbuild that is included. I suggest you make a file called sysbuild.conf in the same folder as prj.conf, and add this line to the new file:

    SB_CONFIG_PARTITION_MANAGER=n

    This will disable the partition manager for the build

  • This will disable the partition manager for the build

    I have disabled the Partition Manager, and now I can compile the example and get it running. However, I have noticed that when I connect the board to the PC via USB, the visible memory is still 108KB, even though I modified the storage_partition in the overlay to 8MB (which is the external memory size of the 52840DK) 

    &mx25r64 {
    	partitions {
    		compatible = "fixed-partitions";
    		#address-cells = <1>;
    		#size-cells = <1>;
    
    		storage_partition: partition@0 {
    			label = "storage";
    			reg = <0x00000000 0x00800000>;
    		};
    	};
    };

    while the application outputs the correct values to me

    [00:00:00.374,664] <inf> flashdisk: Initialize device NAND
    [00:00:00.374,664] <inf> flashdisk: offset 0, sector size 512, page size 4096, volume size 8388608
    Area 0 at 0x0 on mx25r6435f@0 for 8388608 bytes
    Mount /NAND:: 0
    /NAND:: bsize = 512 ; frsize = 512 ; blocks = 216 ; bfree = 213
    /NAND: opendir: 0
      D 0 SYSTEM~1
    End of files
    [00:00:00.430,664] <inf> main: The device is put in USB mass storage mode.

    1) Why the PC see only 108KB?
    2) If I have an application that necessarily uses sysbuild and the Partition Manager, and I want to implement USB MSC, how can I make them coexist? Do you have any advice?

  • Hi,

    I get this working with sysbuild if I disable the partition manager (that is the way things are moving anyway), and then the size from the device tree overlay file is also used. The partition manager is removed by making a file sysbuild.conf that contains this line:

    SB_CONFIG_PARTITION_MANAGER=n

    With that, and your increase in the parition size in the overlay, things work as expected on my end:

Related