<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="https://devzone.nordicsemi.com/cfs-file/__key/system/syndication/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>LittleFS config creating un-used partition in flash_primary</title><link>https://devzone.nordicsemi.com/f/nordic-q-a/103708/littlefs-config-creating-un-used-partition-in-flash_primary</link><description>I am using LittleFS for an external NAND flash by using the KCONFIG option CONFIG_FILE_SYSTEM_LITTLEFS = y and managing the driver implementation manually. This has worked well for me, but I have found that this config option seems to also create an un</description><dc:language>en-US</dc:language><generator>Telligent Community 13</generator><lastBuildDate>Mon, 01 Jul 2024 16:33:26 GMT</lastBuildDate><atom:link rel="self" type="application/rss+xml" href="https://devzone.nordicsemi.com/f/nordic-q-a/103708/littlefs-config-creating-un-used-partition-in-flash_primary" /><item><title>RE: LittleFS config creating un-used partition in flash_primary</title><link>https://devzone.nordicsemi.com/thread/491659?ContentTypeID=1</link><pubDate>Mon, 01 Jul 2024 16:33:26 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:afe3d93d-b5b5-440d-b946-531a3511d8c9</guid><dc:creator>Brett_G</dc:creator><description>&lt;p&gt;No problem. It is worth mentioning that&amp;nbsp; there are a lot of open issues with&amp;nbsp;how littlefs interacts with NAND. It really is not designed for it, and there are a lot of speed and size inefficiencies, that can only partially be worked around.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: LittleFS config creating un-used partition in flash_primary</title><link>https://devzone.nordicsemi.com/thread/491654?ContentTypeID=1</link><pubDate>Mon, 01 Jul 2024 15:54:16 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:0dd56de9-d8af-4d17-99b0-050e4300e389</guid><dc:creator>Furkan Aslan</dc:creator><description>&lt;p&gt;Hi Brett,&lt;/p&gt;
&lt;p&gt;Thank you for your response and for sharing the guide. Your assistance is greatly appreciated!&lt;/p&gt;
&lt;p&gt;Best regards,&lt;br /&gt;Furkan&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: LittleFS config creating un-used partition in flash_primary</title><link>https://devzone.nordicsemi.com/thread/491652?ContentTypeID=1</link><pubDate>Mon, 01 Jul 2024 15:41:16 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:3aa8e6a2-13c3-4e80-a305-f110f7be9a2a</guid><dc:creator>Brett_G</dc:creator><description>&lt;p&gt;Always willing to help.&lt;/p&gt;
&lt;p&gt;A lot of it hinges on you having a driver for your NAND flash that you have validated has working read, write, and erase commands, as well as bad block detection and mapping.&lt;/p&gt;
&lt;p&gt;I wont be able to help with that driver, but I can share a stripped down version of my littlefs wrapper c file here: &lt;pre class="ui-code" data-mode="c_cpp"&gt;#include &amp;lt;zephyr/kernel.h&amp;gt;
#include &amp;lt;zephyr/sys/printk.h&amp;gt;
#include &amp;lt;zephyr/fs/littlefs.h&amp;gt;
#include &amp;lt;string.h&amp;gt;

#include &amp;quot;drivers/nand_flash.h&amp;quot;

// Private Functions
int read_littlefs_wrapper(const struct lfs_config *c, lfs_block_t block, lfs_off_t off, void *buffer, lfs_size_t size){

    int err = 0;

    uint16_t page_numb = off/(nand_metrics.page_size - nand_metrics.spare_size);
    uint16_t column_numb = off%(nand_metrics.page_size - nand_metrics.spare_size);

    if (nand_flash_is_current_block_bad(block)) return LFS_ERR_CORRUPT;

    err = nand_read_data(block, page_numb, column_numb, buffer, size, true, true);

    if (err == NRFX_SUCCESS) err = 0;
    else err = LFS_ERR_IO;
    return err;
}

int write_littlefs_wrapper(const struct lfs_config *c, lfs_block_t block,
            lfs_off_t off, const void *buffer, lfs_size_t size){

    int err = 0;
    uint16_t page_numb = off/(nand_metrics.page_size - nand_metrics.spare_size);
    uint16_t column_numb = off%(nand_metrics.page_size - nand_metrics.spare_size);

    if (nand_flash_is_current_block_bad(block)) return LFS_ERR_CORRUPT;

    err = nand_write_data(block, page_numb, column_numb, (uint8_t*) buffer, size);
    //printk(&amp;quot;LFS Write B:%d P:%d C:%d S:%d, err = %d\n&amp;quot;, block, page_numb, column_numb, size, err);

    if (err == NRFX_SUCCESS) err = 0;
    else err = LFS_ERR_IO;
    return err;
}

int erase_littlefs_wrapper(const struct lfs_config *cfg, lfs_block_t block){

    if (nand_flash_is_current_block_bad(block)) return LFS_ERR_CORRUPT;

    nand_erase_block( block);
    return 0;
}

