How to "relocate" settings_storage when designing a pm_static.yml file?

Hi, I have two firmware images: A and B which I need to make compatible for OTA (DFU over BLE using MCUBoot - the standard process described in the devacademy course). They're both using the same (custom) private key and currently, I am trying to make sure they both share a common pm_static.yml file. From going through some discussions here I've understood that the common practice is to freeze the dynamically generated partitions.yml file into a pm_static.yml when done. But this will not work for me because A and B produce different partitions.yml

Below I have provided their dynamically generated partitions (TLDR: A's app sizes are larger by 0x1000 BUT has a settings_storage entry that does not).

A's partitions.yml:

app:
  address: 0xc200
  end_address: 0x46000
  region: flash_primary
  size: 0x39e00
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: 0x46000
  orig_span: &id001
  - app
  - mcuboot_pad
  region: flash_primary
  sharers: 0x1
  size: 0x3a000
  span: *id001
mcuboot_primary_app:
  address: 0xc200
  end_address: 0x46000
  orig_span: &id002
  - app
  region: flash_primary
  size: 0x39e00
  span: *id002
mcuboot_secondary:
  address: 0x46000
  end_address: 0x80000
  placement:
    after:
    - mcuboot_primary
    align:
      start: 0x1000
    align_next: 0x1000
  region: flash_primary
  share_size:
  - mcuboot_primary
  size: 0x3a000
sram_primary:
  address: 0x20000000
  end_address: 0x20010000
  region: sram_primary
  size: 0x10000

B's partitions.yml:

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

My goal is to create a single pm_static.yml that both the builds of A and B can use. My approach: take A's app sizes (since they are larger and would accommodate B) and relocate settings_storage by an appropriate amount 0x2000 and making sure there are no gaps:

app:
  address: 0xc200
  end_address: 0x46000
  region: flash_primary
  size: 0x39e00
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: 0x46000
  orig_span: &id001
  - app
  - mcuboot_pad
  region: flash_primary
  sharers: 0x1
  size: 0x3a000
  span: *id001
mcuboot_primary_app:
  address: 0xc200
  end_address: 0x46000
  orig_span: &id002
  - app
  region: flash_primary
  size: 0x39e00
  span: *id002
mcuboot_secondary:
  address: 0x46000
  end_address: 0x80000
  placement:
    after:
    - mcuboot_primary
    align:
      start: 0x1000
    align_next: 0x1000
  region: flash_primary
  share_size:
  - mcuboot_primary
  size: 0x3a000
settings_storage:
  address: 0x80000
  end_address: 0x82000
  placement:
    align:
      start: 0x1000
    before:
    - end
  region: flash_primary
  size: 0x2000
sram_primary:
  address: 0x20000000
  end_address: 0x20010000
  region: sram_primary
  size: 0x10000

As you can see: the app sizes are made to match that of A and settings_storage is relocated from (0x7e000 - 0x80000) to (0x80000 - 0x82000). When trying to build, both compile just fine. But B fails to run with the error:

bt_settings: settings_subsys_init failed (err -33)

and the bt module fails to load completely (i do not see any advertising).

My question is: is it possible to change the start and end addresses for the storage_settings like I am attempting to do? Any suggestions are welcome.

Parents
  • Addresses above 0x80000 do not exist on an NRF52832 as it has 512KB flash maximum. You may need external flash for OTA.

  • Hi, unfortunately our board right now doesn't have an external flash. Given time constraints, I think my best option is to combine firmwares for A and B which I can hopefully get done quickly. I might look into reworking this later.

  • Hi,

    What Turbo J states is true. For any 512kB device you will struggle to add dual bank FOTA support due to the requirement of having a two application slots. But it will depend on your application size.

    To put some numbers on this with an example. Consider this scenario where you only have an uppdatable app, but not an uppdatable bootloader. Using typical values for the partition sizes: You have a MCUBoot bootloader of 48kB, and a settings partition for your BLE settings for 8kB. Maybe you also have a storage partition at around 20kB as well. Then your application must be less than the following equation:

    Total flash >= mcuboot + 2x application application size  + settings + storage  -> application size = 1/2 (total flash - mcuboot - settings - storage)

    1. For the nRF52832 with total flash 512kB this results in application size <= 1/2 (512 - 48 - 8 - 20) = 218 kB
    2. For the nRF52840 with total flash 1024kB this results in application size <= 1/2 (1024 - 48 - 8 - 20) = 474 kB

    In addition NCSDK-20567: Partitioning limitation with MCUboot swap move mentioned in https://docs.nordicsemi.com/bundle/ncs-latest/page/nrf/releases_and_maturity/known_issues.html#bootloader 

    "The size of the application must be less than 'mcuboot_primary_size - 80 - (mcuboot_primary_size/ 4096) * 12 -4096'" meaning that if your mcuboot primary size is equal to 474kB, the application size must be ~95% of that size.

    If your application, bootloaders and every other partition requires is well within the estimate above w.r.t flash, then you don't need an external flash. If it's close to or above 218kB for the 52832 or 474kB for the 52840, you need an external flash. In practice, an application with BLE will be too big to fit within 218kB, but it will all depend on what your application is. The peripheral lbs sample with minimal configuration results in a 161kB application, so there are some cases where it will fit for small, simple applications.

    In addition, if I understand you correct, changing the partition map without having an updatable bootloader won't work. MCUboot only knows the partition map it was flashed with initially, and to change it you will require to update MCUboot. If firmware A in the field does not have an uppdatable bootloader then there's no way to get it to recognize the new firmware

    However if this is not in the field, then I recommend you to base pm_static for board A on board B and change the location where the settings_storage is present to be a "reserved" partition where you currently have nothing on board A.

    Kind regards,
    Andreas

Reply
  • Hi,

    What Turbo J states is true. For any 512kB device you will struggle to add dual bank FOTA support due to the requirement of having a two application slots. But it will depend on your application size.

    To put some numbers on this with an example. Consider this scenario where you only have an uppdatable app, but not an uppdatable bootloader. Using typical values for the partition sizes: You have a MCUBoot bootloader of 48kB, and a settings partition for your BLE settings for 8kB. Maybe you also have a storage partition at around 20kB as well. Then your application must be less than the following equation:

    Total flash >= mcuboot + 2x application application size  + settings + storage  -> application size = 1/2 (total flash - mcuboot - settings - storage)

    1. For the nRF52832 with total flash 512kB this results in application size <= 1/2 (512 - 48 - 8 - 20) = 218 kB
    2. For the nRF52840 with total flash 1024kB this results in application size <= 1/2 (1024 - 48 - 8 - 20) = 474 kB

    In addition NCSDK-20567: Partitioning limitation with MCUboot swap move mentioned in https://docs.nordicsemi.com/bundle/ncs-latest/page/nrf/releases_and_maturity/known_issues.html#bootloader 

    "The size of the application must be less than 'mcuboot_primary_size - 80 - (mcuboot_primary_size/ 4096) * 12 -4096'" meaning that if your mcuboot primary size is equal to 474kB, the application size must be ~95% of that size.

    If your application, bootloaders and every other partition requires is well within the estimate above w.r.t flash, then you don't need an external flash. If it's close to or above 218kB for the 52832 or 474kB for the 52840, you need an external flash. In practice, an application with BLE will be too big to fit within 218kB, but it will all depend on what your application is. The peripheral lbs sample with minimal configuration results in a 161kB application, so there are some cases where it will fit for small, simple applications.

    In addition, if I understand you correct, changing the partition map without having an updatable bootloader won't work. MCUboot only knows the partition map it was flashed with initially, and to change it you will require to update MCUboot. If firmware A in the field does not have an uppdatable bootloader then there's no way to get it to recognize the new firmware

    However if this is not in the field, then I recommend you to base pm_static for board A on board B and change the location where the settings_storage is present to be a "reserved" partition where you currently have nothing on board A.

    Kind regards,
    Andreas

Children
No Data
Related