OyvindRonningstad gravatar image

Posted 2016-04-08 13:42:37 +0200

Migrating to Peer Manager

Migrating to Peer Manager

The tutorial has been updated for SDK v11, which contains the production-ready release of Peer Manager. The original tutorial can be found on this page, below the updated tutorial.

Migrating to Peer Manager (SDK v11)

This version of the Peer Manager requires the S13x SoftDevice v2.0.0. A migration document for this SoftDevice can be found in the SDK at

[sdk]/components/softdevice/s132/doc/s13x_nrf5x_2.0.0_migration_document.pdf

Introduction

As of SDK v10, a new module has been introduced which is able to handle bonds to both central and peripheral devices simultaneously. The following tutorial is intended to serve as a guide for migrating projects from Device Manager to Peer Manager. For more complete information, including an architectural overview and more comprehensive examples of use, please see the Peer Manager section at the Nordic Infocenter.

The guide assumes that Keil µVision is used for development. The guide will use the HRS application as an example, which can be found in the SDK at [sdk]/examples/ble_peripheral/ble_app_hrs.

Add required files and includes

Peer Manager is divided into a number of modules, which must be included for the application to use it. Right click on the nRF_BLE group in the project window. Click Add existing files to group 'nRF_BLE' and add:

  • [sdk]/components/ble/peer_manager/ (all source files)
  • [sdk]/components/ble/common/ble_conn_state.c

Then right click on the nRF_Libraries group in the project window. Click Add existing files to group 'nRF_Libraries' and add:

  • [sdk]/components/libraries/fds/fds.c
  • [sdk]/components/libraries/fstorage/fstorage.c
  • [sdk]/components/libraries/util/sdk_mapped_flags.c

Now go to Project -> Options for target ... -> C/C++. From there, add the following directories to the Include Paths:

  • [sdk]/components/ble/peer_manager/
  • [sdk]/components/libraries/fds
  • [sdk]/components/libraries/fstorage
  • [sdk]/components/libraries/experimental_section_vars

To set up the correct headers, we will first remove those required by Device Manager:

#include "pstorage.h"
#include "device_manager.h"

Then, include the headers required by Peer Manager:

#include "fstorage.h"
#include "fds.h"
#include "peer_manager.h"
#include "ble_conn_state.h"

Initialization

Fstorage

First, we will set up the underlying flash storage module. Device Manager relied on pstorage, while Peer Manager uses the newer fstorage. In sys_evt_dispatch(), remove the call to pstorage_sys_event_handler() and add a call to fs_sys_event_handler() at the same location:

// Forward Softdevice events to the fstorage module
fs_sys_event_handler(sys_evt);

Peer Manager

First, ensure that BLE events are passed to the Peer Manager module. In ble_evt_dispatch, remove the call to dm_ble_evt_handler() and add a call to ble_conn_state_on_ble_evt() and pm_on_ble_evt() at the same location:

// Forward BLE events to the Connection State module.
// This must be called before any event handler that uses this module.
ble_conn_state_on_ble_evt(p_ble_evt);

// Forward BLE events to the Peer Manager
pm_on_ble_evt(p_ble_evt);

The Peer Manager modules are initialized the first time an event handler is registered in each module, which is done by pm_init(). There is no need to access the Peer Manager submodules directly.

Locate the function device_manager_evt_handler(), and replace it with

static void pm_evt_handler(pm_evt_t const * p_evt)
{
    switch(p_evt->evt_id)
    {
        case PM_EVT_BONDED_PEER_CONNECTED:
        case PM_EVT_CONN_SEC_START:
        case PM_EVT_CONN_SEC_SUCCEEDED:
        case PM_EVT_CONN_SEC_FAILED:
        case PM_EVT_CONN_SEC_CONFIG_REQ:
        case PM_EVT_STORAGE_FULL:
        case PM_EVT_ERROR_UNEXPECTED:
        case PM_EVT_PEER_DATA_UPDATE_SUCCEEDED:
        case PM_EVT_PEER_DATA_UPDATE_FAILED:
        case PM_EVT_PEER_DELETE_SUCCEEDED:
        case PM_EVT_PEER_DELETE_FAILED:
        case PM_EVT_PEERS_DELETE_SUCCEEDED:
        case PM_EVT_PEERS_DELETE_FAILED:
        case PM_EVT_LOCAL_DB_CACHE_APPLIED:
        case PM_EVT_LOCAL_DB_CACHE_APPLY_FAILED:
        case PM_EVT_SERVICE_CHANGED_IND_SENT:
        case PM_EVT_SERVICE_CHANGED_IND_CONFIRMED:
        default:
            break;
    }
}

