Issue with using SPI flash for holding second boot slot

Hi all,

I have an issue with putting my second boot slot on an external SPI flash. There are more people on the Q&A with issues in this realm, but none that I found were both similar enough and about a somewhat recent NCS release.

Zephyr & MCUboot versions I am using are those checked out by west update when having checked out NCS with version tag 2.7.0, being revision 5cb85570ca43bc344d3145c2338128eacf4b48ec. My target platform is a custom PCB with a nRF9160 (second revision) on it, and an 8 megs mx25r64 flash connected using SPI.

I name what hardware I use for painting a picture, even though my present understanding is this not actually being relevant to my problem, as my problem exists in software and doesn't even get to a stage where hardware might be at fault: To me, most likely my problem is in files related to the build system (bugs or otherwise), code being generated or configuration errors on my part.

Be aware the build is done using the new Sysbuild mechanism.

I defined a pm_static.yml, which looks like this:

mcuboot:
  address: 0x0
  region: flash_primary
  size: 0x10000

mcuboot_pad:
  address: 0x10000
  placement:
    before: mcuboot_primary_app
  region: flash_primary
  size: 0x200

mcuboot_primary:
  address: 0x10000
  placement:
    before: end
    after: mcuboot
  orig_span: &id001
  - mcuboot_pad
  - app
  - tfm
  region: flash_primary
  sharers: 0x1
  size: 0xf0000
  span: *id001

mcuboot_secondary:
  share_size: mcuboot_primary
  address: 0x0
  size: 0xf0000
  region: external_flash

The above gives the following for ninja partition_manager_report:

