Zigbee: NCP

The Zigbee NCP sample demonstrates the usage of Zigbee’s Network Co-Processor (NCP) architecture.

Together with the source code from ZBOSS NCP Host, you can use this sample to create a complete and functional Zigbee device. For example, as shown in the Testing scenario, you can program a development kit with the NCP sample and bundle it with the simple gateway application on the NCP host processor.

You can then use this sample together with the Zigbee light bulb to set up a basic Zigbee network.


The sample supports the following development kits:

Hardware platforms


Board name

Build target

nRF52840 DK




nRF52840 Dongle




nRF52833 DK




nRF21540 DK




nRF5340 DK




nrf5340dk_nrf5340_cpuapp is supported only for development.

You can use any of the development kits listed above.


The nRF52840 Dongle uses a different bootloader than other development kits.

For this sample to work, you also need the following:

  • ZBOSS NCP Host tool, which is based on the ZBOSS stack and requires a PC with an operating system compatible with the 64-bit Ubuntu 18.04 Linux. The tool is available for download as a standalone zip package using the following link:

    For more information, see also the NCP Host documentation.

  • The Zigbee: Light bulb sample programmed on one separate device.

This means that you need at least two development kits for testing this sample.

Zigbee NCP sample setup overview

Zigbee NCP sample setup overview

Requirements for DFU through MCUboot

If you opt for MCUboot when selecting the Bootloader support, you will need the dfu-util tool to upload the new firmware image.


The sample demonstrates using a Nordic Semiconductor’s Development Kit as Zigbee Network Co-Processor.

The sample uses the CONFIG_ZIGBEE_LIBRARY_NCP_DEV Kconfig option, which is available as part of the ZBOSS library configuration. The NCP Kconfig option extends the compilation process with an implementation of the ZBOSS API serialization through NCP commands. It also implements the ZBOSS default signal handler function, which controls the ZBOSS and commissioning logic.

The sample is built to work with bootloader. See Bootloader support for more information.

The NCP application creates and starts a ZBOSS thread as well as the communication channel for NCP commands that are exchanged between the connectivity device and the host processor.


See Configuring your application for information about how to permanently or temporarily change the configuration.

See IEEE 802.15.4 EUI-64 configuration for information about how to configure the IEEE address for this sample.

Serial communication setup

The communication channel uses Zephyr’s UART API. This serial device is selected with CONFIG_ZIGBEE_UART_DEVICE_NAME.

By default, Zephyr’s logger uses UART_0 and the NCP sample communicates through the UART serialization using UART_1. The DTS overlay file configures UART_1 to be connected to the on-board J-Link instead of UART_0. As the result, Zephyr’s logger UART_0 is available only through GPIO pins (P1.00 and P1.01).

The UART_0 pins are configured by Devicetree overlay files for each supported development kit in the boards directory.

Communication through USB

You can change the communication channel from the default UART to nRF USB CDC ACM CDC_ACM_0 by using the prj_usb.conf configuration file and adding the -DCONF_FILE='prj_usb.conf' flag to the build command. See Providing CMake options for instructions on how to add this flag to your build. For example, when building from the command line, you can use the following command:

west build samples/zigbee/ncp -b nrf52840dk_nrf52840 -- -DCONF_FILE='prj_usb.conf'

The USB device VID and PID are configured by the sample’s Kconfig file.


The USB is used as the default NCP communication channel when using the nRF52840 Dongle.

When you change the communication channel to nRF USB with prj_usb.conf, Zigbee stack logs start to be printed by default in binary format using UART_1. This is configured in the prj_usb.conf file with the following settings:

