nRF52832 NVS pagesize change

Hello everyone! This is my first post on the forum and it is about the NVS pagesize.

A bit of context, I am developing an application that has the following parts: LoRaWAN stack, BLE GATT services, Power Management, UART, I2C and NVS.

To this I need to add DFU through BLE using SMP and MCUboot.

All this using VSCode with NCS 2.1.0 and Zephyr 3.1.99.

The thing is that the nRF52832 has 512Kb of flash and it is a bit tight in flash space to reach 2 image-slots, the MCUboot and a Storage partition. So I used a "pm_static.yml" to change a bit the sizes of each part like the following:

app:
  address: 0xc200
  end_address: 0x45000
  region: flash_primary
  size: 0x38e00
mcuboot:
  address: 0x0
  end_address: 0xc000
  placement:
    before:
    - mcuboot_primary
  region: flash_primary
  size: 0xc000
mcuboot_pad:
  address: 0xc000
  end_address: 0xc200
  placement:
    align:
      start: 0x1000
    before:
    - mcuboot_primary_app
  region: flash_primary
  size: 0x200
mcuboot_primary:
  address: 0xc000
  end_address: 0x45000
  orig_span: &id001
  - app
  - mcuboot_pad
  region: flash_primary
  sharers: 0x1
  size: 0x39000
  span: *id001
mcuboot_primary_app:
  address: 0xc200
  end_address: 0x45000
  orig_span: &id002
  - app
  region: flash_primary
  size: 0x38e00
  span: *id002
mcuboot_secondary:
  address: 0x45000
  end_address: 0x7e000
  placement:
    after:
    - mcuboot_primary
    align:
      start: 0x1000
  region: flash_primary
  share_size:
  - mcuboot_primary
  size: 0x39000
nvs_storage:
  address: 0x7e000
  end_address: 0x80000
  placement:
    align:
      start: 0x1000
    before:
    - end
  region: flash_primary
  size: 0x2000
sram_primary:
  address: 0x20000000
  end_address: 0x20010000
  region: sram_primary
  size: 0x10000

The original (default by the partition manager) storage partition size is 0x6000 (24Kb), wich is a lot more than my application really needs.

So I tried to lower this partition size to 0x1000 (4Kb) and give 10Kb to each image-slot (or mcuboot_primary and mcuboot_secondary, as this is their name). In doing so I started to see an error in the initialization of the NVS like this: 

invalid address 0x00080ff8:8

This means that the NVS is trying to enter somewhere outside of the flash space. This is because the pagesize has a size of 4Kb wich is equal to the sector_size, and the problem is that the NVS sector_count has to be minimum 2.

Investigating in the documentation I have found the following: NVS Documentation
Where it explicitly says: "the pagesize is determined by the hardware".

So, where does all of this collide....

When initializing the NVS it makes a comparison between the sector_size and the pagesize:

    /* check that sector size is a multiple of pagesize */
	rc = flash_get_page_info_by_offs(fs->flash_device, fs->offset, &info);
	if (rc) {
		LOG_ERR("Unable to get page info");
		return -EINVAL;
	}
	if (!fs->sector_size || fs->sector_size % info.size) {
		LOG_ERR("Invalid sector size");
		return -EINVAL;
	}

If the pagesize is always 4Kb (definde "by hardware") and cannot be changed, sector_size needs to be equal to pagesize and sector_count needs to be minimum of 2 so the storage partition is as small as possible leaving more room for the application images.

As I showed in the first code snippet of the "pm_static.yml" at the moment the storage partition has a size of 8Kb and the application images have a size of 228Kb. And this is what the compiler drops as error:

