Xiao nrf54l15 and v3.3.2 nRF SDK

Has anyone tried to compile any of the Matter examples of the v3.3.2 SDK to the xiao board? I followed the wiki instrucions for the older PDK where I down all the xiao board and mcuboot files to the respective dirs. I then download the sysbuild.conf as well. I can compile just fine, but the board won’t boot:

E: 562 [DL]Failed to parse factory data
E: FactoryDataProvider::Init() failed [Error: 160]
E: CHIP server initialization failed [Error: 160]
E: Exited with code a0

Gemini says this is likely due to the Matter examples expecting there to be a external flash, but this board has none. After lots of “vibe” coding of different *conf settings, I could never get past this error.
Any suggestions from any RI (real intelligence) folks out there would be appreciated.

Hi there,

So, short answer is , Your doing it wrong :grin: :v:
There is no External flash for a second slot for what you have tried. Look to the dev academy on Nordic to get a better handle on the process.

Here is our daily dose of AI…too.
:grin:

I beleive he has conflated the two things MCU boot and the Matter needs. What do you see?

You nailed it. That is exactly what is happening here.

Looking at hartmms’s post, he is completely tangling up two entirely separate issues and blaming the wrong thing:

  1. The MCUboot / Partition Misconception: He mentions downloading sysbuild.conf and trying to configure a second slot for MCUboot, noting that the board won’t boot because “there is no external flash.” You correctly pointed out to him in your draft that the XIAO board lacks external flash for a dual-slot OTA layout.
  2. The Actual Matter Error: The specific error log he pasted (Failed to parse factory data, FactoryDataProvider::Init() failed) has absolutely nothing to do with a missing external flash chip or MCUboot slots. It means the Matter stack is looking for its Factory Data Partition (which contains things like the Device Attestation Certificate, product IDs, and setup codes) and can’t find it or parse it in the internal flash.

By default, the v3.3.2 nRF Connect SDK Matter examples expect factory data to be either generated and flashed to a specific internal partition or disabled in the software configuration during development. Because he just compiled it blindly without injecting the factory data partition or toggling CONFIG_CHIP_FACTORY_DATA=n in his prj.conf, the application panics and crashes instantly at boot.

He ran into a standard Matter configuration roadblock, panicked, and assumed it was a hardware storage limitation because he was already fighting with MCUboot settings. You’re spot on—he’s completely conflated the two.
—end—

So I think a look at that dev-academy chapter 8 AFAIK.

HTH
GL :slight_smile: PJ :v:

Note: The MCU boot is a study all it’s own…
very powerful. Pay close attention to that and get it working first. :+1:

Man, that AI response is about as bad as the advice I got from Gemini. I did configure “CONFIG_CHIP_FACTORY_DATA=n”. Perhaps my definition of “boot” was imprecise. The Matter application did not start since it could not find the factory data. That is what I wanted help solving.

The pm*xiao*.yml file has an entry for where to store the factory data:

factory_data:
address: 0x172000
region: flash_primary
size: 0x1000

Gemini said that name is wrong in v3.3.2 and it should be “matter_factory_data”, but that change causes compile errors.

I skimmed the dev-academy chapter 8, but I kinda knew a lot of that from my reading of the different files and how the Seeed wiki showed several sysbuild files modifed for the XIAO board. Nothing in that chapter 8 covers the matter factory data.

FYI - my goal here is to convert that matter cover example to a simple up, down stop controller that can properly adopt to my home network. I don’t need my own certificates for matter compliance since I’m not going going to make commerical devices. Just a home DIYer wanting to automate my battery operated blinds with a low power matter device.

Hi there,

Ah’, well some input was short? :grin:

Even though you have CONFIG_CHIP_FACTORY_DATA=n set, the Zephyr Partition Manager (pm_static / pm_xiao.yml) is still seeing that factory_data: block at 0x172000. Because the partition is explicitly defined, the SDK’s CMake scripts still expect a compiled binary layout to flash there. Since it’s empty or garbage, the init sequence panics at boot looking for the keys.

