Maximising littlefs flash storage space

I'm working on a project that uses BLE, NVS storage (for some serial number data and a few other variables) and littlefs, for storing log data that a client can then access over bluetooth via SMP.  I'm on nRF Connect v2.0.0 and am using an nRF52832.

But I'm coming into some problems with making maximum use of the available NVS storage for my information.  At the moment, this is how my static partitions are defined:

settings_storage:
  address: 0x7a000
  size: 0x2000
  placement:
    before: 
    - user_storage
  region: flash_primary
user_storage:
  address: 0x7c000
  size: 0x2000
  placement:
    before:
    - littlefs_storage
  region: flash_primary
littlefs_storage:
  address: 0x7e000
  size: 0x2000
  placement:
    before: 
    - end
  region: flash_primary

Ideally, I want to maximise the amount of littlefs storage, and reduce the settings and user storage to an absolute minimum.  But the user_storage needs at least 2 sectors, each of 4kB (a page) in size, even if I only need to store 200 bytes of info.  Similarly, it seems the settings area needs a similar amount as a minimum, because the moment I try and reduce that, my BLE functionality stops working.  This is only leaving me 8kB of littlefs storage.

Reading this, it seems its possible to combine the settings and user storage areas into one, which potentially would free up 8kB.  But I don't believe this has been implemented in v2.0.0, so I may need to upgrade to a newer SDK (I think its available in v2.1.2).  Question I have though is how do I actually implement this in my code?  I've just followed the nvs example to set up my user storage in my code, so it looks something like this:

static struct nvs_fs fs;

int16_t flash_initialise(void)
{
    int16_t rc;

	fs.flash_device = FLASH_AREA_DEVICE(STORAGE_NODE_LABEL);
	if (!device_is_ready(fs.flash_device)) {
			printk("Flash device %s is not ready\n", fs.flash_device->name);
		return -EINVAL;
	}

	fs.offset = FLASH_AREA_OFFSET(user_storage);
	rc = flash_get_page_info_by_offs(fs.flash_device, fs.offset, &info);
	if (rc !=0) 
	{
			printk("Unable to get page info\n");
		return rc = -EINVAL;
	}

	fs.sector_size = info.size;
	fs.sector_count = NVS_SECTOR_COUNT;

	if(fs.sector_size*fs.sector_count > (FLASH_AREA_SIZE(user_storage)))
	{
		printk("ERROR: Area used by NVS is larger than user storage\n");
	}

	rc = nvs_mount(&fs);
	if (rc !=0) 
	{
		printk("Flash Init failed\n");
		return rc;
	}
}

Note that STORAGE_NODE_LABEL = settings_storage.

Alternatively, this seems to be indicating its possible to combine nvs and littlefs partitions into one.  It doesn't really elaborate on how to do this though.  Is this an easier option than trying to combine settings and user storage?

Are there any other approaches I can use to reduce the amount of flash taken up by the settings and user storage, and hence maximise the amount of littlefs storage space I have?

Cheers,

Mike

  • Hi Mike, 
    As far as I can see it's OK to have the warning as the input for settings_storage_get() expecting type void ** and we will assign it to the  nvs_fs * in the function so it's fine. The function doesn't know which backend will be used so they use void. 
    Have you tried with my example ? you can copy it to peripheral_uart project. 

  • Hi Hung,

    I've been testing your example in the peripheral_uart_project.  I can get it to work if I don't try and define a static partition (which is what I do want to do in my code eventually)

    The moment I define a static partition as follows:

    settings_storage:
      address: 0x7a000
      size: 0x6000
      placement:
        before: 
        - end
      region: flash_primary

    Then the code will crash with a return error of -45.  Stepping through things with the debugger, it looks like it comes unstuck when it makes a call to nvs_startup() in nvs.c

    At the point where it goes through and checks if sectors are open or closed in an attempt to find open sectors where it can begin writing:

    	/* all sectors are closed, this is not a nvs fs */
    	if (closed_sectors == fs->sector_count) {
    		rc = -EDEADLK;
    		goto end;
    	}

    Then it discovers closed_sectors=8 and so sets rc=-EDEADCLK and so the call to bt_enable(NULL) in main.c fails.

    Not sure why all the sectors are showing as closed, or what to do to fix the issue.

    Any ideas?

    Regards,

    Mike

  • Hi Mike, 
    Which board are you testing with ? 
    I added CONFIG_PM_SINGLE_IMAGE=y in prj.conf and then added pm_static.yml as follows and it worked fine for me. I haven't added littlefs partition though. 

    app:
      address: 0x0
      end_address: 0x7a000
      region: flash_primary
      size: 0x7a000
    settings_storage:
      address: 0x7a000
      end_address: 0x80000
      placement:
        before:
        - end
      region: flash_primary
      size: 0x6000
    sram_primary:
      address: 0x20000000
      end_address: 0x20010000
      region: sram_primary
      size: 0x10000

  • Hi Hung,

    I'm using the nRF52-DK at this stage, but will ultimately port this across to my custom board that uses an nRF52832 chip.

    With the mods you described above, I'm still seeing the same issue as before (returns -45 on checking for closed sectors).

     I've tried erasing the board and then reflashing it to see if this fixes the problem, but there is no change.

    I've also tried programming onto another DK, but I'm seeing the same behaviour.

    Cheers,

    Mike

  • Hi Mike, 

    Do you see the same problem with my example as well ? (after the change I suggested)


    If you don't could you try to simplify your application to compare to my example and see what caused the error ? 
    You can send us the simplified version of your application so we can test here. 

Related