Can't program XIAO nrf52840 Sense using NRF connect SDK in vscode

Hi there,

WOW, That’s pretty Awesome and Tricky…:+1: The pm_static.yml was always a PITA to get right for external QSPI_fash (2MB) and trimming the MCUBoot down is also a “thing” :grin: It’s setting up the Slots (kinda evenly) for the Crash proof DFU I’m working on. i.e if the DFU doesn’t take or crashes it Auto-Magically reverts/Switches back to the OG. :crossed_fingers:

Your Students are very lucky, I have seen discussions on the "chaining the BootLoader and MCUBoot, never got it going though, the double-tap reset is also selected in MCUBoot for DFU ? or no?
The reset button bootloader (double-tap) disappeared when I tried it as well. so maybe something there.

I’ll check out the beacon_dfu that attached.

HTH
GL :slight_smile: PJ :v:

Well, my board is no longer working for neither single tap reset…

Before my first SWD write, I took a memory dump. Even if i write back that memory dump, I can´t get single tap reset or double tab bootloader mode.

So, I’ll wait a new Xiao with working bootloader double tap and test my solution with uf2.

Regarding MCUBOOT and double tap bootloader mode, I’m not sure it is supported…

And, I also noticed when building for xiao_ble_sense, the only uf2 generated is the zephyr.uf2 based on zephyr.hex that is the application only, no mcuboot.
To have a uf2 with mcuboot + application, we would need to get to zephyr/scripts/build and run something like:
python uf2conv.py -c -b 0x27000 -o merged.uf2 -f NRF52840 merged.hex
To get a proper uf2 with both mcuboot and application.

1 Like

Hi there,

AFAIK, that was the old way now, the Build adds it as a kconfig
and there is an option for the Double tap also.
MCUBoot does support double-tap reset detection as a trigger to enter bootloader mode, but it’s optional and hardware/board-specific. NRF_SDK

In the prj.conf or via menuconfig, look for:

kconfig

CONFIG_BOOT_SERIAL_DETECT_DOUBLE_RESET=y

This enables double-reset detection when using serial recovery mode, and optionally:

kconfig

CONFIG_BOOT_SERIAL_DETECT_PORT=<GPIO_PIN>

This sets the GPIO pin used to detect the reset via an external circuit — typically a capacitor between the pin and VCC.

Also FYI, it’s present on the Nordic BLE dongle * thingy devices as well. :+1:

HTH
GL :slight_smile: PJ :v:

I just recieved a fresh PLUS version of the Nrf52840 & S3 so I’ll be testing with those too.

1 Like

And final discovery of the day:

When we build for xiao_ble_sense without sysbuild and without mcuboot, it knows where to put the application properly. You can notice in the build log that it considers the application will start on 0x27000 and due to that will have up to 788KB in size. I assume it gets that from partitions definitions on dts.

If you build with sysbuild and without mcuboot, it will not consider the partiioning information, place the application at 0x0000 and due to that consider up to 1MB in size. It won´t run because the adafruit bootloader will try to load application from 0x27000.

So I tested *with sysbuild and with mcuboot, so that I could use the pm_static.yml to tell zephyr where to place the application and it worked.

Tomorrow I’ll try the following: I want to use uf2 with sysbuild and without MCUBOOT on the this dual bootloader approach. I wonder if i can set the pm_static.yml without MCUBOOT to drive sysbuild to place stuff on the right place.

I could not wait for tomorrow :slight_smile:
You can get xiao_ble_sense kinda working with sysbuild and without mcuboot using the factory uf2 loader if you add a pm_static.yml similar to this:

adafruit_boot:
address: 0xf4000
end_address: 0x100000
region: flash_primary
size: 0xc000
app:
address: 0x27000
end_address: 0xec000
region: flash_primary
size: 0xc5000
sd_partition:
address: 0x0
end_address: 0x27000
region: flash_primary
size: 0x27000
storage:
address: 0xec000
end_address: 0xf4000
region: flash_primary
size: 0x8000
sram_primary:
address: 0x20000000
end_address: 0x20040000
region: sram_primary
size: 0x40000