int sync_littlefs_wrapper(const struct lfs_config *cfg){
    //printk(&amp;quot;LFS Sync\n&amp;quot;);
    return 0;
}

struct lfs_config cfg = {
    // block device operations
    .read                   = read_littlefs_wrapper,
    .prog                   = write_littlefs_wrapper,
    .erase                  = erase_littlefs_wrapper,
    .sync                   = sync_littlefs_wrapper,
    .file_max               = LFS_FILE_MAX,
    .attr_max               = LFS_ATTR_MAX,
    .name_max               = LFS_NAME_MAX,
    .metadata_max           = 0,
};

bool fs_bad_blocks(void)
{
    lfs_file_t bad_blocks_file;
    nand_bbt_t* bad_blocks;
    bool success = true;

    // check if bad blocks are already mapped
    if(nand_flash_get_bad_blocks(&amp;amp;bad_blocks))
    {
        // if so, then just load them into flash
        lfs_file_open(&amp;amp;lfs, &amp;amp;bad_blocks_file, &amp;quot;bad_blocks&amp;quot;, LFS_O_WRONLY | LFS_O_CREAT);
        lfs_file_write(&amp;amp;lfs, &amp;amp;bad_blocks_file, bad_blocks, sizeof(nand_bbt_t));
        lfs_file_close(&amp;amp;lfs, &amp;amp;bad_blocks_file);
    }
    else
    {
        // otherwise check if a bad blocks file already exists
        if (lfs_file_open(&amp;amp;lfs, &amp;amp;bad_blocks_file, &amp;quot;bad_blocks&amp;quot;, LFS_O_RDONLY) == LFS_ERR_OK)
        {
            // if so, load it into RAM
            lfs_file_read(&amp;amp;lfs, &amp;amp;bad_blocks_file, bad_blocks, sizeof(nand_bbt_t));
            lfs_file_close(&amp;amp;lfs, &amp;amp;bad_blocks_file);
            nand_flash_set_bad_blocks(bad_blocks);
        }
        else
        {
            // otherwise, manually scan SPI flash and save the file to flash
            nand_flash_bad_block_detect();
            if (lfs_file_open(&amp;amp;lfs, &amp;amp;bad_blocks_file, &amp;quot;bad_blocks&amp;quot;, LFS_O_WRONLY | LFS_O_CREAT) == LFS_ERR_OK)
            {
                lfs_file_write(&amp;amp;lfs, &amp;amp;bad_blocks_file, bad_blocks, sizeof(nand_bbt_t));
                lfs_file_close(&amp;amp;lfs, &amp;amp;bad_blocks_file);
            }
            else success = false;
        }
    }
    return success;
}

void fs_test_boot_count(void)
{
    // read current count
    uint32_t boot_count = 0;
    lfs_file_t boot_count_file;

    if (lfs_file_open(&amp;amp;lfs, &amp;amp;boot_count_file, &amp;quot;boot_count&amp;quot;, LFS_O_RDWR | LFS_O_CREAT) == LFS_ERR_OK)
    {

        lfs_file_read(&amp;amp;lfs, &amp;amp;boot_count_file, &amp;amp;boot_count, sizeof(boot_count));

        // update boot count
        boot_count += 1;
        lfs_file_rewind(&amp;amp;lfs, &amp;amp;boot_count_file);
        lfs_file_write(&amp;amp;lfs, &amp;amp;boot_count_file, &amp;amp;boot_count, sizeof(boot_count));

        // remember the storage is not updated until the file is closed successfully
        lfs_file_close(&amp;amp;lfs, &amp;amp;boot_count_file);
    }

    // print the boot count
    printk(&amp;quot;boot_count: %d\n&amp;quot;, boot_count);
}


