This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Adding peer manager to multiperipheral example and getting FATAL ERROR

Hi Nordic Team! Blush

I have bought nRF52 DK and my aim is to create BLE application for a peripheral that it would be possible to connect multiple centrals (for example android smartphones) to it. I use SEGGER Embedded Studio for ARM V3.34b 64bit to flash my device with SoftDevice s132_nrf52_6.0.0 and with multiperipheral example from nRF5_SDK_15.0.0_a53641a.

The example has got very limited functionality but I believe this will be my base application to work with. I want to extend and develop it. The first thing I want do add is the pairing and bonding (so using persistent memory).

I followed the guide:

https://devzone.nordicsemi.com/tutorials/b/software-development-kit/posts/migrating-to-peer-manager

and added to nRF_BLE group the following:

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

Added to nRF_Libraries group the following:

  • [sdk]/components/libraries/fds/fds.c
  • [sdk]/components/libraries/fstorage/fstorage.c (nrf_fstorage.c was in the folder, not fstorage.c)
  • [sdk]/components/libraries/util/sdk_mapped_flags.c
  • [sdk]/components/libraries/fstorage/nrf_fstorage_sd.c

I hadn’t to add the directories:

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

because they were already there.

Added:

#include "nrf_fstorage.h"
#include "fds.h"
#include "peer_manager.h"

to main.c file.

 

Then I “borrowed” some functions from Heart Rate Service Sample Application from the same SDK:

 

#define SEC_PARAM_BOND                      1                                       /**< Perform bonding. */
#define SEC_PARAM_MITM                      0                                       /**< Man In The Middle protection not required. */
#define SEC_PARAM_LESC                      0                                       /**< LE Secure Connections not enabled. */
#define SEC_PARAM_KEYPRESS                  0                                       /**< Keypress notifications not enabled. */
#define SEC_PARAM_IO_CAPABILITIES           BLE_GAP_IO_CAPS_NONE                    /**< No I/O capabilities. */
#define SEC_PARAM_OOB                       0                                       /**< Out Of Band data not available. */
#define SEC_PARAM_MIN_KEY_SIZE              7                                       /**< Minimum encryption key size. */
#define SEC_PARAM_MAX_KEY_SIZE              16                                      /**< Maximum encryption key size. */

 

 

static void fds_evt_handler(fds_evt_t const * const p_evt)
{
    if (p_evt->id == FDS_EVT_GC)
    {
        NRF_LOG_DEBUG("GC completed\n");
    }
}

 