This will instruct sysbuild to know where to place the application (0x27000, just where the adafruit bootloeader will jump to).

The issue is that it wont generate a uf2. But it will generate a merged.hex (even without mcuboot) that you can convert to a uf2 and it will run properly.

2 Likes

Hi there,

OK, So

  • The Adafruit UF2 bootloader expects the app to be at 0x27000
  • If Zephyr/sysbuild places the app at 0x0000, the bootloader can’t find it
  • Sysbuild defaults to full-chip partitioning unless overridden
  • MCUboot adds partition logic that aligns with many dual-boot systems
  • The workaround is:
    * Use pm_static.yml or custom .dts overlays to explicitly set app flash offset
    * Ensure alignment with UF2 or MCUboot expectations
    • Manually define partitions using pm_static.yml
  • Confirm that Zephyr links the app to 0x27000
  • Avoid hardcoding 0x0000 or using default sysbuild memory layout

I would un tick the Create build and generate the config. then use the Kmenu config to set the options. (nrf_sdk)

Good stuff, More testing tomorrow :v:

GL :slight_smile: PJ :+1:

EDIT:
LOL, perfect… :grin:

Great summary.
Just have in mind that:

  • No Sysbuild and No Mcuboot - Partitions are get from dts
  • No Sysbuild and With Mcuboot - Partitions are get from Partition Manager (pm_static to fix it)
  • Sysbuild - Partitions are always get from Partition Manager (pm_static to fix it)
1 Like

I read the a bunch about this and tested all I could find, but I still can’t get my code to work. I’m trying to use the fast pair fmdn example from nRF which uses the mergehex to embed some configuration.

The problem I ran into:

  • If I use the generated zephyr.uf2 the code runs, but the configuration is not included and the code fails.
  • If I use the merged.hex converted to uf2 the code doesn’t even run and the flashing directory doesn’t unmount itself after the whole file has finished writing.

I’m not using mcuboot but I’m using (and have to use because of mergehex and the fast pair configuration) sysbuild.

Is there a specific thing I have to do to make sure my code will run even with mergehex?

Hi there,

So , It sounds like you’re running into a common pain point when using mergehex together with sysbuild and Fast Pair configs on the nRF platform. They definitely could improve the FMD integration but G & co. is NOT real keen to change there stuff. ANy way :thinking:

A few things to consider:

  • Sysbuild Output Format: Sysbuild by default can generate multiple artifacts (like .hex, .bin, .uf2). When using mergehex, you’re typically combining multiple .hex files (e.g., application + config). But the final merged hex may not always be fully UF2-compatible without an extra conversion step. mergehex doesn’t “rebuild” the metadata needed for UF2 properly, it just merges the memory contents.
  • UF2 Bootloader Expectations: If you’re flashing via drag-and-drop onto a device mass storage (like a DK board or dongle), the UF2 loader expects certain address alignments and metadata. If your merged UF2 isn’t working (e.g., flashing never completes/unmounts), it could be because the merged HEX isn’t producing a correct UF2 file afterward — it’s likely missing essential vector table addresses or metadata. :+1:
  • Not Using MCUboot: Without MCUboot, your app needs to be positioned and built in a way that the bootloader (or ROM bootloader) expects. If mergehex changes the memory map (even slightly), but the device expects a clean app image, it might hang at boot.
  • Tips:
    • After merging, rebuild the UF2 properly (don’t just hex2uf2 blindly) — maybe re-parse the hex into a bin + generate UF2.
    • Check your linker script or sysbuild config to make sure the memory layout remains consistent even after merging.
    • Double-check whether your Fast Pair config blob needs to be linked differently (e.g., as a section inside your main app instead of merged externally).
    • If possible, try merging at build time using sysbuild config instead of post-build mergehex, so the build system knows everything that will be included.

You might want to dig into how sysbuild sets the partition layouts too — sometimes merged.hex isn’t just app+config but includes other parts like settings.hex or bootloader.hex that need to be properly accounted for. I would also post it on the NRF Forum too. I have seen a few FMD issues there in different scenarios.