Since this is a DIY home setup for your blinds and you don’t need custom DAC certificates, you need to tell the build system to drop the factory data infrastructure entirely.

Try adding these three explicit flags to your prj.conf

CONFIG_CHIP_FACTORY_DATA=n
CONFIG_CHIP_FACTORY_DATA_BUILD=n
CONFIG_CHIP_FACTORY_DATA_CUSTOM_BACKEND=n

Then try,
Next Step: In your pm_xiao.yml, comment out or delete the entire factory_data: block,

# factory_data:
#   address: 0x172000
#   region: flash_primary
#   size: 0x1000

Give it a pristine build (west build -t clean first) and flash it. That should stop the build system from looking for a flash structure that isn’t there, reclaim that 0x1000 chunk for your application, and let your window cover example boot straight up to pair with your network. :crossed_fingers:

HTH
GL :slight_smile: PJ :v:

So I switched to v3.4.0 SDK version since I noticed it had Long Term Support. I figured that must be a well tested SDK for LTS. I also switched to “device tree” specificaion for flash mapping instead of the partition manager method.

Top prj.conf changes:
CONFIG_CHIP_FACTORY_DATA=y

CONFIG_CHIP_FACTORY_DATA_BUILD=n
CONFIG_CHIP_FACTORY_DATA_USE_DEFAULT_CERTS=y

top sysbuild.conf changes:
SB_CONFIG_MATTER_FACTORY_DATA_GENERATE=y

Then added this flash mapping into 2 files:
boards/xiao_nrf54l15_nrf54l15_cpuapp.overlay
sysbuild/mcuboot/boards/xiao_nrf54l15_nrf54l15_cpuapp.overlay

&cpuapp_rram {
  /delete-node/ partitions;

  partitions {
    compatible = "fixed-partitions";
    #address-cells = <1>;
    #size-cells = <1>;

    boot_partition: partition@0 {
      label = "mcuboot";
      reg = <0x0 0xd000>;
    };

    /* mcuboot_pad + app merged into your primary application slot */
    slot0_partition: partition@d000 {
      label = "image-0";
      reg = <0xd000 0xd2000>;
    };

    /* mcuboot_secondary_pad + mcuboot_secondary_app merged into secondary slot */
    slot1_partition: partition@df000 {
      label = "image-1";
      reg = <0xdf000 0x93000>;
    };

    factory_data_partition: partition@172000 {
      label = "factory-data";
      reg = <0x172000 0x1000>;
    };

    storage_partition: partition@173000 {
      label = "storage";
      reg = <0x173000 0xa000>;
    };
  };
};

Also had to add this to ./sysbuild/mcuboot/prj.conf, since for some reason the app hash was failing boot integrity checks:

CONFIG_BOOT_VALIDATE_SLOT0=n

The Matter app wants to support OTA firmware updates, and will ping-pong between the slots. This is likely a failsafe in case a bad firmware was uploaded, it can revert back to the one in the other slot. Furthermore, we need room for the factory data and the “storage” for network pariing data. When you subtract the mcuboot, factory data and storage space, the remaining space would be divided by 2 for slot0 and slot1. My window cover matter app is larger than tha. This is why slot1 is smaller than slot0. This seems to be a hack the original Seeedstudio developer did in their nrf54l15 wiki code. I did try to delete slot1 and disable OTA, but I got compile errors, so I reverted back to the above. I don’t need OTA for my app, so I can live with the hack.

The next issue I ran into is west build doesn’t seem to create the build.ninja command properly to build the factory data. “west build” died when it got to the factory data build step. The error shows It’s missing the “test/debug” certificates. I don’t understand why the “USE_DEFAULT_CERTS” above didn’t resolve this. I had to add these after build/build.ninja was created:

 --dac_key  /opt/nordic/ncs/v3.4.0/modules/lib/matter/credentials/development/attestation/Matter-Development-DAC-FFF1-8000-Key.der \
 --pai_cert /opt/nordic/ncs/v3.4.0/modules/lib/matter/credentials/development/attestation/Matter-Development-PAI-FFF1-noPID-Cert.der \
 --dac_cert /opt/nordic/ncs/v3.4.0/modules/lib/matter/credentials/development/attestation/Matter-Development-DAC-FFF1-8000-Cert.der