static void pm_evt_handler(pm_evt_t const * p_evt)
{
    ret_code_t err_code;

    switch (p_evt->evt_id)
    {
        case PM_EVT_BONDED_PEER_CONNECTED:
        {
            NRF_LOG_INFO("Connected to a previously bonded device.");
        } break;

        case PM_EVT_CONN_SEC_SUCCEEDED:
        {
            NRF_LOG_INFO("Connection secured: role: %d, conn_handle: 0x%x, procedure: %d.",
                         ble_conn_state_role(p_evt->conn_handle),
                         p_evt->conn_handle,
                         p_evt->params.conn_sec_succeeded.procedure);
        } break;

        case PM_EVT_CONN_SEC_FAILED:
        {
            /* Often, when securing fails, it shouldn't be restarted, for security reasons.
             * Other times, it can be restarted directly.
             * Sometimes it can be restarted, but only after changing some Security Parameters.
             * Sometimes, it cannot be restarted until the link is disconnected and reconnected.
             * Sometimes it is impossible, to secure the link, or the peer device does not support it.
             * How to handle this error is highly application dependent. */
        } break;

        case PM_EVT_CONN_SEC_CONFIG_REQ:
        {
            // Reject pairing request from an already bonded peer.
            pm_conn_sec_config_t conn_sec_config = {.allow_repairing = false};
            pm_conn_sec_config_reply(p_evt->conn_handle, &conn_sec_config);
        } break;

        case PM_EVT_STORAGE_FULL:
        {
            // Run garbage collection on the flash.
            err_code = fds_gc();
            if (err_code == FDS_ERR_NO_SPACE_IN_QUEUES)
            {
                // Retry.
            }
            else
            {
                APP_ERROR_CHECK(err_code);
            }
        } break;

        case PM_EVT_PEERS_DELETE_SUCCEEDED:
        {
            NRF_LOG_DEBUG("PM_EVT_PEERS_DELETE_SUCCEEDED");
            advertising_start(); // was advertising_start(false) before
        } break;

        case PM_EVT_PEER_DATA_UPDATE_FAILED:
        {
            // Assert.
            APP_ERROR_CHECK(p_evt->params.peer_data_update_failed.error);
        } break;

        case PM_EVT_PEER_DELETE_FAILED:
        {
            // Assert.
            APP_ERROR_CHECK(p_evt->params.peer_delete_failed.error);
        } break;

        case PM_EVT_PEERS_DELETE_FAILED:
        {
            // Assert.
            APP_ERROR_CHECK(p_evt->params.peers_delete_failed_evt.error);
        } break;

        case PM_EVT_ERROR_UNEXPECTED:
        {
            // Assert.
            APP_ERROR_CHECK(p_evt->params.error_unexpected.error);
        } break;

        case PM_EVT_CONN_SEC_START:
        case PM_EVT_PEER_DATA_UPDATE_SUCCEEDED:
        case PM_EVT_PEER_DELETE_SUCCEEDED:
        case PM_EVT_LOCAL_DB_CACHE_APPLIED:
        case PM_EVT_LOCAL_DB_CACHE_APPLY_FAILED:
            // This can happen when the local DB has changed.
        case PM_EVT_SERVICE_CHANGED_IND_SENT:
        case PM_EVT_SERVICE_CHANGED_IND_CONFIRMED:
        default:
            break;
    }
}

 

 

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

    err_code = pm_init();
    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.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);

    err_code = fds_register(fds_evt_handler);
    APP_ERROR_CHECK(err_code);
}

 

 and added the call:

    peer_manager_init();
  inside main() function.

Then I got into sdk_config.h file and changed some defines:

#define PEER_MANAGER_ENABLED 0 to #define PEER_MANAGER_ENABLED 1

#define FDS_ENABLED 0 to #define FDS_ENABLED 1

#define NRF_FSTORAGE_ENABLED 0 to #define NRF_FSTORAGE_ENABLED 1

 

 and changed 

static void advertising_start(void) to void advertising_start(void)

in main.c file (there was an error during compilation without this change).

 

According to: https://devzone.nordicsemi.com/b/blog/posts/segger-embedded-studio-a-cross-platform-ide

 I have checked the flash_placement.xml but the below lines already were there:

FLASH:  ...

  <ProgramSection alignment="4" keep="Yes" load="Yes" name=".fs_data"  inputsections="*(.fs_data*)" runin=".fs_data_run"/> 

...

RAM:   ...

<ProgramSection alignment="4" keep="Yes" load="No" name=".fs_data_run" address_symbol="__start_fs_data" end_symbol="__stop_fs_data" />

...

 I have imported thumb_crt0.s (to have own copy in project folder, not use the shared one from SDK) and added: 

# ADD HERE ... 
ldr r0, =__fs_data_load_start__
ldr r1, =__fs_data_start__
ldr r2, =__fs_data_end__
bl memory_copy
# TO HERE ...

 

 

 The program compiles and flashed without any error. I am able to connect more than one smartphone to it, so multiconnection works. When I hit "bond" on nRF Connect mobile app I get DC and message on puTTY terminal saying:

<error> app: Fatal error
<warning> app: System reset

 My question is: what have I done wrong or what changes have to be done additionally? I don't know whether the problem is with the peer manager or the flash data storage.

 thanks,