HTH
GL :slight_smile: PJ :v:

Stay at it , your almost there. :crossed_fingers:

Hello,

I am facing this same issue with my xiao_ble board - I updated the bootloader to the one from Adafruit, v0.9.2. I am building the blinky sample with nRF Connect SDK v3.0.0 with the --no-sysbuild option, and when I copy the generated uf2 file into the bootloader folder, the copy is successful but nothing blinks… I also tried the uf2 you have provided here and it didn’t work for me.

I am able to enter the bootloader again so I know that the device is not bricked. Any ideas on what I could try? I’m a bit lost.

Thank you!

Hi there,

and Welcome here…

So this is a common misconception about the builds, and boot loaders
If you’re using Zephyr/NCS to build UF2 files, they won’t work with Adafruit’s bootloader out of the box. The memory layout and expected image headers don’t match.

  • Using a Xiao BLE (nRF52840) with Adafruit bootloader v0.9.2
  • Building a Zephyr app (like blinky) using nRF Connect SDK v3.0.0
  • Using --no-sysbuild
  • Successfully copies the .uf2 to the bootloader, but nothing runs
  • Device can still re-enter bootloader, so not bricked

Your options:

  • Either switch back to the original Seeed/Nordic bootloader (or no bootloader at all) and flash using nrfjprog or west flash
  • Or build with Arduino/CircuitPython if you want to stick with the Adafruit UF2 bootloader

TL;DR: Adafruit UF2 bootloader is not compatible with Zephyr builds unless you do extra steps.

Use nrf52840dk_nrf52840 + Custom Partitioning (Advanced)

To make Zephyr firmware compatible with Adafruit’s UF2 bootloader:

  • Use nrf52840dk_nrf52840 as the board target
  • Add a custom pm_static.yml or partition overlay to match Adafruit’s bootloader layout
  • Or better: Use MCUboot as the secondary bootloader to package the app

But this is non-trivial.

I have a video and demo on here doing exactly that with the DK and the nRF52840 Xiao via SWD, use the search and “Nordic” key word it’s in the list returned.
This is very good to know how it works, check out the Nordic Tech ed Webinar on “Builds & Boot loaders” they have recently updated them so worth it’s weight in GOLD and it’s free. :+1:

HTH
GL :slight_smile: PJ :v:

of all of it related to Xiao , The " pm_static.yml " is the Secret :shushing_face: learn it , know it LOVE it!

Thank you for your reply!

While I understand that there is a mismatch between the bootloader and the NCS images, I have found multiple posts/comments from people saying that this has worked for them. Just on this post (title: Zephyr samples not working on NRF5280 board), I see multiple people saying that fiddling around with their SDK versions or disabling SYSBUILD made it work for them with the UF2. And in this same post, you have also said that it worked for you and even uploaded a uf2 file. This is why I am so confused.

Ultimately, what I want to do is get rid of the Adafruit bootloader and replace it with MCUBoot. But for now, I want to get the uf2 upload working as a means of easy flashing…

UPDATE: I switched back to the original Seeed_XIAO_nRF52840_bootloader-0.6.1_s140_7.3.0.zip bootloader, rebuilt blinky from Zephyr with --no-sysbuild and I have a blinking LED!

Hi there,

Ah’ yes I see… sorry I stopped comprehending :grin: after NOT bricked…
Yes it does work, I haven’t built it with the new version of Adafruit bootloader you see the video it’s old by now. So the short of it this, the SDK version and tool-chains had to all be just what versions to do it (hence the fiddling) :sweat_smile:
I can assume then you have a similar setup Hardware wise ? what is that?
Nrf52840DK and SWD to Xiao on Dev expansion board?
Then look at the Sysbuild, it used to be required. Now it’s not but only on the latest versions.

You’ll get it , took me a couple tries and a few erased devices, once the DK :stuck_out_tongue_closed_eyes: and once the Xiao but hay it’s great learning. :crossed_fingers:

