Electronics Design AU
nRF

How Do You Structure nRF Connect SDK Firmware for the nRF5340's Dual-Core Architecture?

Last updated 4 August 2026 · 7 min read

Direct Answer

nRF5340 firmware is built as two separate images, one per core: a network-core image (typically the Bluetooth LE or 802.15.4 controller) and an application-core image (the main application). nRF Connect SDK's sysbuild orchestrates building, signing, and flashing both images together as a multi-image build, and the two cores exchange data at runtime through an IPC service built on OpenAMP's remote processor messaging (RPMsg) protocol.

Detailed Explanation

The nRF5340 splits firmware across two independent Arm Cortex-M33 cores rather than running a single monolithic image the way the single-core nRF52 series does. The network core (up to 64 MHz) is dedicated to radio-layer processing, typically running Nordic's Bluetooth LE controller or an 802.15.4 stack for Thread or Zigbee. The application core (up to 128 MHz) runs Zephyr, the main application, and any higher-level protocol logic (a Bluetooth host, Matter, or application-specific code). Nordic's stated rationale for the split is timing isolation: application workload variability on one core does not affect the other core's ability to meet radio-layer timing deadlines. For the broader nRF52-vs-nRF53 selection decision, see Nordic nRF Series Compared; for how this architecture applies specifically to Matter-over-Thread devices, see how to implement a Matter device on the nRF Connect SDK.

This split has a direct consequence for firmware structure: a project targeting the nRF5340 produces two separate compiled images rather than one, and nRF Connect SDK (NCS) needs a way to build, sign, and flash both together in a coordinated way. That's what sysbuild and multi-image builds handle.

Sysbuild and Multi-Image Builds

A single-core nRF52 project builds one firmware image from one west build invocation. An nRF5340 project needs at least two images built together: the application-core image and the network-core image, each with its own prj.conf, device tree overlay, and (usually) MCUboot bootloader slot.

NCS uses sysbuild to coordinate this. Sysbuild treats the application-core build as the primary target and pulls in the network-core image (and, where used, MCUboot images for either core) as additional build targets defined by Kconfig options such as SB_CONFIG_NETCORE_IMAGE and the equivalent MCUboot options for each core. A single west build with sysbuild enabled (the default for new NCS projects since NCS added sysbuild support) produces every image the target board needs in one pass, rather than requiring the older pre-sysbuild "child image" configuration mechanism NCS used previously.

For the network-core image itself, most projects do not write custom network-core firmware. Nordic ships ready-made network-core images for the common cases:

  • hci_ipc: a Bluetooth LE HCI controller image, used when the application core runs the Bluetooth host (Zephyr's host stack or NCS's Bluetooth subsystem).
  • 802154_rpmsg (or the newer spinel-based equivalent): an IEEE 802.15.4 radio image, used for Thread and Zigbee network-core roles.

Most nRF5340 projects select one of these as the network-core image and focus custom development on the application core. Writing custom network-core firmware is a specialised case, generally limited to non-standard radio protocols or use cases needing direct low-level radio access.

If you haven't set up an NCS workspace before, how do you set up the nRF Connect SDK and Zephyr RTOS for nRF52 development covers the base west workspace and toolchain setup this builds on; the nRF5340-specific parts described here sit on top of that same workspace.

The IPC Service

At runtime, the two cores need a way to exchange data: the application core sends commands to the radio stack running on the network core, and the network core sends events and data back. NCS provides this through Zephyr's IPC service API, backed by the OpenAMP framework's remote processor messaging (RPMsg) protocol, running over a shared-memory region and a hardware mailbox mechanism the nRF5340 provides for signalling between cores.

For the common case of a Bluetooth HCI or 802.15.4 network-core image, this IPC transport is already configured by the image itself; the application core interacts with it through the ordinary Zephyr Bluetooth host API or 802.15.4/OpenThread API, not through the IPC service directly. Application code only needs to use the IPC service API explicitly when it defines a custom data path between the two cores that isn't already covered by the standard Bluetooth or 802.15.4 network-core images.