This is a very minimal example, intended to show the different events that can be acted on. How to handle these events will vary between applications, but an example is shown at the Nordic Infocenter.

Replace device_manager_init() with the following function, and remove the m_app_handle variable:

static void peer_manager_init(bool erase_bonds)
{
    ble_gap_sec_params_t sec_param;
    ret_code_t err_code;

    err_code = pm_init();
    APP_ERROR_CHECK(err_code);

    if (erase_bonds)
    {
        err_code = pm_peers_delete();
        APP_ERROR_CHECK(err_code);
    }

    memset(&sec_param, 0, sizeof(ble_gap_sec_params_t));

    // Security parameters to be used for all security procedures.
    sec_param.bond              = SEC_PARAM_BOND;
    sec_param.mitm              = SEC_PARAM_MITM;
    sec_param.lesc              = SEC_PARAM_LESC;
    sec_param.keypress          = SEC_PARAM_KEYPRESS;
    sec_param.io_caps           = SEC_PARAM_IO_CAPABILITIES;
    sec_param.oob               = SEC_PARAM_OOB;
    sec_param.min_key_size      = SEC_PARAM_MIN_KEY_SIZE;
    sec_param.max_key_size      = SEC_PARAM_MAX_KEY_SIZE;
    sec_param.kdist_own.enc     = 1;
    sec_param.kdist_own.id      = 1;
    sec_param.kdist_peer.enc    = 1;
    sec_param.kdist_peer.id     = 1;

    err_code = pm_sec_params_set(&sec_param);
    APP_ERROR_CHECK(err_code);

    err_code = pm_register(pm_evt_handler);
    APP_ERROR_CHECK(err_code);
}

The ble_gap_sec_params_t parameter passed to pm_sec_params_set() is the same as previously passed to pm_register(), and the same settings can be used. Add a line calling peer_manager_init() in the main() function, before you start scanning or advertising.

Further Reading


Migrating to experimental Peer Manager (SDK v10)

Introduction

As of SDK v10, a new module has been introduced which is able to handle bonds to both central and peripheral devices simultaneously. The following tutorial is intended to serve as a guide for migrating projects from Device Manager to Peer Manager. For more complete information, including an architectural overview and more comprehensive examples of use, please see the Peer Manager section at the Nordic Infocenter.

The guide assumes that Keil µVision is used for development. The guide will use the HRS application from SDK 10 as an example, which can be found in the SDK at sdk/Nordic/nrf51/examples/ble_peripheral/ble_app_hrs.

Add required files and includes

Peer Manager is divided into a number of modules, which must be included for the application to use it. Right click on the nRF_BLE group in the project window. Click Add existing files to group 'nRF_BLE' and add:

  • sdk/Nordic/nrf51/components/ble/peer_manager/ (all source files)
  • sdk/Nordic/nrf51/components/ble/common/ble_conn_state.c

Then right click on the nRF_Libraries group in the project window. Click Add existing files to group 'nRF_Libraries' and add:

  • sdk/Nordic/nrf51/components/libraries/fds/fds.c
  • sdk/Nordic/nrf51/components/libraries/fstorage/fstorage.c
  • sdk/Nordic/nrf51/components/libraries/util/sdk_mapped_flags.c

Now go to Project -> Options for target ... -> C/C++. From there, add the following directories to the Include Paths:

  • sdk/Nordic/nrf51/components/ble/peer_manager/
  • sdk/Nordic/nrf51/components/libraries/fds
  • sdk/Nordic/nrf51/components/libraries/fstorage
  • sdk/Nordic/nrf51/components/libraries/experimental_section_vars

To set up the correct headers, we will first remove those required by Device Manager:

#include "pstorage.h"
#include "device_manager.h"

Then, include the headers required by Peer Manager:

#include "fstorage.h"
#include "fds.h"
#include "peer_manager.h"
#include "ble_conn_state.h"

Initialization

Fstorage

First, we will set up the underlying flash storage module. Device Manager relied on pstorage, while Peer Manager uses the newer fstorage. In sys_evt_dispatch(), remove the call to pstorage_sys_event_handler() and add a call to fs_sys_event_handler() at the same location:

// Forward Softdevice events to the fstorage module
fs_sys_event_handler(sys_evt);

Peer Manager