c:/ncs/toolchains/v2.1.0/opt/zephyr-sdk/arm-zephyr-eabi/bin/../lib/gcc/arm-zephyr-eabi/10.3.0/../../../../arm-zephyr-eabi/bin/ld.exe: region `FLASH' overflowed by 796 bytes

So finally my question is this:

Is there a way to reduce the "pagesize" to something like 1Kb? which is a lot for what my application actually uses from the NVS.

Or maybe I'm approaching this from the wrong angle?
Any comments are welcome!!

  • Hi,

    The page size is indeed 4Kb and you can not change this.

    Using pm_static.yml is a good idea, as it is wise to have a constant size of partitions in all versions of your project, when doing DFU later on.

    But as an alternative now, you can try to use CONFIG_PM_PARTITION_SIZE_LITTLEFS to set the storage partiton size.
    Then if that works you can get inspiration from  build/partitions.yml to generate your pm_static.yml.
    EDIT: Use CONFIG_PM_PARTITION_SIZE_NVS_STORAGE to change NVS instead of trying to change LITTLEFS oops.

    And this is what the compiler drops as error:

    Can you see from the build log if this FLASH overflow error is from the application or from the MCUboot child image?

    Sometimes the easier solution is not to increase flash size, but rather optimalize flash size of the application/child_image.
    See Optimizing application and CONFIG_SIZE_OPTIMIZATIONS.

    For optimizing MCUboot, you can use the machine learining sample as an example.
    You configure MCUboot in a child_image/mcuboot.conf file.

    Regards,
    Sigurd Hellesvik

  • Thank you  I will look into it.

    Can you see from the build log if this FLASH overflow error is from the application or from the MCUboot child image?

    The overflow I believe is from the app side, this is the fragment of the build log that shows what I believe is the MCUboot image:

    I don't know why I can't put this in code, but anyway... this:


    [260/265] Generating linker.cmd
    [261/265] Generating isr_tables.c, isrList.bin
    [262/265] Building C object zephyr/CMakeFiles/zephyr_final.dir/misc/empty_file.c.obj
    [263/265] Building C object zephyr/CMakeFiles/zephyr_final.dir/dev_handles.c.obj
    [264/265] Building C object zephyr/CMakeFiles/zephyr_final.dir/isr_tables.c.obj
    [265/265] Linking C executable zephyr\zephyr.elf
    Memory region Used Size     Region Size       %age Used
    FLASH:             28860 B        48 KB                 58.72%
    SRAM:              22400 B        64 KB                 34.18%
    IDT_LIST:         0 GB               2 KB                   0.00%


    [261/282] Linking C executable zephyr\zephyr_pre0.elf
    FAILED: zephyr/zephyr_pre0.elf zephyr/zephyr_pre0.map
    cmd.exe /C "cd . && C:\ncs\toolchains\v2.1.0\opt\zephyr-sdk\arm-zephyr-eabi\bin\arm-zephyr-eabi-gcc.exe @CMakeFiles\zephyr_pre0.rsp -o zephyr\zephyr_pre0.elf && cmd.exe /C "cd /D C:\Users\ig\Documents\Repos\NFL2\build\zephyr && C:\ncs\toolchains\v2.1.0\opt\bin\cmake.exe -E echo ""
    c:/ncs/toolchains/v2.1.0/opt/zephyr-sdk/arm-zephyr-eabi/bin/../lib/gcc/arm-zephyr-eabi/10.3.0/../../../../arm-zephyr-eabi/bin/ld.exe: zephyr\zephyr_pre0.elf section `k_mem_slab_area' will not fit in region `FLASH'

    Hope you can read this 

  • Hi,

    Since the memory regions for MCUboot are printed (I know from the size), we know that MCUboot built fine.

    Pepe Sanches said:
    FLASH:             28860 B        48 KB                 58.72%
    SRAM:              22400 B        64 KB                 34.18%
    IDT_LIST:         0 GB               2 KB                   0.00%

    As long as you do not have other child images active, it must be the application that overflows.

    EDIT: Also see the edit of my below post

    Regards,
    Sigurd Hellesvik

  • Hi  ,

    EDIT: Use CONFIG_PM_PARTITION_SIZE_NVS_STORAGE to change NVS instead of trying to change LITTLEFS oops.

    I tried this, I think it helped, but I'm still using the pm_static.yml.

    I tried to change also the MCUboot partition size, seeing that it has a lot to give.

    I lowered the size from 48Kb to 40Kb, this gave me a bit more room for the application images.

    I don't think this is a good way to achieve this, but for the moment this works.

    I will look further into optimizing as you told me in your first response.

    For the moment the topic of the thread kind of shifted, so I will mark this as resolved.

    Thank you for your help!!!

Related