In this blog, I would share how to create the multiple role concurrently example on nRF5 SDK.  It would cover how to do the multiple peripheral role, single central role to connect multiple peripherals, combo example (2 x peripheral role + 2 x central role) concurrently.  This example is based on the Nordic NRF5 SDK 15.3 and can run on the nRF52832 and nRF52840 chipset.

This example is given to show how to set up the multiple role on Nordic SDK.   If you need to get more details, you may have a way to study the source code directly or ask the question on the Nordic Developer Zone.


Regarding to the classic (BR/EDR) bluetooth, each node can connect up to maximum 7 devices [Link].  It calls the connection in a piconet network.  The devices can switch roles, by agreement, and the slave can become the master.

Regarding to the Bluetooth Low Energy, after the bluetooth 4.1 specification, device has started to support the device to run multiple role (central/peripheral) concurrently.

On the Nordic Softdevice (Bluetooth Stack), S130 / S132 / S140 have started to support the multiple role.  For example, S132v4.x or later has support up to 20 concurrent links in all roles.  For example, if the device acts as central role, it can connect up to 20 peripherals.  Also, if the device can connect multiple mobile at the same time by using peripheral role.

For example, this demo shows the multilink capabilities of the nRF52 Series SoCs and their associated stacks. Both the nRF52840 and the nRF52832 together with the S140 and S132 SoftDevices respectively can support 20 concurrent Bluetooth Low Energy connections.


At the Nordic Playground Github [Link], it shows the demo code how to implement an aggregator node, running on an nRF52DK or an nRF52840 DK.  This aggregator can connect with an Android Host and 19 x peripheral devices (either DK or Thingy) at the same time.


Inside Nordic nRF5 SDK, it has the BLE mult-link central example which uses to connect more BLE Blinky Application as peripherals.

In this example, there are three difference roles.

  • Peripheral role
  • Central role
  • 2 x Peripheral Role + 2 x Central Role

All of them contains the GATT Server / Client.

  • NUS (Nordic UART Service)
  • Image Transfer Service (ITS)
  • BLE Blinky service (LBS)
/* Combo Role */

#define DEVICE_NAME                     "Multi_Role"                         /**< Name of device. Will be included in the advertising data. */

static char const m_target_periph_name[] = "LBS_NUS_Node";     
/**< Name of the device we try to connect to. This name is searched in the scan report data*/
//Inside sdk_config.h,

// <o> NRF_SDH_BLE_PERIPHERAL_LINK_COUNT - Maximum number of peripheral links.

// <o> NRF_SDH_BLE_CENTRAL_LINK_COUNT - Maximum number of central links.

// <o> NRF_SDH_BLE_TOTAL_LINK_COUNT - Total link count.
// <i> Maximum number of total concurrent connections using the default configuration.



  • Peripheral Role — NRF52840 DK / NRF52832 DK
  • Central Role — NRF52840 DK
  • Combo Role — NRF52832 DK
  • IDE Segger Embedded Studio

Source code : https://github.com/jimmywong2003/nrf5-ble-multiple-role-example

The example code is based at the nRF5 SDK 15.3.

GATT Table

The device has included 3 difference services.

  1. Nordic Blinky Service (LBS) (Server and Client)
  2. Nordic UART Service (NUS) (Server and Client)
  3. Image Transfer Service (ITS) (Server and Client)

On the callback of the BLE batch routine, it has two difference routines to handle either peripheral role or central role.

static void ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context)
        ret_code_t err_code;
        // For readability.
        uint16_t conn_handle = p_ble_evt->evt.gap_evt.conn_handle;

        uint16_t role        = ble_conn_state_role(conn_handle);
        ble_gap_evt_t const * p_gap_evt = &p_ble_evt->evt.gap_evt;

        if (    (p_ble_evt->header.evt_id == BLE_GAP_EVT_CONNECTED)
                &&  (is_already_connected(&p_ble_evt->evt.gap_evt.params.connected.peer_addr)))
                NRF_LOG_INFO("%s: Already connected to this device as %s (handle: %d), disconnecting.",
                             (role == BLE_GAP_ROLE_PERIPH) ? "PERIPHERAL" : "CENTRAL",
                             (role == BLE_GAP_ROLE_PERIPH) ? "CENTRAL"    : "PERIPHERAL",

                (void)sd_ble_gap_disconnect(conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);

                // Do not process the event further.

        switch (p_ble_evt->header.evt_id)

                // Assign connection handle to available instance of QWR module.

                m_connected_peers[conn_handle].is_connected = true;
                m_connected_peers[conn_handle].address = p_ble_evt->evt.gap_evt.params.connected.peer_addr;

                // Handle central connections
                if (p_gap_evt->params.connected.role == BLE_GAP_ROLE_PERIPH)
                else if ((p_gap_evt->params.connected.role == BLE_GAP_ROLE_CENTRAL) || (p_ble_evt->header.evt_id == BLE_GAP_EVT_ADV_REPORT))
Peripheral Role Connected
Central Role Connected

This example is just for the proof of concept how to build up the multiple central and peripheral together. I don’t have any code guarantee and support.

if you would like to setup the 2 central + 2 peripheral role to run on the nRF52810, I have the simple example. Please let your message and email to me on such request.

Welcome to give any feedback and comments.

Thanks for your interests on my blog. Since 2019, I have created this blog and shared the idea how to do some funny stuffs. I am very pleasure that I get quite a lot of positive feedback. I really hope that this blog helps your own embedded solution development. May I get support from you to keep it in order to maintain the wordpress host service? Your appreciation would be very helpful.