First, ensure that BLE events are passed to the Peer Manager module. In ble_evt_dispatch, remove the call to dm_ble_evt_handler() and add a call to ble_conn_state_on_ble_evt() and pm_ble_evt_handler() at the same location:

// Forward BLE events to the Connection State module.
// This must be called before any event handler that uses this module.
ble_conn_state_on_ble_evt(p_ble_evt);

// Forward BLE events to the Peer Manager
pm_ble_evt_handler(p_ble_evt);

The Peer Manager modules are initialized the first time an event handler is registered in each module, which is done by pm_init(). Therefore, except to register separate event handlers in addition to those registered by Peer Manager, there is no need to access the Peer Manager submodules directly.

Locate the function device_manager_evt_handler(), and replace it with

static void pm_evt_handler(pm_evt_t const * p_evt)
{
    switch(p_evt->evt_id)
    {
        case PM_EVT_BONDED_PEER_CONNECTED:
        case PM_EVT_LINK_SECURED:
        case PM_EVT_LINK_SECURE_FAILED:
        case PM_EVT_STORAGE_FULL:
        case PM_EVT_ERROR_UNEXPECTED:
        case PM_EVT_PEER_DATA_UPDATED:
        case PM_EVT_PEER_DATA_UPDATE_FAILED:
        case PM_EVT_ERROR_LOCAL_DB_CACHE_APPLY:
        case PM_EVT_LOCAL_DB_CACHE_APPLIED:
        case PM_EVT_SERVICE_CHANGED_INDICATION_SENT:
        default:
            break;
    }
}

This is a very minimal example, intended to show the different events that can be acted on. How to handle these events will vary between applications, but an example is shown at the Nordic Infocenter.

Replace device_manager_init() with the following function, and remove the m_app_handle variable:

static void peer_manager_init(bool erase_bonds)
{
    ble_gap_sec_params_t sec_param;
    ret_code_t err_code;

    err_code = pm_init();
    APP_ERROR_CHECK(err_code);

    if (erase_bonds)
    {
        pm_peer_delete_all();
    }

    memset(&sec_param, 0, sizeof(ble_gap_sec_params_t));

    // Security parameters to be used for all security procedures.
    sec_param.bond              = SEC_PARAM_BOND;
    sec_param.mitm              = SEC_PARAM_MITM;
    sec_param.io_caps           = SEC_PARAM_IO_CAPABILITIES;
    sec_param.oob               = SEC_PARAM_OOB;
    sec_param.min_key_size      = SEC_PARAM_MIN_KEY_SIZE;
    sec_param.max_key_size      = SEC_PARAM_MAX_KEY_SIZE;
    sec_param.kdist_periph.enc  = 1;
    sec_param.kdist_periph.id   = 1;
    sec_param.kdist_central.enc = 1;
    sec_param.kdist_central.id  = 1;

    err_code = pm_sec_params_set(&sec_param);
    APP_ERROR_CHECK(err_code);

    err_code = pm_register(pm_evt_handler);
    APP_ERROR_CHECK(err_code);
}

The ble_gap_sec_params_t parameter passed to pm_sec_params_set() is the same as previously passed to pm_register(), and the same settings can be used. Add a line calling peer_manager_init() in the main() function, before you start scanning or advertising.

Further Reading

10 comments

ofpaulus gravatar image

Posted Dec. 30, 2015, 8:44 p.m.

I'm trying to migrate from device_manager, but unfortunatelly it doesn't work, and this is not the only issue for me. The biggest problem is the size of the generated code, after apllying peer manager to template application I saw that code size is about 27 KB. For comparison, size of the template with device_manager takes 15 KB. I'm studying yout product actually and I'm using Keil 5 without license so I can generate only 32KB of code. in my opinion you are going in totally wrong way.

Andrew gravatar image

Posted Jan. 8, 2016, 12:39 a.m.

Paulus, if you need more than 32kB for your application, there are detailed tutorials on how to use Eclipse with GCC and the nRF SDK which allows you to use the full code space of the nRF family for free. While it isn't as straightforward, it is in my experience a far superior option over Keil. Not only is the IDE itself better, but you don't need to pay thousands of USD for a license.

chalecampb gravatar image

Posted Jan. 13, 2016, 7:13 p.m.

While it isn't as straightforward

Here to comment that it is actually very straightforward, especially in Mars, to which the most recent GCC tutorials have been updated. Previously you needed to go into the Eclipse Plugins folder, add processor definitions, etc. Now, it's just

  1. Add new software
  2. Import project
  3. Add code parse options
  4. Add makefile targets
  5. Make and flash