The IPC service's shared-memory region and its size are defined in the board's device tree (the same device tree files that describe the rest of the board's hardware), and both core images must agree on this layout. This is one of the more common points of confusion when adapting a working single-core project or a different Nordic board's device tree without carrying its dual-core-specific configuration across as well.

Flashing Order and Considerations

With sysbuild, west flash normally flashes every image sysbuild built, in the order sysbuild determines, so most projects never need to think about flash ordering explicitly. Where it matters is during iterative development: reflashing the network core is only necessary when its image actually changes, which for most projects using the standard hci_ipc or 802.15.4 images is rare after initial bring-up. Day-to-day application development typically means reflashing only the application core, which is faster and avoids unnecessarily power-cycling a network core that's already running correctly.

A network core that has never been flashed, or was flashed with an incompatible image, is the most common cause of an application core that appears to hang waiting for the Bluetooth stack or 802.15.4 radio to become ready. Confirming the network core's image and version match what the application core expects is usually the first debugging step when a dual-core build behaves correctly on one board but not another.

Debugging Across Both Cores

Each core has its own debug access port and can be attached to independently with a J-Link probe (Nordic's recommended debug adapter for nRF52/53 development). The application core is the default target for most west debug and IDE debug configurations; attaching to the network core requires explicitly selecting its board qualifier or domain, which is less commonly needed once its image is known-good.

The failure mode that catches most engineers new to the dual-core architecture is an application core that appears to hang early in initialisation. In the majority of cases this isn't an application-core bug at all: it's the application core blocking on a Bluetooth or 802.15.4 API call (bt_enable() is the most common) that's waiting on a response from a network core that either has no image, has the wrong image, or isn't yet running. Checking the network core's state, rather than single-stepping application-core initialisation code, resolves this faster in practice. A related migration pitfall from a single-core nRF52840 project is described in the forum thread nRF5340 network core not starting, which walks through this exact symptom on a board migration.

Design Considerations

  • Default to Nordic's ready-made network-core images (hci_ipc, 802154_rpmsg/spinel) rather than writing custom network-core firmware, unless the application specifically needs direct low-level radio access sysbuild's standard images don't expose.
  • Carry device tree IPC and shared-memory configuration across intact when adapting a reference design or a different board's project, since a mismatched shared-memory layout between the two cores' images is a common, hard-to-diagnose source of IPC failures.
  • Treat the network core as infrequently-reflashed once its image is validated. Most iterative development happens on the application core alone; unnecessary network-core reflashing slows the development loop without benefit.
  • Confirm network-core image and version compatibility first when a dual-core build hangs on one board but not another, before assuming the bug is in application-core logic.
  • Dual-core firmware architecture and bring-up: Zeus Design develops nRF5340 dual-core firmware, including network/application core IPC design and bring-up debugging, as part of embedded product development.

Common Mistakes

  • Assuming the nRF5340 is a drop-in firmware upgrade from the nRF52840 and porting a single-image project structure directly, rather than restructuring around the dual-core, multi-image build model from the start.
  • Not flashing the network core at all on a fresh board, then spending debugging time on application-core code when the actual cause is an application core blocked waiting on a Bluetooth or radio API call.
  • Copying an IPC-related device tree overlay from a different board or reference design without carrying across the matching shared-memory region definition, producing an IPC failure that looks like an application-level bug.
  • Writing custom network-core firmware for a use case the standard hci_ipc or 802.15.4 images already cover, adding unnecessary development and maintenance burden.

Frequently Asked Questions

Do I need to write my own IPC protocol between the two cores?
Not for the common case. If the network core runs a standard Nordic-provided image (the Bluetooth HCI IPC image, or the 802.15.4 RPMsg/spinel image for Thread and Zigbee), the IPC service and its backend are already configured for you as part of that sample. You only need to design your own IPC protocol if the application core needs to exchange custom, non-radio data with network-core firmware you're writing yourself, which is uncommon outside of specialised low-latency use cases.
Can I flash and debug just the application core without touching the network core?
Yes, once the network core already has a working image on it. West's flash and debug commands default to the application core's image and domain unless you explicitly select the network core with the appropriate domain or board qualifier. This is the normal day-to-day workflow: flash the network core once when its image changes, then iterate on the application core without reflashing it.

References

Related Questions

Related Forum Discussions