ninja: Entering directory `build'
[1/1] cd /home/merethan/src/Dent/zaphod/build/_sysbuild && /home/merethan/src/Dent/zaphod/ven...ripts/partition_manager_report.py --input /home/merethan/src/Dent/zaphod/build/partitions.yml
  external_flash (0x800000 - 8192kB): 
+---------------------------------------------+
| 0x0: mcuboot_secondary (0xf0000 - 960kB)    |
| 0xf0000: external_flash (0x710000 - 7232kB) |
+---------------------------------------------+

  flash_primary (0x100000 - 1024kB): 
+--------------------------------------------------+
| 0x0: mcuboot (0x10000 - 64kB)                    |
+---0x10000: mcuboot_primary (0xf0000 - 960kB)-----+
| 0x10000: mcuboot_pad (0x200 - 512B)              |
+---0x10200: mcuboot_primary_app (0xc7e00 - 799kB)-+
+---0x10200: tfm_secure (0x7e00 - 31kB)------------+
| 0x10200: tfm (0x7e00 - 31kB)                     |
+---0x18000: tfm_nonsecure (0xc0000 - 768kB)-------+
| 0x18000: app (0xc0000 - 768kB)                   |
+--------------------------------------------------+
| 0xd8000: mcuboot_scratch (0x1e000 - 120kB)       |
| 0xf6000: EMPTY_1 (0x2000 - 8kB)                  |
+---0xf8000: nonsecure_storage (0x2000 - 8kB)------+
| 0xf8000: settings_storage (0x2000 - 8kB)         |
+--------------------------------------------------+
| 0xfa000: EMPTY_0 (0x6000 - 24kB)                 |
+--------------------------------------------------+

  otp (0x2f4 - 756B): 
+------------------------------+
| 0xff8108: otp (0x2f4 - 756B) |
+------------------------------+

  sram_primary (0x40000 - 256kB): 
+--------------------------------------------------+
+---0x20000000: mcuboot_sram (0x8000 - 32kB)-------+
+---0x20000000: sram_secure (0x8000 - 32kB)--------+
| 0x20000000: tfm_sram (0x8000 - 32kB)             |
+---0x20008000: sram_nonsecure (0x38000 - 224kB)---+
+---0x20008000: nrf_modem_lib_sram (0x4568 - 17kB)-+
| 0x20008000: nrf_modem_lib_ctrl (0x4e8 - 1kB)     |
| 0x200084e8: nrf_modem_lib_tx (0x2080 - 8kB)      |
| 0x2000a568: nrf_modem_lib_rx (0x2000 - 8kB)      |
+--------------------------------------------------+
| 0x2000c568: sram_primary (0x33a98 - 206kB)       |
+--------------------------------------------------+

As seen in the report, mcuboot_secondary is placed on the external flash chip, and the external flash chip is selected as follows:

chosen {
	zephyr,flash-controller = &flash_controller;
	zephyr,flash = &flash0;
	zephyr,code-partition = &slot0_ns_partition;
	nordic,pm-ext-flash = &mx25r64;
};

This external flash chip works when I use it from the Zephyr shell: I can save & retrieve data over SPI from/to this chip using the serial shell. This detail is not that important however to my understanding, as stuff goes wrong before hardware has a chance to throw things off.

Both MCUboot & application code crash on trying to read the flash, when accessing it as the mcuboot_secondary partition. Both use flash_area_open() of flash_map.c to get a pointer to a flash_area struct, and for both appcode and MCUboot this fails on get_flash_area_from_id() in flash_area_open().

For now lets stick to MCUboot:

        /* Open primary and secondary image areas for the duration
         * of this call.
         */
        for (slot = 0; slot < BOOT_NUM_SLOTS; slot++) {
            fa_id = flash_area_id_from_multi_image_slot(image_index, slot);
            rc = flash_area_open(fa_id, &BOOT_IMG_AREA(state, slot));
            assert(rc == 0);

            if (rc != 0) {
                BOOT_LOG_ERR("Failed to open flash area ID %d (image %d slot %d): %d, "
                             "cannot continue", fa_id, image_index, (int8_t)slot, rc);
                FIH_PANIC;
            }
        }

The above is a snippet from loader.c, starting line 2409.

In loader.c (see snippet), the call to flash_area_id_from_multi_image_slot() in context_boot_go() seems to get a valid partition ID for both boot slots (in my case ID 3 for mcuboot_primary, and ID 1 for mcuboot_secondary; last of which is on my external flash).

Following getting this ID, it is used with flash_area_open() to get a pointer to a struct describing it:

int flash_area_open(uint8_t id, const struct flash_area **fap)
{
	const struct flash_area *area;

	if (flash_map == NULL) {
		return -EACCES;
	}

	area = get_flash_area_from_id(id);
	if (area == NULL) {
		return -ENOENT;
	}

	if (!area->fa_dev || !device_is_ready(area->fa_dev)) {
		return -ENODEV;
	}

	*fap = area;

	return 0;
}

The above is a snippet from flash_map.c, starting line 29.

But then calling flash_area_open() fails. What this function does is cycling over the (in my case) 13 entries in the array extern const struct flash_area *flash_map using get_flash_area_from_id() in flash_map_priv.h, but doing this yields no result for ID 1.

extern const struct flash_area *flash_map;
extern const int flash_map_entries;

static inline struct flash_area const *get_flash_area_from_id(int idx)
{
	for (int i = 0; i < flash_map_entries; i++) {
		if (flash_map[i].fa_id == idx) {
			return &flash_map[i];
		}
	}

	return NULL;
}

The above is a snippet from flash_map_priv.h, around start of the file.

ID 3 however (mcuboot_primary, which is in the nRF flash) is found fine. It only breaks the second invocation when searching for mcuboot_secondary (ID 1), because there's no instance with flash_area.fa_id == 1 in the array of instances.

The above then makes flash_area_open() of flash_map.c fail for mcuboot_secondary (external flash) with return -ENOENT;, which in turn breaks context_boot_go() of loader.c

Program received signal SIGTRAP, Trace/breakpoint trap.
context_boot_go (state=state@entry=0x200038b4 <boot_data>, rsp=rsp@entry=0x20005364 <z_main_stack+1964>)
    at /home/merethan/src/Dent/zaphod/ncs/bootloader/mcuboot/boot/bootutil/src/loader.c:2420
2420	                FIH_PANIC;


And then, there's no bueno: Failed to open flash area ID 1 (image 0 slot 1).

How come flash_area_id_from_multi_image_slot() can come up with a partition ID for the second boot slot, but then there not being a flash_area struct for it in memory?

I'm somewhat stuck as figuring this out goes into a bunch of generated code, CMake scripts, likely some more Python stuff which writes up the partition_manager_report among other things, not to mention sysbuild which obscures everything even more. What I'm hoping for is this problem being (somewhat) obvious to someone, or at least more obvious than the problem is to me.

In the mean time I'll continue debugging & searching. But if someone has hints I'd very much appreciate it.

Grtz!

-Maarten "merethan"

Parents Reply Children
No Data
Related