So far, it has been very consistent for us, and we spent far less than 5k/seat in engineering resources to set it up. Also, from a cursory glance, it looks like Keil Serial window does not support Telnet. We have found the RTT additions to nrf_log, which integrates with the Eclipse Terminal view, very useful. Strongly recommend re-evaluating the tooling since the landscape has changed in the past few months.

ZOU gravatar image

Posted Jan. 19, 2016, 3:04 a.m.

Thanks Einar for this guide.

I tried the nRF52 HRS example of nRF5_SDK_11.0.0-2\examples\ble_peripheral\ble_app_hrs\pca10040\s132, which worked well. Besides the updates you listed above, I also removed pstorage (header and code) from the project. The only update needed is in components\ble\ble_advertising\ble_advertising.c, that we do not need to check pstorage access status in ble_advertising_start() any more.

Memory footprint changes

---- Original code using Periheral Device Manager

Total RO  Size (Code + RO Data)                20228 (  19.75kB)
Total RW  Size (RW Data + ZI Data)             10888 (  10.63kB)
Total ROM Size (Code + RO Data + RW Data)      20256 (  19.78kB)

---- Updated code using Peer Manager

Total RO  Size (Code + RO Data)                30060 (  29.36kB)
Total RW  Size (RW Data + ZI Data)             11568 (  11.30kB)
Total ROM Size (Code + RO Data + RW Data)      30104 (  29.40kB)
henry10210 gravatar image

Posted March 27, 2016, 6:10 a.m.

Hello, I am trying to migrate from device manager to peer manager using the latest SDK 11. The documentations have not caught up yet. For example, you said to call pm_ble_evt_handler() in ble_evt_dispatch(), but there is no such function. Instead, there is the sm_ble_evt_handler(), or the smd_ble_evt_handler(). sm_ble_evt_handler() is basically a wrapper around smd_ble_evt_handler, but I have not yet found an explanation of the SDK 11 peer manager API.

rspanton gravatar image

Posted July 13, 2016, 1:18 p.m.

This guide doesn't mention using the FS_REGISTER_CFG as part of the fstorage initialisation. Is this an oversight, or because this initialisation is not required?

The fstorage docs don't go into enough detail to work out what to do with FS_REGISTER_CFG -- particularly what to set the num_pages attribute of the fst_config_t struct. They also don't state whether the FS_REGISTER_CFG call is required at all.

jefcap gravatar image

Posted Aug. 8, 2016, 4:28 p.m.

Does anyone could perform DFU using peer manager?

jpsajin gravatar image

Posted Jan. 17, 2017, 8:24 a.m.

I'm using sdk12.2 which works perfectly ,but the bonding only takes place at first time when the softdevice is burned. When i forgot the device and bond it again it will not bond and get rejection error from nrf52

muhammadakram.karimi gravatar image

Posted Feb. 11, 2017, 12:33 p.m.

Hello, I am using SDK 11.0 and trying to migrate from DM to PM. While following the tutorial; I managed to compile successfully but when I try to connect my mobile phone with nRF52 DK, I get the following error EVT "PM_EVT_PEER_DATA_UPDATE_FAILED".

Here is the sequence of my main function.

ret_code_t err_code;
bool erase_bonds;

 err_code = NRF_LOG_INIT();
APP_ERROR_CHECK(err_code);

NRF_LOG_PRINTF("D App\r\n");

// Initialize.
//timers_init();
 APP_TIMER_INIT(APP_TIMER_PRESCALER, APP_TIMER_OP_QUEUE_SIZE, NULL);
  buttons_leds_init(&erase_bonds);
     if (erase_bonds)
{
    NRF_LOG_PRINTF("Bonds erased!\r\n");
}

ble_stack_init();
//device_manager_init(erase_bonds);
peer_manager_init(erase_bonds);
//db_discovery_init();

gap_params_init();
conn_params_init();
services_init();
advertising_init();

// Start execution.
application_timers_start();
err_code = ble_advertising_start(BLE_ADV_MODE_FAST);
APP_ERROR_CHECK(err_code);

Please help

muhammadakram.karimi gravatar image

Posted Feb. 11, 2017, 12:37 p.m.

Just to add one comment on #sajin comment... I re-burnt the SD132 on nRF52 DK and it started working good. I am not sure why it was not working before.

Sign in to comment.

User menu

    or sign up

Recent questions

Related posts by tag