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_ipcor 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
Nordic nRF Series Compared: nRF52 vs nRF53 vs nRF91
Compare Nordic nRF series: nRF52 (BLE/Thread), nRF53 (dual-core, LE Audio), and nRF91 (cellular LTE-M/NB-IoT/GNSS) — when to choose each for your product.
How Do You Set Up the nRF Connect SDK and Zephyr RTOS for nRF52 Development?
Set up nRF Connect SDK (NCS) for nRF52 development: install tools, create a west workspace, configure Kconfig, build a Zephyr project, and flash with J-Link.
How Do You Implement a Matter Device on the nRF Connect SDK?
How to implement a Matter device on Nordic's nRF Connect SDK: dual-core nRF5340 architecture, Zephyr Matter samples, chip-tool, and certification.
How Does PPI/DPPI Work on the nRF52 and nRF53?
How PPI and DPPI let nRF52/nRF53 peripherals trigger each other directly in hardware, with no CPU involvement — channels, fork vs publish/subscribe, and code.
How Do You Use the nRF52840 USB Port and Update Firmware Over DFU?
Use the nRF52840 native USB port in Zephyr NCS: CDC ACM serial, USB DFU class setup, MCUboot dual-slot partitioning, image signing, and DFU trigger workflow.
How Do You Debug Embedded Firmware?
Covers JTAG/SWD hardware debugging, printf over UART or SWO trace, and logic analyser use for embedded firmware on STM32, ESP32, and other MCU platforms.
Related Forum Discussions
nRF5340 network core not starting — BLE stack hangs on bt_enable after migrating from nRF52840
Trying to bring up an nRF5340 DK for the first time. I've done a few nRF52840 projects before so I figured the NCS migration would be fairly
nRF52840 BLE advertising not starting — device not showing up in scanner after bt_enable completes
Trying my first Zephyr/NCS project on an nRF52840 DK after mostly doing ESP32 stuff. Following the [BLE GATT peripheral guide](/questions/nr