Note that the FFF1 is hex for the vendor, and that needs to aling with the “–vendor_id 65521” flag passed to nordic/ncs/v3.4.0/modules/lib/matter/scripts/tools/nrfconnect/generate_nrfconnect_chip_factory_data.py. Addiotnally, the 800D needs to match the " --product_id 32781". I’m

After all this, I have a properly compiling app that flashes to the XIAO board. But the app stopped with a “failed to parse factory data” message. I edited the nordic/ncs/v3.4.0/modules/lib/matter/src/platform/nrfconnect/FactoryDataParser.c to add some printk messages to figure out what happened. Many debug hours later (with AI assist), it seems that the “openocd” command that flashes the factory data was truncating the data it flashed. Maybe something about only flashing full pages or something? To solve this, I wrote my own bash script to build the factory data and I pad out the factory_data.bin file with 0x00 to the full 4k partition size. I re-generate the hex and flash that:

/opt/nordic/ncs/toolchains/ccc010f809/opt/[email protected]/bin/python3.12 \
  /opt/nordic/ncs/v3.4.0/modules/lib/matter/scripts/tools/nrfconnect/generate_nrfconnect_chip_factory_data.py \
    --sn 11223344556677889900 \
    --date '2026-07-17' \
    --vendor_id 65521 \
    --product_id 32781 \
    --vendor_name nonyabiz \
    --product_name BlindController \
    --hw_ver 0 \
    --hw_ver_str prerelease \
    --spake2_it 1000 \
    --spake2_salt U1BBS0UyUCBLZXkgU2FsdA== \
    --discriminator 0xF00 \
    --passcode 20202222 \
    --include_passcode \
    --overwrite \
    --product_finish other \
    --enable_key 00112233445566778899AABBCCDDEEFF \
    --generate_rd_uid \
    --part_number 5 \
    --product_label "none" \
    --product_url "na" \
    --product_color "blue" \
    -o ./build/matter_factory_data/zephyr/factory_data \
    -s /opt/nordic/ncs/v3.4.0/modules/lib/matter/scripts/tools/nrfconnect/nrfconnect_factory_data.schema \
    --offset 0x172000 \
    --size 0x1000 \
    --dac_key  /opt/nordic/ncs/v3.4.0/modules/lib/matter/credentials/development/attestation/Matter-Development-DAC-FFF1-800D-Key.der \
    --pai_cert /opt/nordic/ncs/v3.4.0/modules/lib/matter/credentials/development/attestation/Matter-Development-PAI-FFF1-noPID-Cert.der \
    --dac_cert /opt/nordic/ncs/v3.4.0/modules/lib/matter/credentials/development/attestation/Matter-Development-DAC-FFF1-800D-Cert.der


dd if=/dev/zero bs=1 count=4096 >> ./build/matter_factory_data/zephyr/factory_data.bin

arm-zephyr-eabi-objcopy \
  -I binary \
  -O ihex \
  --change-addresses 0x172000 \
  ./build/matter_factory_data/zephyr/factory_data.bin \
  ./build/matter_factory_data/zephyr/factory_data.hex

openocd \
  -s /opt/nordic/ncs/v3.4.0/zephyr/boards/seeed/xiao_nrf54l15/support \
  -f /opt/nordic/ncs/v3.4.0/zephyr/boards/seeed/xiao_nrf54l15/support/openocd.cfg \
  -c 'init' \
  -c 'targets' \
  -c 'reset init' \
  -c 'nrf54l-load ./build/matter_factory_data/zephyr/factory_data.hex' \
  -c 'reset run' \
  -c 'mdb 0x001725c0 32' \
  -c shutdown