Ultimately , YES MCUBoot is the way forward if you want any of the advanced features a BL can offer. ie. crash-proof DFU for starters, multiple DFU image slots. some advanced security too. SO you ARE heading in the right direction IMO. :+1:

run through the Nordic web video on the building for target devices. It was what made it go for me then.

HTH
GL :slight_smile: PJ :v:

BTW, which tool chain are you using?

For now, I only have the xiao_ble by itself. I also have a nRF52840DK that I use as a JLink but I don’t have any SWD wires soldered to the xiao_ble (yet). Once the xiao_ble is connected to the DK and I have JLink access, nothing else will matter until most of the development is complete - bootloader will come later.

For the xiao_ble + uf2 bootloader, disabling sysbuild works. I know that in future versions, sysbuild will become mandatory, so I am trying to figure out how to do it with sysbuild.

I am using the Zephyr 0.17.0 toolchain.

Thanks for the tip with the pm_static.yml:

Here is the properly formatted file in case someone needs it:

adafruit_boot:
  address: 0xf4000
  end_address: 0x100000
  region: flash_primary
  size: 0xc000
app:
  address: 0x27000
  end_address: 0xec000
  region: flash_primary
  size: 0xc5000
sd_partition:
  address: 0x0
  end_address: 0x27000
  region: flash_primary
  size: 0x27000
storage:
  address: 0xec000
  end_address: 0xf4000
  region: flash_primary
  size: 0x8000
sram_primary:
  address: 0x20000000
  end_address: 0x20040000
  region: sram_primary
  size: 0x40000

It works fine with the default sysbuild options and produces a working .uf2 file that can be flashed with:

west flash -r uf2

Tested with nRF Connect SDK v3.0.2.

The next step would be to investigate the MCUboot options for easier flashing / updating.

Hi there,

Ok, You hit it…BINGO!
so check this out…
The Zephyr toolchain is the issue, you have to use the NRF_toolchain and it will work, or use ONLY the Zephyr tools (command-line) if you are mixing. that is really where the problem lies. There is tons of info available about the incompatibilities but only when you mix in the adafruit BL. I can only say I did it with NRF_SDK and it’s Tool chains, leaving the Adafruit BL intact when Flashing the Xiao (uf2, drag&drop)

later I did try with the Zephyr Vanilla tools and toolchain but the Board, files and overlays where not compatible with NRF’s graphical board pin diagram. and at that time I wasn’t able to create my own.

Swap out the toolchain and see what you get. :+1:

HTH
GL :slight_smile: PJ :v:

funny thing is it works one way but not the other, I do believe that is the case. and IMO the adafruit BL is just Meh’ Seeed should have invested some time in using MCUBoot but , the fruit guys were the ones doing it so there’s that. (some good reading about sandeep ministry, et’al) early dev efforts and Xiao.

fyi, I’ll be setting this up again to revisit, update and for something New…So this is going to be a FIRE :fire: HOT :hot_pepper:topic coming Sooon! :heart_eyes:

Legend! Thank you for sharing this. Do you know if there is a way to name the file so that it only applies to certain boards? I don’t want this to apply to a different board that I’m using for the same project.

Hi there,

Yes! Place your pm_static.yml and overlay.conf inside a boards/your_board_name/ folder within your project. Zephyr will use them only when building that board.
Or use the -- -DPM_STATIC_YML_FILE=... method to explicitly include it per build. see nordic video. :+1:

If you’re using multiple boards in a single project, you can create a folder like:

your_project/
├── boards/
│   ├── your_board_name/
│   │   ├── pm_static.yml
│   │   ├── overlay.conf
│   │   └── board.cmake (optional)
├── src/
│   └── main.c
├── CMakeLists.txt
└── prj.conf

this was how I learned to set it up from the mustache man at nordic :grin:

HTH
GL :slight_smile: PJ :v:

1 Like

Hm that didn’t quite work - the build system failed to pick up my board specific files altogether when I moved them into a board/xiao_ble folder under my project root…

Should be

boards\xiao_ble\pm_static.yml

boards, not board.

1 Like