Pawel

  • Update on this error:

    I have set breakpoint inside app_error_handler_bare function in app_error.c file and below there is call stack with error of invalid state.

  • Update number 2 on this error:

    I have added  NRF_LOG_INFO("event nr: %x", p_ble_evt->header.evt_id); and commented below case

     

    /*
     case BLE_GAP_EVT_SEC_PARAMS_REQUEST:
                // Pairing not supported
                err_code = sd_ble_gap_sec_params_reply(p_ble_evt->evt.gap_evt.conn_handle,
                                                       BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP,
                                                       NULL,
                                                       NULL);
                APP_ERROR_CHECK(err_code);
                break;
    */

    inside static void ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context) in main.c. I am able to connect AND bond. Here is the PuTTY log:

    <info> app: Erase bonds!
    <info> app: Multiperipheral example started.
    <info> app: event nr: 10
    <info> app: Connection with link 0x0 established.
    <info> app: event nr: 12
    <info> app: event nr: 12
    <info> app: event nr: 12
    <info> app: event nr: 12
    <info> app: event nr: 13
    <info> app: event nr: 12
    <info> app: event nr: 1A
    <info> app: Connection secured: role: 1, conn_handle: 0x0, procedure: 1.
    <info> app: event nr: 19
    <info> app: event nr: 12
    <info> app: event nr: 12
    

    and for reconnection:

    <info> app: event nr: 11
    <info> app: Connection 0x0 has been disconnected. Reason: 0x13
    <info> app: Connected to a previously bonded device.
    <info> app: event nr: 10
    <info> app: Connection with link 0x1 established.
    <info> app: event nr: 14
    <info> app: Connection secured: role: 1, conn_handle: 0x1, procedure: 0.
    <info> app: event nr: 1A
    

    I don't like how I got no control over this. I mean the case inside the switch isn't supposed to be just commented out, right?

  • Hi Pawel,

    I am sorry, but it seems that you have followed some old blogs about older SDK versions, where SES support wasn't integrated and where you didn't have peer manager. 

     

    It will just cause more trouble and work continuing down that path, so instead I would recommend you to use the (unmodified) BLE MultiPeripheral example as a base then add the Peer Manager as described in the documentation. 

    Example found in [RF5_SDK_15\examples\ble_peripheral\experimental\ble_app_multiperipheral\pca10040\s132\ses]

    -> Remember to enable Peer Manager in sdk_config.h

    // <e> PEER_MANAGER_ENABLED - peer_manager - Peer Manager
    //==========================================================
    #ifndef PEER_MANAGER_ENABLED
    #define PEER_MANAGER_ENABLED 1
    #endif

    -> Then follow the descriptions in the documentation

  • Hi Martin

    Firstly thanks for the response, I was waiting for it. I have just opened fresh unmodified multiperipheral example to work with.

    Secondly the "old blog" I was relying mostly comes from the documentation you have linked. There is a bug in this documentation, I believe: the function is peer_manager_event_handler but peer_manager_init calls pm_evt_handler. But I have added peer_manager_initpm_evt_handler function definitions, security parameters and a call from main function. I have omitted "Storing data" and "Using whitelist" paragraphs. 

    Moreover setting  PEER_MANAGER_ENABLED 1 is not enough, I do also have to set NRF_FSTORAGE_ENABLED 1 and FDS_ENABLED 1 to get rid of compiling errors. 

    I have also added many .c files which I listed in the 1st post.

    Now my project compiles and flashed. I am able to connect masters to it but when I try to pair/bond I get the same Fatal Error and the identical CallStack when I debug this. 

    Maybe if there is no guide without errors and uncertainties you could provide a MultiPeripheral example with already implemented Peer Manager?

    Below I am pasting all the changes I have done to the original project:

    main.c

    sdk_config.h

    ble_app_multiperipheral_pca10040_s132.emProject (with listed all the files and libraries)

    I really need help on this, whitout it I cannot procced.

    thanks in advance

  • Hi Pawel,

    Have you had any progress on this?

     I have added MultiPeripheral example with peer manager added which seem to work.ble_app_multiperipheral - Copy.zip

Related