// Public Functions
void fs_init(bool reformat)
{

    // init the spi flash
    if (nand_flash_init() != NRFX_SUCCESS)
    {
        printk(&amp;quot;Error: Unable to start the file system.\n&amp;quot;);
        return;
    }

    // set up the config file metrics
    cfg.read_size              = 64;
    cfg.prog_size              = 64;
    cfg.block_size             = (nand_metrics.page_size - nand_metrics.spare_size)*nand_metrics.page_per_block;
    cfg.block_count            = nand_metrics.num_blocks;
    cfg.block_cycles           = 500;
    cfg.cache_size             = (nand_metrics.page_size - nand_metrics.spare_size);
    cfg.lookahead_size         = 256;

    // check if we need to reformat
    if (reformat) 
    {
        nand_flash_bad_block_detect();
        lfs_format(&amp;amp;lfs, (const struct lfs_config *) &amp;amp;cfg);
    }
    
    // mount the filesystem
    int err = lfs_mount(&amp;amp;lfs, (const struct lfs_config *) &amp;amp;cfg);

    // reformat if we can&amp;#39;t mount the filesystem
    // this should only happen on the first boot
    if (err) {
        // check for bad blocks manually
        nand_flash_bad_block_detect();

        // then format the drive and re-mount
        lfs_format(&amp;amp;lfs, (const struct lfs_config *) &amp;amp;cfg);
        err = lfs_mount(&amp;amp;lfs, (const struct lfs_config *) &amp;amp;cfg);
        if (err) return;

    }

    // initialize the bad blocks tracker
    if (fs_bad_blocks() == false)
    {
        // then format the drive and re-mount
        lfs_format(&amp;amp;lfs, (const struct lfs_config *) &amp;amp;cfg);
        err = lfs_mount(&amp;amp;lfs, (const struct lfs_config *) &amp;amp;cfg);
        if (err) return;
    }
    
    // perform simple test with boot count
    fs_test_boot_count();
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;The main thing to focus on is the read, write and erase wrappers.&amp;nbsp;I just have them checking for any bad blocks, converting&amp;nbsp;the offset addressing of littlefs to pages and columns, and then handing it off to my NAND flash driver to perform the actual operation. Also make sure to return the proper LFS_ERR codes.&lt;/p&gt;
&lt;p&gt;In the example above, my NAND flash driver provides the block, and page size info required to configure littlefs. Formats and mounts the filesystem. Generates or loads a mapping of bad blocks, and updates a boot_count value within the filesystem.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: LittleFS config creating un-used partition in flash_primary</title><link>https://devzone.nordicsemi.com/thread/491394?ContentTypeID=1</link><pubDate>Fri, 28 Jun 2024 14:48:45 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:b10e0ede-d479-4a32-a02f-e981609a337e</guid><dc:creator>Furkan Aslan</dc:creator><description>&lt;p&gt;Hi Brett,&lt;/p&gt;
&lt;p&gt;We are also started to implement little fs on external NAND memory. We we able to comminicate basic spi functions. Can you share a guide to implementation with little fs? You mention you are &lt;span&gt;managing the driver implementation manually and how it is connected to little fs.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Best Regards,&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Furkan&lt;/span&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: LittleFS config creating un-used partition in flash_primary</title><link>https://devzone.nordicsemi.com/thread/446118?ContentTypeID=1</link><pubDate>Thu, 14 Sep 2023 16:11:10 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:6b9dc6f4-3a3a-49b4-a22b-d8fc1c41b779</guid><dc:creator>&amp;#216;ivind</dc:creator><description>&lt;p&gt;Ok, you can try one of both of these configs:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="text"&gt;CONFIG_PM_PARTITION_REGION_LITTLEFS_EXTERNAL=y
CONFIG_PM_PARTITION_SIZE_LITTLEFS=0&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Reducing its size to zero may cause issues with code that uses &amp;quot;storage&amp;quot; or &amp;quot;storage_partition&amp;quot; as defined in flash_map_pm.h instead of &amp;quot;settings_storage&amp;quot; or &amp;quot;nvs_storage&amp;quot;, unless you also have a &amp;quot;settings_storage&amp;quot; partition.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: LittleFS config creating un-used partition in flash_primary</title><link>https://devzone.nordicsemi.com/thread/446107?ContentTypeID=1</link><pubDate>Thu, 14 Sep 2023 14:56:34 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:3a2dcc69-23ed-4a2a-a4e6-60498467e1f2</guid><dc:creator>Brett_G</dc:creator><description>&lt;p&gt;Here is the relevant section of my prj.conf:&lt;br /&gt;&lt;pre class="ui-code" data-mode="text"&gt;# file system
CONFIG_FLASH=y
CONFIG_FLASH_MAP=y
CONFIG_FLASH_PAGE_LAYOUT=y
CONFIG_FILE_SYSTEM=y
CONFIG_FILE_SYSTEM_LITTLEFS=y
CONFIG_FS_LITTLEFS_BLK_DEV=y
CONFIG_DISK_ACCESS=y
CONFIG_DISK_DRIVER_SDMMC=n
CONFIG_FILE_SYSTEM_MKFS=y&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Adding those config options didn&amp;#39;t cause any errors and as expected the settings_storage partition showed up along side the littlefs partition:&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img style="max-height:101px;max-width:646px;" alt=" " height="101" src="https://devzone.nordicsemi.com/resized-image/__size/1292x202/__key/communityserver-discussions-components-files/4/0763.Capture2.PNG" width="646" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;I don&amp;#39;t have any doubts that I&amp;#39;ll be able to use nvs along side littlefs, I just don&amp;#39;t understand why littlefs, when used on external flash, needs to create a partition on internal flash_primary.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: LittleFS config creating un-used partition in flash_primary</title><link>https://devzone.nordicsemi.com/thread/446086?ContentTypeID=1</link><pubDate>Thu, 14 Sep 2023 13:52:32 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:95166d72-708c-4f13-b10f-d59cb8391348</guid><dc:creator>&amp;#216;ivind</dc:creator><description>&lt;p&gt;Hi,&lt;/p&gt;
&lt;p&gt;Could I see the prj.conf of the application? And do you get any errors if you add the following configs?&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="text"&gt;CONFIG_NVS=y
CONFIG_SETTINGS=y
CONFIG_SETTINGS_NVS=y
&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;If that builds, please check the partition.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item></channel></rss>