Alternatively, you can configure Zigbee stack logs to be printed in binary format using an independent CDC ACM device of the same nRF USB. To do so, complete the following steps:

  1. Set the following Kconfig options:

  2. Create two instances of USB CDC ACM for application by completing the following steps:

    1. Create two entries in the DTS overlay file for the selected board, one for each USB CDC ACM instance. See USB device stack CDC ACM support for more information.

    2. While the NCP sample configures single USB CDC ACM instance "CDC_ACM_0" by default, configure the second USB CDC ACM instance "CDC_ACM_1" by extending zephyr_udc0 node in the DTS overlay file with the following code:

      &zephyr_udc0 {
         cdc_acm_uart0: cdc_acm_uart0 {
            compatible = "zephyr,cdc-acm-uart";
            label = "CDC_ACM_0";
         cdc_acm_uart1: cdc_acm_uart1 {
            compatible = "zephyr,cdc-acm-uart";
            label = "CDC_ACM_1";
  3. Enable the composite USB device driver using the CONFIG_USB_COMPOSITE_DEVICE Kconfig option.

With this configuration, you will see two serial ports created by the NCP sample. Use the first one for NCP communication. Use second serial port for collecting Zigbee stack logs.

You can also check the prj_usb.conf file, which contains the complete Kconfig configuration of Zigbee stack logs over nRF USB serial commented out. For more configuration options, see Zigbee stack logs.

Bootloader support

The bootloader support in the NCP sample depends on the development kit, its respective build target, and Serial communication setup:

  • For the nrf52840dongle_nrf52840 build target, nRF5 SDK Bootloader is used by default because the dongle comes with this bootloader preinstalled.

  • For the nrf52840dk_nrf52840, nrf52833dk_nrf52833, and nrf21540dk_nrf52840 build targets, the following scenarios are possible when building for these build targets:

    • If the Communication through USB is selected, MCUboot is enabled by default.

    • If the default UART serial communication channel is used, the bootloader support is not enabled, but MCUboot can be enabled by the user.


When the Communication through USB is selected, MCUboot in this sample is built with support for single application slot, and uses the USB DFU class driver to allow uploading image over USB.

If you want to use the default UART serial communication channel, you can enable MCUboot by setting the CONFIG_BOOTLOADER_MCUBOOT Kconfig option. To use the same MCUboot configuration as in Communication through USB, you need to provide MCUboot with the Kconfig options included in the child_image/mcuboot_usb.conf file. See Image-specific variables for how to set the required options.

MCUboot with the USB DFU requires a larger partition. To increase the partition, define the PM_STATIC_YML_FILE variable that provides the path to the pm_static.yml static configuration file in the configuration directory for the build target of your choice.

For instructions on how to set these additional options and configuration at build time, see Providing CMake options and Configuring your application.

See the following command-line instruction for an example:

west build samples/zigbee/ncp -b nrf52840dk_nrf52840 -- -DCONFIG_BOOTLOADER_MCUBOOT=y  -Dmcuboot_CONFIG_MULTITHREADING=y -Dmcuboot_CONFIG_BOOT_USB_DFU_WAIT=y -Dmcuboot_CONFIG_SINGLE_APPLICATION_SLOT=y -DPM_STATIC_YML_FILE=samples/zigbee/ncp/configuration/nrf52840dk_nrf52840/pm_static.yml

When building the sample, the build system also generates the signed app_update.bin image file in the build directory. This file can be used to upgrade a device. See Using MCUboot in nRF Connect SDK for more information about this and other automatically generated files.

After every reset, the sample first boots to MCUboot and then, after a couple of seconds, the NCP sample is booted. When booted to MCUboot, the new image can be uploaded with the dfu-util tool. See the Testing section of the USB DFU sample documentation for the list of required dfu-util commands.

To learn more about configuring bootloader for an application in nRF Connect SDK, see the Secure bootloader chain page.

nRF5 SDK Bootloader

When the sample is built for nrf52840dongle_nrf52840, the build system does not produce an upgrade image. to upgrade the dongle, you can use one of the following options:

  • nRF Connect Programmer application (part of nRF Connect for Desktop). For more details, see Programming the nRF52840 Dongle in the nRF Connect Programmer user guide.

  • nRF Util tool, if you do not want to use the nRF Connect Programmer application. To generate a DFU package, see Generating DFU packages in the nRF Util user guide. Upgrading the dongle using this method requires putting the dongle into the DFU mode. When in the DFU mode, you can use nRF Util for sending the upgrade image. See DFU over a serial USB connection in the nRF Util user guide.


    By default, you can enter the DFU mode on the dongle using the pin reset. Alternatively, you can also trigger the bootloader on the dongle from the NCP Host application by calling ncp_host_ota_run_bootloader().

FEM support

You can add support for the nRF21540 front-end module to this sample by using one of the following options, depending on your hardware:

  • Build the sample for one board that contains the nRF21540 FEM, such as nrf21540dk_nrf52840.

  • Manually create a devicetree overlay file that describes how FEM is connected to the nRF5 SoC in your device. See Set devicetree overlays for different ways of adding the overlay file.

  • Provide nRF21540 FEM capabilities by using a shield, for example the nRF21540 EK shield that is available in the nRF Connect SDK. In this case, build the project for a board connected to the shield you are using with an appropriate variable included in the build command. This variable instructs the build system to append the appropriate devicetree overlay file. For example, to build the sample from the command line for an nRF52833 DK with the nRF21540 EK attached, use the following command within the sample directory:

    west build -b nrf52833dk_nrf52833 -- -DSHIELD=nrf21540_ek

    This command builds the application firmware. See Programming nRF21540 EK for information about how to program when you are using a board with a network core, for example nRF5340 DK.

Each of these options adds the description of the nRF21540 FEM to the devicetree. See Radio front-end module (FEM) support for more information about FEM in the nRF Connect SDK.

To add support for other front-end modules, add the respective devicetree file entries to the board devicetree file or the devicetree overlay file.

Vendor-specific commands

You can extend the NCP sample with support for vendor-specific commands to implement new features, such as controlling LEDs. These commands let you request custom actions over the ZBOSS NCP protocol.

Vendor-specific commands are sent over the NCP protocol using the following types of packets:

  • Request - These can be sent only by the host. The nRF SoC must respond to all of them.

  • Response - These can be sent only by the nRF SoC. The nRF SoC can send them only when requested by the host. This limitation can be bypassed by indications.

  • Indication - These can be sent only by the nRF SoC. The indications are sent on demand from the nRF SoC to the host, for example to inform the host about polling avoidance or sudden or rare events, such as pressing the button. Indications are neither responded to nor acknowledged.

By default, the NCP sample already supports the vendor-specific commands for controlling a LED.

Implementing vendor-specific commands


The steps in this section describe the process of implementing the vendor-specific commands in the NCP sample. Documentation for the implementation steps for the host side is not yet available.

To implement custom vendor-specific commands, you need to modify the NCP sample in the following manner:

  1. Implement a callback for handling custom commands requests. The function must follow the zb_ncp_custom_request_cb_t() declaration. For an example, see ncp_vendor_specific_req_handler() in the sample. This function parses the command payload, validates it, performs required action on LED 2, and sends a response.

  2. Register the handler function using zb_ncp_custom_register_request_cb(), as implemented in the sample. Once the callback is registered, it is called for every custom command request received from the host.

  3. At the end of the custom request callback, implement the response to the request using one of the following options:

    • Implement an immediate response, which is sent just after the request is received and parsed. For this option, make sure that the length of the response is returned from the custom command callback (implemented in step 1) and zb_ncp_custom_response() is called with a buffer that contains both the response payload and the parameters encapsulated in ncp_hl_custom_resp_t.

    • Implement a delayed response, which can be useful for example to implement commands that require more time to complete. For this option, make sure that NCP_RET_LATER is returned from the custom command callback (implemented in step 1) and zb_ncp_custom_response() is called after this callback.

    If the function fails, it must return an error code, while a response is automatically generated by the stack. See ncp_vendor_specific_req_handler() for an example of the immediate response.

  4. Implement custom indications by using zb_ncp_custom_indication() to send an indication to the host. The NCP sample demonstrates the indication usage to inform the host about the index of the LED that is controlled by custom requests. The indication is sent 3 seconds after start-up. See custom_indication() in the sample to see how to pass the data to the indication’s payload.

Once you complete these steps and configure the vendor-specific commands on the host, you can call these commands from the host to use the extended functionalities in the NCP sample.

User interface

All the NCP sample’s interactions with the application are automatically handled using serial or USB communication.

Building and running

Make sure to configure the Zigbee stack before building and testing this sample. See Configuring Zigbee in nRF Connect SDK for more information.

This sample can be found under samples/zigbee/ncp in the nRF Connect SDK folder structure.

See Building and programming an application for information about how to build and program the application.


After building the sample and programming it to your development kit, test it by performing the following steps:

  1. Download and extract the ZBOSS NCP Host package.


    If you are using an Linux distribution different than the 64-bit Ubuntu 18.04, make sure to rebuild the package libraries and applications by following the instructions described in the Rebuilding the ZBOSS libraries for host section in the NCP Host documentation.

  2. If you are using Communication through USB, connect the nRF USB port of the NCP sample’s development kit to the PC USB port with an USB cable.

  3. Get the kit’s serial port name (for example, /dev/ttyACM0). If you are communicating through the nRF USB, get the nRF USB serial port name.

  4. Turn on the development kit that runs the light bulb sample.

  5. Start the simple gateway application by running the following command with serial_port_name replaced with the serial port name used for communication with the NCP sample:

    NCP_SLAVE_PTY=*serial_port_name* ./application/simple_gw/simple_gw

The simple gateway device forms the Zigbee network and opens the network for 180 seconds for new devices to join. When the light bulb joins the network, the LED 3 on the light bulb device turns on to indicate that it is connected to the simple gateway. The gateway then starts discovering the On/Off cluster. When it is found, the simple gateway configures bindings and reporting for the device and then starts sending On/Off toggle commands with a 15-second period that toggle the LED 4 on the light bulb on and off.


This sample uses the following nRF Connect SDK libraries:

  • Zigbee subsystem:

    • zb_nrf_platform.h

This sample uses the following sdk-nrfxlib libraries:

In addition, it uses the following Zephyr libraries: