Im having trouble setting up and using flash on nRF5340dk.
Is there any example on how to use LittleFS on external flash that is on the dev kit?
Im having trouble setting up and using flash on nRF5340dk.
Is there any example on how to use LittleFS on external flash that is on the dev kit?
my code for testing the flash storage is:
/* Matches LFS_NAME_MAX */
#define MAX_PATH_LEN 255
#define PARTITION_NODE DT_NODELABEL(lfs1)
#if DT_NODE_EXISTS(PARTITION_NODE)
FS_FSTAB_DECLARE_ENTRY(PARTITION_NODE);
#else /* PARTITION_NODE */
FS_LITTLEFS_DECLARE_DEFAULT_CONFIG(storage);
static struct fs_mount_t lfs_storage_mnt = {
.type = FS_LITTLEFS,
.fs_data = &storage,
.storage_dev = (void *)FLASH_AREA_ID(storage),
.mnt_point = "/lfs",
};
#endif /* PARTITION_NODE */
void testLittleFS(void)
{
struct fs_mount_t *mp =
#if DT_NODE_EXISTS(PARTITION_NODE)
&FS_FSTAB_ENTRY(PARTITION_NODE)
#else
&lfs_storage_mnt
#endif
;
unsigned int id = (uintptr_t)mp->storage_dev;
char fname[MAX_PATH_LEN];
const struct flash_area *pfa;
int rc;
snprintf(fname, sizeof(fname), "%s/boot_count", mp->mnt_point);
rc = open_flash_area(id, &pfa);
if (rc < 0)
{
return;
}
if (IS_ENABLED(CONFIG_APP_WIPE_STORAGE))
{
rc = erase_flash_area(pfa);
}
flash_area_close(pfa);
#if !DT_NODE_EXISTS(PARTITION_NODE) || (FSTAB_ENTRY_DT_MOUNT_FLAGS(PARTITION_NODE) & !FS_MOUNT_FLAG_AUTOMOUNT)
rc = mount_fs(mp);
if (rc < 0)
{
return;
}
#endif
reformat_and_mount_lfs(mp);
struct fs_statvfs sbuf;
rc = get_fs_stats(mp->mnt_point, &sbuf);
rc = read_update_write_boot_count(mp, fname);
rc = list_directory_contents(mp);
rc = unmount_fs(mp);
}
int open_flash_area(unsigned int id, const struct flash_area **pfa)
{
int rc = flash_area_open(id, pfa);
if (rc < 0)
{
printk("FAIL: unable to find flash area %u: %d\n", id, rc);
}
else
{
printk("Area %u at 0x%x on %u for %u bytes\n", id, (unsigned int)(*pfa)->fa_off, (*pfa)->fa_id, (unsigned int)(*pfa)->fa_size);
}
return rc;
}
int erase_flash_area(const struct flash_area *pfa)
{
printk("Erasing flash area ... ");
int rc = flash_area_erase(pfa, 0, pfa->fa_size);
printk("%d\n", rc);
return rc;
}
int mount_fs(struct fs_mount_t *mp)
{
int rc = fs_mount(mp);
if (rc < 0)
{
printk("FAIL: mount id %" PRIuPTR " at %s: %d\n", (uintptr_t)mp->storage_dev, mp->mnt_point, rc);
}
else
{
printk("%s mount: %d\n", mp->mnt_point, rc);
}
return rc;
}
int get_fs_stats(const char *mnt_point, struct fs_statvfs *sbuf)
{
int rc = fs_statvfs(mnt_point, sbuf);
if (rc < 0)
{
printk("FAIL: statvfs: %d\n", rc);
}
else
{
printk("LittleFS statistics:\n");
printk(" - Total space: %lu bytes\n", (unsigned long)sbuf->f_blocks * sbuf->f_frsize);
printk(" - Free space: %lu bytes\n", (unsigned long)sbuf->f_bfree * sbuf->f_frsize);
printk(" - Block size: %lu bytes\n", (unsigned long)sbuf->f_frsize);
}
return rc;
}
int read_update_write_boot_count(struct fs_mount_t *mp, const char *fname)
{
struct fs_dirent dirent;
int rc = fs_stat(fname, &dirent);
printk("%s stat: %d\n", fname, rc);
if (rc >= 0)
{
printk("\tfn '%s' size %zu\n", dirent.name, dirent.size);
}
struct fs_file_t file;
fs_file_t_init(&file);
rc = fs_open(&file, fname, FS_O_CREATE | FS_O_RDWR);
if (rc < 0)
{
printk("FAIL: open %s: %d\n", fname, rc);
return rc;
}
uint32_t boot_count = 0;
rc = fs_read(&file, &boot_count, sizeof(boot_count));
printk("%s read count %u: %d\n", fname, boot_count, rc);
rc = fs_seek(&file, 0, FS_SEEK_SET);
printk("%s seek start: %d\n", fname, rc);
boot_count += 1;
rc = fs_write(&file, &boot_count, sizeof(boot_count));
printk("%s write new boot count %u: %d\n", fname, boot_count, rc);
rc = fs_close(&file);
printk("%s close: %d\n", fname, rc);
return rc;
}
int list_directory_contents(struct fs_mount_t *mp)
{
struct fs_dir_t dir;
fs_dir_t_init(&dir);
int rc = fs_opendir(&dir, mp->mnt_point);
printk("%s opendir: %d\n", mp->mnt_point, rc);
while (rc >= 0)
{
struct fs_dirent ent = {0};
rc = fs_readdir(&dir, &ent);
if (rc < 0)
{
break;
}
if (ent.name[0] == 0)
{
printk("End of files\n");
break;
}
printk(" %c %zu %s\n",
(ent.type == FS_DIR_ENTRY_FILE) ? 'F' : 'D',
ent.size,
ent.name);
}
(void)fs_closedir(&dir);
return rc;
}
int unmount_fs(struct fs_mount_t *mp)
{
int rc = fs_unmount(mp);
printk("%s unmount: %d\n", mp->mnt_point, rc);
return rc;
}
static int write_test_file(const char *filename)
{
struct fs_file_t file;
int res = fs_open(&file, filename, FS_O_CREATE | FS_O_WRITE);
if (res < 0)
{
printk("Failed to open file for writing: %d\n", res);
return res;
}
#define FILE_SIZE 512
uint8_t buffer[512];
size_t remaining = FILE_SIZE;
while (remaining > 0)
{
size_t to_write = MIN(remaining, sizeof(buffer));
ssize_t written = fs_write(&file, buffer, to_write);
if (written < 0)
{
printk("Failed to write to file: %d\n", (int)written);
fs_close(&file);
return (int)written;
}
remaining -= written;
}
fs_close(&file);
return 0;
}
void erase_partition(const struct flash_area *fa)
{
flash_area_erase(fa, fa->fa_off, fa->fa_size);
}
int reformat_littlefs(struct fs_mount_t *mp)
{
printk("REFORMATING");
struct fs_littlefs *fs = mp->fs_data;
const struct lfs_config *lfs_cfg = &fs->cfg; // Access the 'cfg' member directly
int rc = lfs_format(&fs->lfs, lfs_cfg);
return rc;
}
void reformat_and_mount_lfs(struct fs_mount_t *mp)
{
// Unmount the filesystem
fs_unmount(mp);
// Erase the partition
const struct flash_area *fa;
flash_area_open(FLASH_AREA_ID(storage), &fa);
erase_partition(fa);
flash_area_close(fa);
// Reformat the filesystem using the updated configuration
reformat_littlefs(mp);
// Remount the filesystem
fs_mount(mp);
}
with overlay:
Hi,
Here is the example https://github.com/nrfconnect/sdk-zephyr/tree/main/samples/subsys/fs/littlefs.
Please duplicate this https://github.com/nrfconnect/sdk-zephyr/blob/main/samples/subsys/fs/littlefs/boards/nrf52840dk_nrf52840_qspi.conf config file and rename it to nrf5340dk_nrf5340_cpuapp.conf.
Duplicate https://github.com/nrfconnect/sdk-zephyr/blob/main/samples/subsys/fs/littlefs/boards/nrf52840dk_nrf52840_qspi.overlay overlay file, rename it to nrf5340dk_nrf5340_cpuapp.overlay and update with the following content:
/* * Copyright (c) 2019 Peter Bigot Consulting, LLC * * SPDX-License-Identifier: Apache-2.0 */ /delete-node/ &storage_partition; / { chosen { nordic,pm-ext-flash = &mx25r64; }; fstab { compatible = "zephyr,fstab"; lfs1: lfs1 { compatible = "zephyr,fstab,littlefs"; mount-point = "/lfs1"; partition = <&lfs1_part>; automount; read-size = <16>; prog-size = <16>; cache-size = <64>; lookahead-size = <32>; block-cycles = <512>; }; }; }; &mx25r64 { partitions { compatible = "fixed-partitions"; #address-cells = <1>; #size-cells = <1>; lfs1_part: partition@0 { label = "storage"; reg = <0x00000000 0x00010000>; }; }; };
Then, you could get the output like this
Regards,
Amanda H.
Thank you, It's working. I can now see all 8mb of flash. But there is an issue.
When running the littlefs example I get
Area 0 at 0x0 on mx25r6435f@0 for 8388608 bytes - Which is correct
but when I transfer that code, exact code, to my app I get
Area 2 at 0xfa000 on flash-controller@39000 for 24576 bytes
Ive been going over whats different but cant find it, Maybe Im missing something?
I also tried moving my code to littlefs example and everything was going fine until I added
It switched to flash flash-controller@39000, after commenting it out it stayed with flash and I cant get it to go back to mx25??
Ok, an Update. As soon as I add