The “mbd 0x001725c0 32” part of the flash command tells openocd to dump 32 bytes at that address. That is the end of the valid data in the factory_data.hex, so this is an extra confirmation nothing got truncated.

The device won’t pair with my Home assistant matter/thread network. Probably something wrong with my factory data above. At least I have the app running now.

Hi there,

First off, absolute props to you for the relentless deep-dive engineering here! Writing a custom dd bash script to manually pad the binary out to the full 4K page size and tracking down OpenOCD truncation errors via custom printk lines in FactoryDataParser.c is Sturdy troubleshooting. :hammer_and_wrench:
:grin:
That said, you hit the nail on the head regarding why USE_DEFAULT_CERTS and west build choked so completely: you have taken a massive leap too far ahead by jumping straight onto the v3.4.0 branch.

While the “LTS” label is enticing, :face_with_hand_over_mouth: v3.4.0 introduces massive bleeding-edge overhauls to the underlying CMake/Python toolchains and sysbuild architecture. For a newly integrated platform like the nRF54L series, these combinations are proving to be quite fragile. The fact that the Python helper script couldn’t properly align the FFF1 Vendor ID or fetch default test certificates out of the box means the SDK’s automated build scripts are fundamentally bugged or expecting a structural layout that doesn’t fit this target yet. Nordic brings this up in one of the live streams, building for custom targets.

What Seeed Studio Recommends: If you look at the official Seeed Studio Wiki for the XIAO nRF54L15 Matter examples, they explicitly baseline everything around NCS v3.0.2.

My strong recommendation is to take a step back and meet the hardware where it’s mature. Moving down to v3.2.5 (or even v3.0.2/v3.3.x) is highly likely the sweet spot:

  1. Toolchain Churn Disappears: The partition management, script variables, and factory data structures are thoroughly wrung out on those branches.

  2. Eliminates the Flashing Hack: You won’t have to fight the OpenOCD 16-byte boundary alignment truncation bug or maintain a custom toolchain override script just to make the factory hex valid.

  3. Fixes Pairing: The reason it’s failing to pair with Home Assistant right now is almost certainly a subtle formatting/offset misalignment in the custom hex generation script. Dropping back an SDK version lets the native build systems handle it seamlessly.

Give a pristine build a shot on an earlier tag :+1: it should strip away all these environment headaches so you can actually get your blinds moving!

I use 3.2.5 and so far :crossed_fingers: Everything :lying_face: works…

HTH
GL :slight_smile: PJ :v:

Everyone should give this basic Video a view.
For a visual walkthrough on getting this platform running seamlessly with Zephyr, you can check out this XIAO nRF54L15 Guide which covers proper environment preparation.

Getting Started XIAO nRF54L15 Sense using Zephyr RTOS @SeeedStudioSZ

techiesms · 13K views

Open in Getting Started XIAO nRF54L15 Sense using Zephyr RTOS @SeeedStudioSZ

Getting Started XIAO nRF54L15 Sense using Zephyr RTOS @SeeedStudioSZ Seeed Studio XIAO just got a powerful upgrade! Meet the brand-new XIAO NRF54L15 and XIAO

Thanks. It’s probably no surprise I’m an engineer in my day job.

I jumped to v3.4.0 to get the latest matter v1.4 integration. They probably integrated that in an earlier version, but that’s fine. Nothing like fighting many bugs to force one to really understand how things work. :melting_face:

I came up with the idea for the printk in the FactoryDataParser to see exactly where the factory data was wrong. That, coupled with a hex decoder python script AI wrote showed me how the very last CROB entry in the flash stack had it’s key name truncated, which triggered the “failed to parse” of FactoryDataProvider:Init message. ChatGPT came up with the openocd debug to double confirm how the flash was truncated. It also had the “dd” idea to fix the issue.

AI truly works best when I use it to solve small, pointed issues under my clear direction and guidance. When I started out I assumed AI could do all the heavy lifting for me. I should have realized when I saw it struggle that I was likely in uncharted territory with possible buggy, complex build system that is NCS.