<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="https://devzone.nordicsemi.com/cfs-file/__key/system/syndication/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>nRF52840 unexpectedly stops scanning</title><link>https://devzone.nordicsemi.com/f/nordic-q-a/51937/nrf52840-unexpectedly-stops-scanning</link><description>Hello, 
 I have a running system constituted of a central and 15 peripherals using nRF52840 devices. The central is set to scan the peripherals for 5 seconds then stop and restart the scanning 30 seconds after and so on. After 5 seconds, the scan callback</description><dc:language>en-US</dc:language><generator>Telligent Community 13</generator><lastBuildDate>Mon, 23 Sep 2019 07:16:51 GMT</lastBuildDate><atom:link rel="self" type="application/rss+xml" href="https://devzone.nordicsemi.com/f/nordic-q-a/51937/nrf52840-unexpectedly-stops-scanning" /><item><title>RE: nRF52840 unexpectedly stops scanning</title><link>https://devzone.nordicsemi.com/thread/211105?ContentTypeID=1</link><pubDate>Mon, 23 Sep 2019 07:16:51 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:fce1348f-32f0-4583-b576-72b8bd2c525f</guid><dc:creator>Vidar Berg</dc:creator><description>&lt;p&gt;Hello,&lt;/p&gt;
&lt;p&gt;It sounds like a&amp;nbsp;reasonable workaround.&amp;nbsp;It&amp;nbsp;would of course have been nice to know the root cause of this. I kept my test running over the weekend but still no failures on my side.&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: nRF52840 unexpectedly stops scanning</title><link>https://devzone.nordicsemi.com/thread/211006?ContentTypeID=1</link><pubDate>Fri, 20 Sep 2019 15:57:43 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:d0d81556-8eca-4c84-a8ec-ba6546736fab</guid><dc:creator>Sandrine</dc:creator><description>&lt;p&gt;Hello Vida,&lt;/p&gt;
&lt;p&gt;We decided internally to reboot the Nordic when it happens. We have not implemented it yet nor tested it. I will come back to you once it will be done. The issue is random and can occur anytime from couple of minutes to days but usually within 3 days.&lt;/p&gt;
&lt;p&gt;Thanks.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: nRF52840 unexpectedly stops scanning</title><link>https://devzone.nordicsemi.com/thread/210883?ContentTypeID=1</link><pubDate>Fri, 20 Sep 2019 09:42:57 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:11b19aec-4fea-4ab4-bbfb-d16bdae48ae9</guid><dc:creator>Vidar Berg</dc:creator><description>&lt;p&gt;Hello,&lt;/p&gt;
&lt;p&gt;I&amp;#39;ve tried to replicate the missing &amp;#39;&lt;span&gt;NRF_BLE_SCAN_EVT_SCAN_TIMEOUT&amp;#39; by modifying the ble_app_uart_c example in SDK 15.2.0/s140 6.1.0 to scan for devices named Temp: (have 9 of those in my office) and with the scan timeout set to 5 seconds. But it has been running for around 48 hours now, and haven&amp;#39;t detected any missed events.&amp;nbsp;Have you had any progress on this?&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;img src="https://devzone.nordicsemi.com/resized-image/__size/320x240/__key/communityserver-discussions-components-files/4/pastedimage1568972279347v1.png" alt=" " /&gt;&lt;/span&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: nRF52840 unexpectedly stops scanning</title><link>https://devzone.nordicsemi.com/thread/209558?ContentTypeID=1</link><pubDate>Fri, 13 Sep 2019 08:50:17 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:b0b0e0f4-79b0-4817-a866-de074c1029ad</guid><dc:creator>Vidar Berg</dc:creator><description>&lt;p&gt;Sorry for the delay.&amp;nbsp;I&amp;#39;ve briefly discussed the issue with our Softdevice team and it does not appear to be a known issue at least. So I&amp;#39;m not sure if it makes sense to update the Softdevice since you are on v6.1.0 already. But remember to increase the application&amp;#39;s start address by 0x1000 if you want to give s140 v.7.0.1 a try. I will continue to investigate this here.&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: nRF52840 unexpectedly stops scanning</title><link>https://devzone.nordicsemi.com/thread/209201?ContentTypeID=1</link><pubDate>Wed, 11 Sep 2019 13:35:48 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:51196587-5b66-43fb-98a9-05c39388bbed</guid><dc:creator>Sandrine</dc:creator><description>&lt;p&gt;Indeed it is strange that no error is reported after attempting to re-start the scan. We are using softdevice version s140 v6.1.0. I saw there are 2 new releases after that one: s140 v6.1.1 and s140 v7.0.1. Would you advise to upgrade to s140 v7.0.1?&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: nRF52840 unexpectedly stops scanning</title><link>https://devzone.nordicsemi.com/thread/209177?ContentTypeID=1</link><pubDate>Wed, 11 Sep 2019 12:49:55 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:64969c7f-373e-4da2-9ad9-a3e59425b7b2</guid><dc:creator>Vidar Berg</dc:creator><description>&lt;p&gt;Hello,&lt;/p&gt;
&lt;p&gt;I&amp;nbsp;can&amp;#39;t see anything wrong with the code and It&amp;#39;s strange that scan starts without any errors. Are you using s140 v6.1.1? If not, please try it and see if it makes any differences. It does not seem to have any bug fixes directly related to this but found this in the release notes for s140 6.1.0:&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&lt;em&gt;Fixed an issue where the source of the timeout event might be set to BLE_GAP_TIMEOUT_SRC_CONN instead of BLE_GAP_TIMEOUT_SRC_SCAN when the scanner times out (DRGN-10000).&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;/em&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: nRF52840 unexpectedly stops scanning</title><link>https://devzone.nordicsemi.com/thread/209010?ContentTypeID=1</link><pubDate>Tue, 10 Sep 2019 15:12:59 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:c329cc20-d7b2-4193-a698-f9086e6693cb</guid><dc:creator>Sandrine</dc:creator><description>&lt;p&gt;Hello,&lt;/p&gt;
&lt;p&gt;Thanks for your answer.&lt;/p&gt;
&lt;p&gt;Indeed, here is part of the ble_task:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;
#define BLE_TASK_STACK_SIZE           512u
#define BLE_TASK_QUEUE_SIZE           200u
#define BLE_IDLE_TIMEOUT              120000 // 2 minutes idle timeout

int BleTask_Init(void)
{
  int err;

  // Initialzie and start BLE driver
  err = BleDriver_Init(BLE_DEVICE_NAME_TRANSCEIVER);

  DBGPRINTF(&amp;quot;BleDriver_init: %d&amp;quot;, err);

  TimerCreateOneShot(&amp;amp;idleTimer, BLE_IDLE_TIMEOUT, (TimerCallbackT)IdleTimerCallback);
  TimerCreatePeriodic( &amp;amp;bleSweepTestTimer, BLE_SWEEP_INTERVAL_MS, (TimerCallbackT)BleSweepTestCallback );

  BleDriver_SetCallback( BleCallback, NULL );

  QueueCreate(&amp;amp;bleTaskMessageQueue, /* address of the message queue */
              BLE_TASK_QUEUE_SIZE); /* number of messages allowed */

  TaskCreate( &amp;amp;bleTask,             /* address of task control block */
              &amp;quot;bleTask&amp;quot;,            /* Task name */
              &amp;amp;BleTask_Run,         /* Task &amp;quot;Run&amp;quot; function */
              NULL,
              bleTask_Stk,          /* base of the stack */
              BLE_TASK_STACK_SIZE,  /* stack size in TaskT */
              BLE_TASK_PRIORITY);   /* priority */

  SemaphoreCreate( &amp;amp;sema );

  return 0;
}

QueueT* BleTask_GetMessageQueue(void)
{
  return &amp;amp;bleTaskMessageQueue;
}

static void BleTask_Run(void* pArg)
{
  UNUSED(pArg);

  while (1)
  {
    // Run task core
    BleTask_RunCore();
  }
}

static void StartAdvertising(void)
{
  // Check if we need to stop current advertising
  if( receivedAdvertisingInfo == true )
  {
    receivedAdvertisingInfo = false;
    if( advertisingStarted == true )
    {
      BlePeripheralDriver_StopAdvertising();
      int err = BlePeripheralDriver_StopAdvertising();
      if (err &amp;lt; 0)
      {
         DBGPRINTF(&amp;quot;BLE Task - Stopping Advertizing in StartAdvertizing failed with err %d&amp;quot;, err);
      }
      advertisingStarted = false;
    }
  }

  // Check if we can start/re-start advertising
  if( (advertisingStarted == false) &amp;amp;&amp;amp; (isBlePeripheralEnabled == true) )
  {
    int err;
    // Start advertising
    err = BlePeripheralDriver_StartAdvertising((void*)&amp;amp;manufacturerData, sizeof(manufacturerData));

    if ( err == 0 )
    {
      // Mark advertising as started
      advertisingStarted = true;
    }
    else
    {
      DBGPRINTF(&amp;quot;BLE Task - Start Advertizing failed with err %d&amp;quot;, err);
    }
  }
}

void BleTask_RunCore(void)
{
  int msgSize = 0;
  InterTaskMsg* msg = 0;

  // Wait for message
  msg = (InterTaskMsg*)QueueWait(&amp;amp;bleTaskMessageQueue, &amp;amp;msgSize, true, 0);

  // Process inter task message
  if( msg != 0 )
  {
    HandleInterTaskMsg( msg );
    MsgFree( &amp;amp;msg-&amp;gt;base );
  }

  // Start advertising if enabled.
  StartAdvertising();

}

static void HandleInterTaskMsg( InterTaskMsg* msg )
{
  switch( msg-&amp;gt;base.id )
  {
    case INTER_TASK_BLE_START_SCAN_ID:
      HandleScan( msg );
    break;

    case INTER_TASK_BLE_CONNECT_REQUEST_ID:
      HandleConnect( msg );
    break;

    case INTER_TASK_BLE_DISCONNECT_REQUEST_ID:
      HandleDisconnect( msg );
    break;

    case INTER_TASK_BLE_TO_PERIPHERAL_DATA_ID:
      HandleSendDataToPeripheralRequest( msg );
    break;

    case INTER_TASK_BLE_TO_CENTRAL_DATA_ID:
      HandleSendDataToCentralRequest( msg );
    break;

    case INTER_TASK_BLE_START_ADVERTISING_ID:
      HandleStartAdvertisingRequest(msg);
    break;

    case INTER_TASK_BLE_STOP_ADVERTISING_ID:
      HandleStopAdvertisingRequest(msg);
    break;

    case INTER_TASK_BLE_TRANSCEIVER_CHARACTERISTICS_ID:
      HandleBleTransceiverCharacteristics(msg);
    break;

    case INTER_TASK_BLE_DISABLE_ID:
    {
      // NOTE: Once bLE is disabled, there is no way to re-enable it
      isBleEnabled = false;
    }
    break;


    case INTER_TASK_BLE_TEST_STOP_ID:
    {
      HandleBleTestStop();
    }
    break;


    default:
      DBGPRINTF(&amp;quot;BLE Task - Unknown message ID&amp;quot;);
    break;
  }
}

static void BleCallback(enum BleEventId eventId, uint8_t* peerAddress, void* eventData, void* arg)
{
  UNUSED( arg );

  switch( eventId )
  {
    case BLE_CONNECTION_EVENT:
    {
      ProcessConnectionEvent( peerAddress, eventData );
    }
    break;

    case BLE_SCAN_COMPLETED_EVENT:
    {
      ProcessScanCompleteEvent();
    }
    break;

    case BLE_DATA_LINK_READY_EVENT:
    {
      ProcessDataLinkReadyEvent( peerAddress );
    }
    break;

    case BLE_DATA_RECEIVED_EVENT:
    {
      ProcessDataReceivedEvent( peerAddress, eventData );
    }
    break;

    case BLE_DATA_SENT_EVENT:
    {
      ProcessDataSentEvent();
    }
    break;

    case BLE_DEVICE_DISCOVERY_EVENT:
    {
        if( eventData != NULL )
        {
          ProcessDiscoveryEvent( peerAddress, eventData );
        }
    }
    break;

    case BLE_TCVR_CHAR_WRITE_EVENT:
    {
      if (eventData != NULL)
      {
        ProcessTcvrCharWriteEvent((BleTcvrCharacteristics*)eventData);
      }
    }
  }
}

static void HandleScan( InterTaskMsg* msg )
{
  UNUSED( msg );
  DBGPRINTF( &amp;quot;BLE Scan Starting\r\n&amp;quot; );
  int err = BleCentralDriver_StartScan(BLE_DEVICE_NAME_BELTPACK);
  if(err != 0)
  {
    DBGPRINTF( &amp;quot;BLE Scan FAILED with error : %d\r\n&amp;quot;, err );
  }
}

static void HandleConnect( InterTaskMsg* msg )
{
  int err = BleCentralDriver_Connect(&amp;amp;msg-&amp;gt;payload.peerAddress[0]);
  if( err != 0 )
  {
    isCentralConnected = false;
    DBGPRINTF( &amp;quot;BLE Error connecting, error %d \r\n&amp;quot;, err );
  }
  else
  {
    isCentralConnected = true;
    memcpy(&amp;amp;centralConnectionAddress, &amp;amp;msg-&amp;gt;payload.peerAddress[0], sizeof(blePeerAddress_t));
  }
}

static void HandleDisconnect( InterTaskMsg* msg )
{
  int err = BleCentralDriver_Disconnect(&amp;amp;msg-&amp;gt;payload.peerAddress[0]) ;
  if( err != 0 )
  {
    DBGPRINTF( &amp;quot;BLE Error disconnecting error %d\r\n&amp;quot;, err );
  }
  if( memcmp( &amp;amp;msg-&amp;gt;payload.peerAddress[0], &amp;amp;centralConnectionAddress[0], sizeof(blePeerAddress_t) ) == 0 )
  {
    // Now disconnected from the previous connection
    isCentralConnected = false;
  }
}

static void HandleSendDataToPeripheralRequest( InterTaskMsg* msg )
{
  if( msg-&amp;gt;payload.bleData.dataLength &amp;lt;= CONTROL_BLE_MAX_PAYLOAD_LEN )
  {
    while(BleCentralDriver_SendData(&amp;amp;msg-&amp;gt;payload.bleData.peerAddress[0], &amp;amp;msg-&amp;gt;payload.bleData.data[0], msg-&amp;gt;payload.bleData.dataLength) == -EBUSY)
    {
      txBusy = true;
      if( SemaphoreWait( &amp;amp;sema, true, 5000 ) == -ETIMEDOUT )
      {
        txBusy = false;
        DBGPRINTF(&amp;quot;BLE Task - Timeout sending data\r\n&amp;quot;);
        int err = BleCentralDriver_Disconnect(&amp;amp;msg-&amp;gt;payload.peerAddress[0]);
        if (err != 0)
        {
          DBGPRINTF(&amp;quot;BLE Task - FAILED TO DISCONNECT HandleSendDataToCentralRequest %d&amp;quot;, err);
        }
        break;
      }
    }
  }
  else
  {
    DBGPRINTF( &amp;quot;BLE Task - Invalid payload length: %u\r\n&amp;quot;, msg-&amp;gt;payload.bleData.dataLength );
  }
}

static void HandleSendDataToCentralRequest( InterTaskMsg* msg )
{
  if( dataLinkReady == true )
  {
    if( msg-&amp;gt;payload.bleData.dataLength &amp;lt;= CONTROL_BLE_MAX_PAYLOAD_LEN )
    {
      while(BlePeripheralDriver_SendData(&amp;amp;msg-&amp;gt;payload.bleData.data[0], msg-&amp;gt;payload.bleData.dataLength) == -EBUSY)
      {
        txBusy = true;
        if( SemaphoreWait( &amp;amp;sema, true, 5000 ) == -ETIMEDOUT )
        {
          isConnected = false;
          dataLinkReady = false;
          txBusy = false;
          DBGPRINTF(&amp;quot;BLE Task - Timeout sending data\r\n&amp;quot;);
          int err = BlePeripheralDriver_Disconnect();
          if (err &amp;lt; 0)
          {
            DBGPRINTF(&amp;quot;BLE Task - FAILED TO DISCONNECT HandleSendDataToCentralRequest&amp;quot;);
          }
          break;
        }
      }
    }
    else
    {
      DBGPRINTF( &amp;quot;BLE Task - Invalid payload length: %u\r\n&amp;quot;, msg-&amp;gt;payload.bleData.dataLength );
    }
  }
}

static void HandleStartAdvertisingRequest( InterTaskMsg* msgs )
{
  DBGPRINTF(&amp;quot;BLE Processing BLE Start Advertising&amp;quot;);
  isBlePeripheralEnabled = true;

  manufacturerData.systemId = msgs-&amp;gt;payload.advertising.systemId;
  memcpy(manufacturerData.systemName, msgs-&amp;gt;payload.advertising.systemName, CONTROL_MAX_SYSTEM_NAME);
  manufacturerData.standalone = msgs-&amp;gt;payload.advertising.standalone;
  manufacturerData.openForRegistration = msgs-&amp;gt;payload.advertising.openForRegistration;

  receivedAdvertisingInfo = true;

}

static void HandleStopAdvertisingRequest( InterTaskMsg* msgs )
{
  DBGPRINTF(&amp;quot;BLE Processing BLE Stop Advertising&amp;quot;);
  isBlePeripheralEnabled = false;

  if (advertisingStarted == true)
  {
    BlePeripheralDriver_StopAdvertising();
    advertisingStarted = false;
  }
}

static void HandleBleTransceiverCharacteristics( InterTaskMsg* msg )
{
  int result;
  BleTcvrCharacteristics tcvrChars;
  if (!tcvrServiceStarted)
  {
    result = BlePeripheralDriver_StartTcvrService();
    if (result != 0)
    {
      SCtrlInterfaceTask_Trace(&amp;quot;BlePeripheralDriver_StartTcvrService failed %d&amp;quot;, result);
    }
    else
    {
      tcvrServiceStarted = true;
    }
  }

  tcvrChars.presenceFlags = msg-&amp;gt;payload.bleTcvrCharacteristics.presenceFlags;
  tcvrChars.channel1 = msg-&amp;gt;payload.bleTcvrCharacteristics.channel1;
  tcvrChars.channel2 = msg-&amp;gt;payload.bleTcvrCharacteristics.channel2;
  tcvrChars.ipAddress = msg-&amp;gt;payload.bleTcvrCharacteristics.ipAddress;
  memcpy(tcvrChars.name, msg-&amp;gt;payload.bleTcvrCharacteristics.name, sizeof(tcvrChars.name));
  result = BlePeripheralDriver_UpdateTcvrCharacteristics(&amp;amp;tcvrChars);
  if (result != 0)
  {
    SCtrlInterfaceTask_Trace(&amp;quot;BlePeripheralDriver_UpdateTcvrCharacteristics failed %d&amp;quot;, result);
  }
}


static void ProcessDiscoveryEvent( uint8_t* peerAddress, struct BleDeviceDiscoveryData* discoveryEventData )
{
  if( (peerAddress != NULL) &amp;amp;&amp;amp; (discoveryEventData != NULL) )
  {
    if(!discoveryEventData-&amp;gt;manufacturerData.beltpack.upgradeRefused)
    {
      InterTaskMsg* pInterTaskMsg = (InterTaskMsg*)MsgAlloc( sizeof(InterTaskMsg) );
      if( pInterTaskMsg != NULL )
      {
        pInterTaskMsg-&amp;gt;base.id = INTER_TASK_BLE_DEVICE_DISCOVERY_REPORT_ID;
        pInterTaskMsg-&amp;gt;payload.discoveryReport.rssi = discoveryEventData-&amp;gt;rssi;
        memcpy( &amp;amp;pInterTaskMsg-&amp;gt;payload.discoveryReport.peerAddress[0], peerAddress, CONTROL_BLE_MAX_PAYLOAD_LEN );
        pInterTaskMsg-&amp;gt;payload.discoveryReport.serialNumber = discoveryEventData-&amp;gt;manufacturerData.beltpack.serialNumber;
        pInterTaskMsg-&amp;gt;payload.discoveryReport.systemId = discoveryEventData-&amp;gt;manufacturerData.beltpack.systemId;
        pInterTaskMsg-&amp;gt;payload.discoveryReport.versionMajor = discoveryEventData-&amp;gt;manufacturerData.beltpack.versionMajor;
        pInterTaskMsg-&amp;gt;payload.discoveryReport.versionMinor = discoveryEventData-&amp;gt;manufacturerData.beltpack.versionMinor;
        pInterTaskMsg-&amp;gt;payload.discoveryReport.versionRev = discoveryEventData-&amp;gt;manufacturerData.beltpack.versionRev;

        DBGPRINTF( &amp;quot;Device Discovery: %d %04x%08x %08X %08X %d %d %d\r\n&amp;quot;,
            discoveryEventData-&amp;gt;rssi,
            *((uint16_t*)(&amp;amp;peerAddress[4])),
            *((uint32_t*)&amp;amp;peerAddress[0]),
            discoveryEventData-&amp;gt;manufacturerData.beltpack.serialNumber,
            discoveryEventData-&amp;gt;manufacturerData.beltpack.systemId,
            discoveryEventData-&amp;gt;manufacturerData.beltpack.versionMajor,
            discoveryEventData-&amp;gt;manufacturerData.beltpack.versionMinor,
            discoveryEventData-&amp;gt;manufacturerData.beltpack.versionRev
        );

        if( !QueuePost(SCtrlInterfaceTask_GetMessageQueue(), pInterTaskMsg, sizeof(*pInterTaskMsg)) )
        {
          MsgFree( &amp;amp;pInterTaskMsg-&amp;gt;base );
          DBGPRINTF( &amp;quot;BLE Task : Error, Unable to post on Slave task\r\n&amp;quot; );
        }
      }
    }
    else
    {
      DBGPRINTF( &amp;quot;Upgrade refuse on discovered device: %d %04x%08x %08X %08X %d %d %d\r\n&amp;quot;,
          discoveryEventData-&amp;gt;rssi,
          *((uint16_t*)(&amp;amp;peerAddress[4])),
          *((uint32_t*)&amp;amp;peerAddress[0]),
          discoveryEventData-&amp;gt;manufacturerData.beltpack.serialNumber,
          discoveryEventData-&amp;gt;manufacturerData.beltpack.systemId,
          discoveryEventData-&amp;gt;manufacturerData.beltpack.versionMajor,
          discoveryEventData-&amp;gt;manufacturerData.beltpack.versionMinor,
          discoveryEventData-&amp;gt;manufacturerData.beltpack.versionRev
      );
    }
  }
}

static void ProcessScanCompleteEvent( void )
{
  InterTaskMsg* pInterTaskMsg = (InterTaskMsg*)MsgAlloc( sizeof(InterTaskMsg) );
  if( pInterTaskMsg != NULL )
  {
    // Fill the message
    pInterTaskMsg-&amp;gt;base.id = INTER_TASK_BLE_SCAN_COMPLETED_EVENT_ID;

    // Post the message
    if( !QueuePost(SCtrlInterfaceTask_GetMessageQueue(), pInterTaskMsg, sizeof(*pInterTaskMsg)) )
    {
      MsgFree( &amp;amp;pInterTaskMsg-&amp;gt;base );
      DBGPRINTF( &amp;quot;BLE Task : Error, Unable to post on Slave task\r\n&amp;quot; );
      return;
    }

    DBGPRINTF( &amp;quot;BLE Scan Completed\r\n&amp;quot; );
  }
}

static void ProcessConnectionEvent( uint8_t* peerAddress, struct BleConnectionEventData* connectionEventData )
{
  if ( connectionEventData != NULL )
  {
    InterTaskMsg* pInterTaskMsg = (InterTaskMsg*)MsgAlloc( sizeof(InterTaskMsg) );
    if( pInterTaskMsg != NULL )
    {
      if (peerAddress == NULL)
      {
        // We are a peripheral connected to a central device.
        if( connectionEventData-&amp;gt;connected == true )
        {
          TimerStart(&amp;amp;idleTimer);
          isConnected = true;
          advertisingStarted = false;
          int err = BlePeripheralDriver_StopAdvertising();
          if (err &amp;lt; 0)
          {
              DBGPRINTF(&amp;quot;BLE Task - Stopping Advertizing in HandleStopAdvertisingRequest failed with err %d&amp;quot;, err);
          }
          else
          {
            DBGPRINTF(&amp;quot;BLE Connected&amp;quot;);
          }
        }
        else
        {
          TimerStop(&amp;amp;idleTimer);
          isConnected = false;
          dataLinkReady = false;
          DBGPRINTF(&amp;quot;BLE Disconnected&amp;quot;);

          // Re-start advertising
          StartAdvertising();
        }
        memset( &amp;amp;pInterTaskMsg-&amp;gt;payload.peerAddress[0], 0, BLE_GAP_ADDR_LEN );
      }
      else
      {
        if( connectionEventData-&amp;gt;connected == true )
        {
          DBGPRINTF( &amp;quot;BLE Connected to: %04x%08x\r\n&amp;quot;, *((uint16_t*)(&amp;amp;peerAddress[4])),*((uint32_t*)&amp;amp;peerAddress[0]) );
        }
        else
        {
          DBGPRINTF( &amp;quot;BLE Disconnected from: %04x%08x\r\n&amp;quot;, *((uint16_t*)(&amp;amp;peerAddress[4])),*((uint32_t*)&amp;amp;peerAddress[0]) );
        }
        memcpy( &amp;amp;pInterTaskMsg-&amp;gt;payload.peerAddress[0], peerAddress, BLE_GAP_ADDR_LEN );
      }

       // Fill the message
      if( connectionEventData-&amp;gt;connected == true )
      {
        pInterTaskMsg-&amp;gt;base.id = INTER_TASK_BLE_DEVICE_CONNECTED_EVENT_ID;
        DBGPRINTF( &amp;quot;BLE Task : Sending  INTER_TASK_BLE_DEVICE_CONNECTED_EVENT_ID\r\n&amp;quot; );
      }
      else
      {
        pInterTaskMsg-&amp;gt;base.id = INTER_TASK_BLE_DEVICE_DISCONNECTED_EVENT_ID;
        DBGPRINTF( &amp;quot;BLE Task : Sending  INTER_TASK_BLE_DEVICE_DISCONNECTED_EVENT_ID\r\n&amp;quot; );

        // If we get disconnected during a transfer we need to signal the semaphore
        if( txBusy == true )
        {
          txBusy = false;
          SemaphoreSignal( &amp;amp;sema );
        }
      }

      // Post the message
      if( !QueuePost(SCtrlInterfaceTask_GetMessageQueue(), pInterTaskMsg, sizeof(*pInterTaskMsg)) )
      {
        MsgFree( &amp;amp;pInterTaskMsg-&amp;gt;base );
        DBGPRINTF( &amp;quot;BLE Task : Error, Unable to post on Slave task\r\n&amp;quot; );
      }
    }
  }
}

static void ProcessDataLinkReadyEvent( uint8_t* peerAddress )
{
  InterTaskMsg* pInterTaskMsg = (InterTaskMsg*)MsgAlloc( sizeof(InterTaskMsg) );
  if( pInterTaskMsg != NULL )
  {
    // Fill the message
    pInterTaskMsg-&amp;gt;base.id = INTER_TASK_BLE_DEVICE_DATA_LINK_READY_EVENT_ID;
    if (peerAddress == NULL)
    {
      TimerStart(&amp;amp;idleTimer);
      dataLinkReady = true;
      memset( &amp;amp;pInterTaskMsg-&amp;gt;payload.peerAddress[0], 0, BLE_GAP_ADDR_LEN );
      DBGPRINTF( &amp;quot;BLE Data link ready with central&amp;quot;);
    }
    else
    {
      memcpy( &amp;amp;pInterTaskMsg-&amp;gt;payload.peerAddress[0], peerAddress, BLE_GAP_ADDR_LEN );
      DBGPRINTF( &amp;quot;BLE Data link ready with: %04x%08x\r\n&amp;quot;, *((uint16_t*)(&amp;amp;peerAddress[4])),*((uint32_t*)&amp;amp;peerAddress[0]) );
    }

    // Post the message
    if( !QueuePost(SCtrlInterfaceTask_GetMessageQueue(), pInterTaskMsg, sizeof(*pInterTaskMsg)) )
    {
      MsgFree( &amp;amp;pInterTaskMsg-&amp;gt;base );
      DBGPRINTF( &amp;quot;BLE Task : Error, Unable to post on Slave task\r\n&amp;quot; );
      return;
    }
  }
}

static void ProcessDataReceivedEvent( uint8_t* peerAddress, struct BleDataReceivedEventData* receivedEventData )
{
  if( receivedEventData != NULL )
  {
    InterTaskMsg* pInterTaskMsg = (InterTaskMsg*)MsgAlloc( sizeof(InterTaskMsg) );
    if( pInterTaskMsg != NULL )
    {
      // Fill the message
      if (peerAddress)
      {
        pInterTaskMsg-&amp;gt;base.id = INTER_TASK_BLE_FROM_PERIPHERAL_DATA_ID;
        memcpy( &amp;amp;pInterTaskMsg-&amp;gt;payload.bleData.peerAddress[0], peerAddress, BLE_GAP_ADDR_LEN );
      }
      else
      {
        DBGPRINTF(&amp;quot;Received DATA from central&amp;quot;);
        pInterTaskMsg-&amp;gt;base.id = INTER_TASK_BLE_FROM_CENTRAL_DATA_ID;
        memset( &amp;amp;pInterTaskMsg-&amp;gt;payload.bleData.peerAddress[0], 0, BLE_GAP_ADDR_LEN );
        TimerStart(&amp;amp;idleTimer);
      }

      pInterTaskMsg-&amp;gt;payload.bleData.dataLength = receivedEventData-&amp;gt;length;
      memcpy( &amp;amp;pInterTaskMsg-&amp;gt;payload.bleData.data[0], receivedEventData-&amp;gt;data, receivedEventData-&amp;gt;length );

      // Post the message
      if( !QueuePost(SCtrlInterfaceTask_GetMessageQueue(), pInterTaskMsg, sizeof(*pInterTaskMsg)) )
      {
        MsgFree( &amp;amp;pInterTaskMsg-&amp;gt;base );
        DBGPRINTF( &amp;quot;BLE Task : Error, Unable to post on Slave task\r\n&amp;quot; );
        return;
      }
    }
  }
}

static void ProcessDataSentEvent( void )
{
  
  if( txBusy == true )
  {
    txBusy = false;
    DBGPRINTF( &amp;quot;BLE Task : Data send evt busy\r\n&amp;quot; );
    SemaphoreSignal( &amp;amp;sema );
  }
}

static void ProcessTcvrCharWriteEvent(BleTcvrCharacteristics* eventData)
{
  InterTaskMsg* pInterTaskMsg = (InterTaskMsg*)MsgAlloc( sizeof(InterTaskMsg) );
  if( pInterTaskMsg != NULL )
  {
    DBGPRINTF(&amp;quot;ProcessTcvrCharWriteEvent&amp;quot;);
    pInterTaskMsg-&amp;gt;base.id = INTER_TASK_BLE_TRANSCEIVER_CHARACTERISTICS_ID;

    pInterTaskMsg-&amp;gt;payload.bleTcvrCharacteristics.presenceFlags = eventData-&amp;gt;presenceFlags;
    pInterTaskMsg-&amp;gt;payload.bleTcvrCharacteristics.channel1 = eventData-&amp;gt;channel1;
    pInterTaskMsg-&amp;gt;payload.bleTcvrCharacteristics.channel2 = eventData-&amp;gt;channel2;
    pInterTaskMsg-&amp;gt;payload.bleTcvrCharacteristics.ipAddress = eventData-&amp;gt;ipAddress;
    memcpy(pInterTaskMsg-&amp;gt;payload.bleTcvrCharacteristics.name, eventData-&amp;gt;name,
    sizeof(pInterTaskMsg-&amp;gt;payload.bleTcvrCharacteristics.name));
    // Post the message
    if( !QueuePost(SCtrlInterfaceTask_GetMessageQueue(), pInterTaskMsg, sizeof(*pInterTaskMsg)) )
    {
      MsgFree( &amp;amp;pInterTaskMsg-&amp;gt;base );
      DBGPRINTF( &amp;quot;BLE Task : Error, Unable to post on Slave task\r\n&amp;quot; );
      return;
    }
    TimerStart(&amp;amp;idleTimer);
  }
}


static void IdleTimerCallback(void)
{
  // Kill the connection if still connected
  if(isConnected)
  {
    isConnected = false;
    dataLinkReady = false;
    int err = BlePeripheralDriver_Disconnect();
   if (err &amp;lt; 0)
    {
      DBGPRINTF(&amp;quot;BLE Task - FAILED TO DISCONNECT LINK&amp;quot;);
    }
  }
}


&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Here is the part of the ble_driver&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;#define APP_ADV_INTERVAL                    300                                     /**&amp;lt; The advertising interval (in units of 0.625 ms. This value corresponds to 187.5 ms). */
#define APP_ADV_DURATION                    0                                       /**&amp;lt; The advertising duration in units of 10 milliseconds (0 = no timeout). */

#define DEFAULT_CONN_INTERVAL               MSEC_TO_UNITS(BLE_CONNECTION_INTERVAL, UNIT_1_25_MS)
#define MIN_CONN_INTERVAL                   (uint16_t)(MSEC_TO_UNITS(7.5, UNIT_1_25_MS))    /**&amp;lt; Minimum acceptable connection interval, in units of 1.25 ms. */
#define MAX_CONN_INTERVAL                   (uint16_t)(MSEC_TO_UNITS(500, UNIT_1_25_MS))    /**&amp;lt; Maximum acceptable connection interval, in units of 1.25 ms. */
#define CONN_SUP_TIMEOUT                    (uint16_t)(MSEC_TO_UNITS(4000,  UNIT_10_MS))    /**&amp;lt; Connection supervisory timeout (4 seconds). */
#define SLAVE_LATENCY                       0                                               /**&amp;lt; Slave latency. */


#define BLE_DVR_DEBUG_PRINT                 1

enum BleDriverConnectionStatus
{
  BLE_DISCONNECTED,
  BLE_CONNECTING,
  BLE_CONNECTED,
};

struct BleDriverCallbackData
{
  BleDriver_Callback cb;
  void* arg;
} callbackData;

struct BleDriverConnectionMap
{
  ble_gap_addr_t gapAddr;
  uint16_t connectionHandle;
  ble_gap_conn_params_t connectionParams;
  enum BleDriverConnectionStatus status;
  bool dataLinkReady;
};

NRF_BLE_GATT_DEF(gattInstance);
NRF_BLE_QWR_DEF(qwrInstance);
NRF_BLE_SCAN_DEF(scanInstance);
BLE_DB_DISCOVERY_DEF(dbDiscoveryInstance);
static nrf_ble_spes_t spesInstance;
NRF_SDH_BLE_OBSERVER(spesBleObserver, BLE_SPES_BLE_OBSERVER_PRIO, nrf_ble_spes_on_ble_evt, &amp;amp;spesInstance);
static nrf_ble_spes_c_t specInstance;
NRF_SDH_BLE_OBSERVER(specBleObserver, BLE_SPES_C_BLE_OBSERVER_PRIO, nrf_ble_spes_c_on_ble_evt, &amp;amp;specInstance);
static ble_tcvr_t tcvrInstance;
NRF_SDH_BLE_OBSERVER(tcvrBleObserver, TCVR_BLE_OBSERVER_PRIO, ble_tcvr_on_ble_evt, &amp;amp;tcvrInstance);

static ble_gap_scan_params_t scanParams =
{
    .active        = 0x01,
    .interval      = NRF_BLE_SCAN_SCAN_INTERVAL,
    .window        = NRF_BLE_SCAN_SCAN_WINDOW,
    .filter_policy = BLE_GAP_SCAN_FP_ACCEPT_ALL,
    .timeout       = NRF_BLE_SCAN_SCAN_DURATION,
    .scan_phys     = BLE_GAP_PHY_1MBPS,
};
static const ble_gap_conn_params_t defaultConnectionParams =
{
    .min_conn_interval = MIN_CONN_INTERVAL,   // Minimum connection interval.
    .max_conn_interval = MAX_CONN_INTERVAL,   // Maximum connection interval.
    .slave_latency     = SLAVE_LATENCY,       // Slave latency.
    .conn_sup_timeout  = CONN_SUP_TIMEOUT     // Supervisory timeout.
};
static bool scanInProgress;
static int eScanResult = -1;
static struct BleDriverConnectionMap connectionMap[NRF_SDH_BLE_CENTRAL_LINK_COUNT];

static uint8_t m_adv_handle = BLE_GAP_ADV_SET_HANDLE_NOT_SET;
static uint8_t m_enc_advdata[BLE_GAP_ADV_SET_DATA_SIZE_MAX];
static ble_gap_adv_data_t m_adv_data =
{
  .adv_data =
  {
    .p_data = m_enc_advdata,
    .len    = BLE_GAP_ADV_SET_DATA_SIZE_MAX
  },
  .scan_rsp_data =
  {
    .p_data = NULL,
    .len    = 0
  }
};
static uint16_t m_conn_handle = BLE_CONN_HANDLE_INVALID;
static const char* m_bleDeviceNameAdvFilter = NULL;

int BleDriver_Init(const char* bleDeviceName)
{
  int err;

  // Configure and initialize the BLE stack.
  err = BleStackInit();
  if( err != 0 )
  {
    DbgPrintf(&amp;quot;BleDriver_init: BleStackInit %d&amp;quot;, err);
    return err;
  }

  // Initialize modules.
  err = GapInit(bleDeviceName);
  if ( err != 0 )
  {
    DbgPrintf(&amp;quot;BleDriver_init: GapInit %d&amp;quot;, err);
    return err;
  }
  err = GattInit();
  if( err != 0 )
  {
    DbgPrintf(&amp;quot;BleDriver_init: GattInit %d&amp;quot;, err);
    return err;
  }
  err = DiscoveryInit();
  if( err != 0 )
  {
    DbgPrintf(&amp;quot;BleDriver_init: DiscoveryInit %d&amp;quot;, err);
    return err;
  }
  err = ServicesInit();
  if( err != 0 )
  {
    DbgPrintf(&amp;quot;BleDriver_init: ServicesInit %d&amp;quot;, err);
    return err;
  }
  err = PeerManagerInit();
  if( err != 0 )
  {
    DbgPrintf(&amp;quot;BleDriver_init: PeerManagerInit %d&amp;quot;, err);
    return err;
  }
  err = ScanInit();
  if( err != 0 )
  {
    DbgPrintf(&amp;quot;BleDriver_init: ScanInit %d&amp;quot;, err);
    return err;
  }

  // Create the connection semaphore
  SemaphoreCreate(&amp;amp;connectionSema);

  // Create a uC-OS task for the BLE stack.
  nrf_sdh_ucos_init(NULL, NULL);

  // Success
  return 0;
}

int BleCentralDriver_StartScan(const char* bleDeviceFilter)
{
  uint32_t err;

  // BLE device name filter cannot be null at the moment.
  if (bleDeviceFilter == NULL)
  {
    DbgPrintf(&amp;quot;Device Filter is NULL&amp;quot;);
    return -EFAULT;
  }

  // Make sure we are not already scanning
  if( scanInProgress == true )
  {
    
    BleCentralDriver_StopScan();
    DbgPrintf(&amp;quot;scan is in progress, restarting process received evt %d&amp;quot;, eScanResult);
  }

  m_bleDeviceNameAdvFilter = bleDeviceFilter;

  // Set power level for scanning
  err = sd_ble_gap_tx_power_set(BLE_GAP_TX_POWER_ROLE_SCAN_INIT, BLE_CONN_HANDLE_INVALID, 8);
  if( err != 0 )
  {
    DbgPrintf(&amp;quot;sd_ble_gap_tx_power_set failed with error %u&amp;quot;, err);
    return -EFAULT;
  }

  // Start scanning
  err = nrf_ble_scan_params_set(&amp;amp;scanInstance, &amp;amp;scanParams);
  if( err != 0 )
  {
    DbgPrintf(&amp;quot;nrf_ble_scan_params_set failed with error %u&amp;quot;, err);
    return -EFAULT;
  }

  err = nrf_ble_scan_start(&amp;amp;scanInstance);
  if( err != 0 )
  {
     DbgPrintf(&amp;quot;nrf_ble_scan_start failed with error %u&amp;quot;, err);
    return -EFAULT;
  }

  // Set flag
  scanInProgress = true;

  // Success
  return 0;
}

int BleCentralDriver_StopScan(void)
{
  // Stop scanning
  nrf_ble_scan_stop();

  // Reset flag
  scanInProgress = false;

  m_bleDeviceNameAdvFilter = NULL;

  // Success
  return 0;
}

int BleCentralDriver_Connect(uint8_t* peerAddress)
{
  int err;
  int freeSlot = -1;

  // Check for valid address
  if( peerAddress == NULL)
  {
    DbgPrintf(&amp;quot;BleCentralDriver_Connect peerAddress null&amp;quot;);
    return -EFAULT;
  }

  // Check if we are already connected to that peer
  if( GetConnectedSlotFromAddress(peerAddress) != -1 )
  {
    DbgPrintf(&amp;quot;BleCentralDriver_Connect already connected to that peer&amp;quot;);
    return -EFAULT;
  }

  // Find a free slot
  freeSlot = GetDisconnectedSlot();
  if( freeSlot == -1 )
  {
    DbgPrintf(&amp;quot;BleCentralDriver_Connect no free slot found %d&amp;quot;, freeSlot);
    return -EFAULT;
  }

  // Prepare connection map
  memset(&amp;amp;connectionMap[freeSlot].gapAddr, 0, sizeof(ble_gap_addr_t));
  memcpy(&amp;amp;connectionMap[freeSlot].gapAddr.addr, peerAddress, BLE_GAP_ADDR_LEN);
  connectionMap[freeSlot].gapAddr.addr_type = BLE_GAP_ADDR_TYPE_RANDOM_STATIC;
  connectionMap[freeSlot].connectionParams = defaultConnectionParams;
  connectionMap[freeSlot].dataLinkReady = false;

  // Initialize connection param
  sd_ble_gap_ppcp_set(&amp;amp;connectionMap[freeSlot].connectionParams);
  connectionMap[freeSlot].connectionParams.min_conn_interval = DEFAULT_CONN_INTERVAL;
  connectionMap[freeSlot].connectionParams.max_conn_interval = DEFAULT_CONN_INTERVAL;

  // Initiate connection
  err = sd_ble_gap_connect(&amp;amp;connectionMap[freeSlot].gapAddr, &amp;amp;scanParams, &amp;amp;connectionMap[freeSlot].connectionParams, APP_BLE_CONN_CFG_TAG);
  if( err != 0 )
  {
    DbgPrintf(&amp;quot;BleCentralDriver_Connect error initializing the connection %d&amp;quot;, err);
    return err;
  }

  // Set current slot as connecting
  connectionMap[freeSlot].status = BLE_CONNECTING;

  // Wait for connection to end
  SemaphoreWait(&amp;amp;connectionSema, true, 0);

  // Success
  return 0;
}

int BleCentralDriver_Disconnect(uint8_t* peerAddress)
{
  int currentSlot = -1;

  // Find the proper slot
  currentSlot = GetConnectedSlotFromAddress(peerAddress);
  if( currentSlot == -1 )
  {
    DbgPrintf(&amp;quot;BleCentralDriver_Connect error finding proper slot&amp;quot;);
    return -EFAULT;
  }

  // Initiate peer disconnection
  uint32_t err_code =  sd_ble_gap_disconnect(connectionMap[currentSlot].connectionHandle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
  if (err_code != NRF_SUCCESS)
  {
      DbgPrintf(&amp;quot;BleCentralDriver_Connect error while initiating disconnection&amp;quot;, err_code);
      return -EFAULT;
  }

  // Success
  return 0;
}

int BleCentralDriver_SendData(uint8_t* peerAddress, uint8_t* data, uint16_t length)
{
  int err;
  int currentSlot = -1;

  // Find the proper slot
  currentSlot = GetConnectedSlotFromAddress(peerAddress);
  if( currentSlot == -1 )
  {
    return -EFAULT;
  }

  // Make sure the data link is ready
  if( connectionMap[currentSlot].dataLinkReady == false )
  {
    return -EFAULT;
  }

  // Send data
  if( nrf_ble_spes_send_notif(connectionMap[currentSlot].connectionHandle, &amp;amp;spesInstance, data, length) != NRF_SUCCESS )
  {
    return -EBUSY;
  }

  // Success
  return 0;
}

int BlePeripheralDriver_StartAdvertising(void* pManufacturerData, uint32_t len)
{
  // Make sure we have manufacturer data
  if( pManufacturerData == NULL )
  {
    return -EFAULT;
  }

  // Initialize advertising
  AdvertisingInit(pManufacturerData, len);

  // Set power level for advertising
  sd_ble_gap_tx_power_set(BLE_GAP_TX_POWER_ROLE_ADV, m_adv_handle, 8);

  // Start advertising
  uint32_t result = sd_ble_gap_adv_start(m_adv_handle, APP_BLE_CONN_CFG_TAG);
  if (result != NRF_SUCCESS)
  {
    DbgPrintf(&amp;quot;BlePeripheralDriver_StartAdvertising failed %u&amp;quot;, result);
    return -EFAULT;
  }

  // Success
  return 0;
}

int BlePeripheralDriver_StopAdvertising(void)
{
  // Stop advertising
  uint32_t result = sd_ble_gap_adv_stop(m_adv_handle);
  if (result != NRF_SUCCESS)
  {
    return -EFAULT;
  }

  // Success
  return 0;
}

bool BlePeripheralDriver_IsConnected(void)
{
  return (m_conn_handle != BLE_CONN_HANDLE_INVALID);
}

int BlePeripheralDriver_Disconnect(void)
{
  sd_ble_gap_disconnect(m_conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);

  // Success
  return 0;
}

int BlePeripheralDriver_SendData(uint8_t* data, uint16_t length)
{
  int err;

  // Send data
  if( nrf_ble_spes_send_notif(m_conn_handle, &amp;amp;spesInstance, data, length) != NRF_SUCCESS )
  {
    return -EBUSY;
  }

  // Success
  return 0;
}

int BleDriver_SetCallback(BleDriver_Callback callback, void* arg)
{
  callbackData.cb = callback;
  callbackData.arg = arg;
  return 0;
}

static int GetConnectedSlotFromAddress(uint8_t* peerAddress)
{
  for(uint8_t i = 0; i &amp;lt; NRF_SDH_BLE_CENTRAL_LINK_COUNT; i++)
  {
    if( (connectionMap[i].status == BLE_CONNECTED) &amp;amp;&amp;amp; (memcmp(connectionMap[i].gapAddr.addr, peerAddress, BLE_GAP_ADDR_LEN) == 0) )
    {
      return i;
    }
  }
  return -1;
}

static int GetConnectedSlotFromHandle(uint16_t connectionHandle)
{
  for(uint8_t i = 0; i &amp;lt; NRF_SDH_BLE_CENTRAL_LINK_COUNT; i++)
  {
    if( (connectionMap[i].status == BLE_CONNECTED) &amp;amp;&amp;amp; (connectionMap[i].connectionHandle == connectionHandle) )
    {
      return i;
    }
  }
  return -1;
}

static int GetDisconnectedSlot(void)
{
  for(uint8_t i = 0; i &amp;lt; NRF_SDH_BLE_CENTRAL_LINK_COUNT; i++)
  {
    if( connectionMap[i].status == BLE_DISCONNECTED )
    {
      return i;
    }
  }
  return -1;
}

static int GetConnectingSlot(void)
{
  for(uint8_t i = 0; i &amp;lt; NRF_SDH_BLE_CENTRAL_LINK_COUNT; i++)
  {
    if( connectionMap[i].status == BLE_CONNECTING )
    {
      return i;
    }
  }
  return -1;
}

static int BleStackInit(void)
{
  int err;

  DbgPrintf(&amp;quot;BleStackInit: entering&amp;quot;);

  err = nrf_sdh_enable_request();
  if( err != 0 )
  {
    DbgPrintf(&amp;quot;BleStackInit: nrf_sdh_enable_request %d&amp;quot;, err);
    return -EFAULT;
  }

  // Configure the BLE stack using the default settings.
  // Fetch the start address of the application RAM.
  uint32_t ram_start = 0;
  err = nrf_sdh_ble_default_cfg_set(APP_BLE_CONN_CFG_TAG, &amp;amp;ram_start);
  if( err != 0 )
  {
    DbgPrintf(&amp;quot;BleStackInit: nrf_sdh_ble_default_cfg_set %d&amp;quot;, err);
    return -EFAULT;
  }

  // Enable BLE stack.
  err = nrf_sdh_ble_enable(&amp;amp;ram_start);
  if( err != 0 )
  {
    DbgPrintf(&amp;quot;BleStackInit: nrf_sdh_ble_enable %d&amp;quot;, err);
    return -EFAULT;
  }

  // Register a handler for BLE events.
  NRF_SDH_BLE_OBSERVER(bleObserver, APP_BLE_OBSERVER_PRIO, BleCallback, NULL);

  // Success
  return 0;
}

static int GapInit(const char* bleDeviceName)
{
  ble_gap_conn_params_t   gap_conn_params;
  ble_gap_conn_sec_mode_t sec_mode;
  int err;

  BLE_GAP_CONN_SEC_MODE_SET_OPEN(&amp;amp;sec_mode);

  err = sd_ble_gap_device_name_set(&amp;amp;sec_mode, (const uint8_t *)bleDeviceName, strlen(bleDeviceName));
  if (err != 0)
  {
    return -EFAULT;
  }
  memset(&amp;amp;gap_conn_params, 0, sizeof(gap_conn_params));

  gap_conn_params.min_conn_interval = DEFAULT_CONN_INTERVAL;
  gap_conn_params.max_conn_interval = DEFAULT_CONN_INTERVAL;
  gap_conn_params.slave_latency     = SLAVE_LATENCY;
  gap_conn_params.conn_sup_timeout  = CONN_SUP_TIMEOUT;

  err = sd_ble_gap_ppcp_set(&amp;amp;gap_conn_params);
  if (err != 0)
  {
    return -EFAULT;
  }

  // Success
  return 0;
}

static int GattInit(void)
{
  ble_opt_t opt = {0};
  int err;

  err = nrf_ble_gatt_init(&amp;amp;gattInstance, NULL);
  if( err != 0 )
  {
    return -EFAULT;
  }

  err = nrf_ble_gatt_att_mtu_central_set(&amp;amp;gattInstance, NRF_SDH_BLE_GATT_MAX_MTU_SIZE);
  if( err != 0 )
  {
    return -EFAULT;
  }

  opt.common_opt.conn_evt_ext.enable = 1;
  err = sd_ble_opt_set(BLE_COMMON_OPT_CONN_EVT_EXT, &amp;amp;opt);
  if( err != 0 )
  {
    return -EFAULT;
  }

  return 0;
}

static int DiscoveryInit(void)
{
  int err;
  err = ble_db_discovery_init(DiscoveryCallback);
  if( err != 0 )
  {
    return -EFAULT;
  }

  return 0;
}

static int ServicesInit(void)
{
  int err;
  nrf_ble_qwr_init_t qwr_init = {0};

  // Initialize Serial Port Emulation Service
  err = nrf_ble_spes_init(&amp;amp;spesInstance, SpesCallback);
  if( err != 0 )
  {
    return -EFAULT;
  }
  err = nrf_ble_spes_c_init(&amp;amp;specInstance, SpecCallback);
  if( err != 0 )
  {
    return -EFAULT;
  }

  // Initialize Queued Write Module.
  qwr_init.error_handler = NULL;
  err = nrf_ble_qwr_init(&amp;amp;qwrInstance, &amp;amp;qwr_init);
  if ( err != 0 )
  {
    return -EFAULT;
  }

  return 0;
}

static int ScanInit(void)
{
  int err;
  nrf_ble_scan_init_t initScan = {0};

  // Initialize scan
  initScan.connect_if_match = false;
  initScan.conn_cfg_tag = APP_BLE_CONN_CFG_TAG;
  initScan.p_scan_param = &amp;amp;scanParams;
  err = nrf_ble_scan_init(&amp;amp;scanInstance, &amp;amp;initScan, ScanCallback);
  if(err != 0 )
  {
    return -EFAULT;
  }
  return 0;
}

static void ScanCallback(scan_evt_t const * p_scan_evt)
{
  ret_code_t err_code;
  switch(p_scan_evt-&amp;gt;scan_evt_id)
  {
    case NRF_BLE_SCAN_EVT_SCAN_TIMEOUT:
    {
      scanInProgress = false;
      if( callbackData.cb != NULL )
      {
        callbackData.cb(BLE_SCAN_COMPLETED_EVENT, NULL, NULL, callbackData.arg);
      }
    }
    break;

    case NRF_BLE_SCAN_EVT_CONNECTED:
    {
      scanInProgress = false; // Scan ended because of a connection
    }
    break;

#if BLE_DVR_DEBUG_PRINT
    default:
    {
      eScanResult = p_scan_evt-&amp;gt;scan_evt_id;
      DbgPrintf(&amp;quot;Unknown scan Event: %u\r\n&amp;quot;, p_scan_evt-&amp;gt;scan_evt_id);
    }
#endif
  }
}

static void AdvertisingInit(void* pManufacturerData, uint32_t len)
{
  ble_gap_adv_params_t adv_params = {0};
  ble_advdata_t adv_data = {0};
  ble_advdata_manuf_data_t advManufacturerData = {0};

  advManufacturerData.data.p_data        = pManufacturerData;
  advManufacturerData.data.size          = len;
  advManufacturerData.company_identifier = BLE_COMPANY_ID;

  adv_params.properties.type = BLE_GAP_ADV_TYPE_CONNECTABLE_SCANNABLE_UNDIRECTED;
  adv_params.p_peer_addr     = NULL;
  adv_params.filter_policy   = BLE_GAP_ADV_FP_ANY;
  adv_params.interval        = APP_ADV_INTERVAL;
  adv_params.duration        = 0;
  adv_params.primary_phy     = BLE_GAP_PHY_1MBPS;
  adv_params.secondary_phy   = BLE_GAP_PHY_1MBPS;

  adv_data.name_type               = BLE_ADVDATA_FULL_NAME;
  adv_data.include_appearance      = false;
  adv_data.flags                   = BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE;
  adv_data.uuids_complete.uuid_cnt = 0;
  adv_data.p_manuf_specific_data   = &amp;amp;advManufacturerData;

  ble_advdata_encode(&amp;amp;adv_data, m_adv_data.adv_data.p_data, &amp;amp;m_adv_data.adv_data.len);

  sd_ble_gap_adv_set_configure(&amp;amp;m_adv_handle, &amp;amp;m_adv_data, &amp;amp;adv_params);
}

static int PeerManagerInit(void)
{
  ble_gap_sec_params_t sec_param;

  pm_init();

  memset(&amp;amp;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;

  pm_sec_params_set(&amp;amp;sec_param);

  pm_register(PeerManagerCallback);
}

static void PeerManagerCallback(pm_evt_t const * p_evt)
{
  switch (p_evt-&amp;gt;evt_id)
  {
    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-&amp;gt;conn_handle, &amp;amp;conn_sec_config);
    } break;

    case PM_EVT_STORAGE_FULL:
    {
      // Run garbage collection on the flash.
      fds_gc();
    } break;

    case PM_EVT_PEERS_DELETE_SUCCEEDED:
    {
      pm_peers_delete();
    } break;

#if BLE_DVR_DEBUG_PRINT
    default:
    {
      DbgPrintf(&amp;quot;Unknown PM Event: %d&amp;quot;, p_evt-&amp;gt;evt_id);
    }
#endif
    break;
  }
}

static void BleCallback(ble_evt_t const * p_ble_evt, void * p_context)
{
  int currentSlot = -1;
  uint8_t* addr = NULL;

  switch (p_ble_evt-&amp;gt;header.evt_id)
  {
    case BLE_GAP_EVT_ADV_REPORT:
    {
      DbgPrintf(&amp;quot;BleCallback BLE_GAP_EVT_ADV_REPORT with status %u&amp;quot;, p_ble_evt-&amp;gt;evt.gap_evt.params.adv_report.type.status);
      ProcessAdvReport(&amp;amp;p_ble_evt-&amp;gt;evt.gap_evt.params.adv_report);
    }
    break;

    case BLE_GAP_EVT_CONNECTED:
    {
      // Set power level for connection
      sd_ble_gap_tx_power_set(BLE_GAP_TX_POWER_ROLE_CONN, p_ble_evt-&amp;gt;evt.gap_evt.conn_handle, 8);

      // Received a connection when in Central.
      if (p_ble_evt-&amp;gt;evt.gap_evt.params.connected.role == BLE_GAP_ROLE_CENTRAL)
      {
        // Get proper slot
        currentSlot = GetConnectingSlot();

        if( currentSlot == -1 )
        {
          DbgPrintf(&amp;quot;BleCallback connecting slot error&amp;quot;);
          return;
        }

        addr = connectionMap[currentSlot].gapAddr.addr;

        // Assign the connection handle
        connectionMap[currentSlot].connectionHandle = p_ble_evt-&amp;gt;evt.gap_evt.conn_handle;

        // Update connection map
        connectionMap[currentSlot].status = BLE_CONNECTED;

        // Release the semaphore
        SemaphoreSignal(&amp;amp;connectionSema);
      }
      else
      {
        m_conn_handle = p_ble_evt-&amp;gt;evt.gap_evt.conn_handle;
        nrf_ble_qwr_conn_handle_assign(&amp;amp;qwrInstance, m_conn_handle);

        // Update phy
        ble_gap_phys_t const phys =
        {
          .rx_phys = BLE_GAP_PHY_2MBPS,
          .tx_phys = BLE_GAP_PHY_2MBPS,
        };
        sd_ble_gap_phy_update(p_ble_evt-&amp;gt;evt.gap_evt.conn_handle, &amp;amp;phys);
      }

      // Start GATT service discovery
      ble_db_discovery_start(&amp;amp;dbDiscoveryInstance, p_ble_evt-&amp;gt;evt.gap_evt.conn_handle);

      // Call user connection callback
      if( callbackData.cb != NULL )
      {
        struct BleConnectionEventData connectionEventData;
        connectionEventData.connected = true;
        callbackData.cb(BLE_CONNECTION_EVENT, addr, &amp;amp;connectionEventData, callbackData.arg);
      }
    }
    break;

    case BLE_GAP_EVT_DISCONNECTED:
    {
      // If disconnected from central (aka, we are the peripheral)
      if ( m_conn_handle == p_ble_evt-&amp;gt;evt.common_evt.conn_handle )
      {
        m_conn_handle = BLE_CONN_HANDLE_INVALID;
      }
      // If disconnected from peripheral (aka, we are the central)
      else
      {
        // Find the proper slot
        currentSlot = GetConnectedSlotFromHandle(p_ble_evt-&amp;gt;evt.common_evt.conn_handle);
        if( currentSlot == -1 )
        {
           DbgPrintf(&amp;quot;BleCallback disconnected slot was not found&amp;quot;);
          return;
        }

        // Update connection map
        connectionMap[currentSlot].status = BLE_DISCONNECTED;
        connectionMap[currentSlot].dataLinkReady = false;

        addr = connectionMap[currentSlot].gapAddr.addr;
      }

      // Call user connection callback
      if( callbackData.cb != NULL )
      {
        struct BleConnectionEventData connectionEventData;
        connectionEventData.connected = false;
        callbackData.cb(BLE_CONNECTION_EVENT, addr, &amp;amp;connectionEventData, callbackData.arg);
      }
    }
    break;

    case BLE_GAP_EVT_TIMEOUT:
    {
      // Find the proper slot
      currentSlot = GetConnectingSlot();
      if( currentSlot == -1 )
      {
        DbgPrintf(&amp;quot;BleCallback - SLOT not found&amp;quot;);
        return;
      }

      // Update connection map
      connectionMap[currentSlot].status = BLE_DISCONNECTED;
      connectionMap[currentSlot].dataLinkReady = false;

      // Inform the BLE task
      if (p_ble_evt-&amp;gt;evt.gap_evt.params.timeout.src == BLE_GAP_TIMEOUT_SRC_CONN) 
      {
        DbgPrintf(&amp;quot;BleCallback - BLE_GAP_TIMEOUT_SRC_CONN&amp;quot;);
        callbackData.cb(BLE_CONNECTION_TIMEOUT_EVENT, addr, NULL, callbackData.arg);

      }
      else if (p_ble_evt-&amp;gt;evt.gap_evt.params.timeout.src == BLE_GAP_TIMEOUT_SRC_SCAN)
      {
        DbgPrintf(&amp;quot;BleCallback - BLE_GAP_TIMEOUT_SRC_SCAN&amp;quot;);
        // TODO: handle...
      }
      else if (p_ble_evt-&amp;gt;evt.gap_evt.params.timeout.src == BLE_GAP_TIMEOUT_SRC_AUTH_PAYLOAD)
      {
        DbgPrintf(&amp;quot;BleCallback - BLE_GAP_TIMEOUT_SRC_AUTH_PAYLOAD&amp;quot;);
        // TODO: handle...
      }

      // Release the semaphore
      SemaphoreSignal(&amp;amp;connectionSema);
    }
    break;

    case BLE_GAP_EVT_PHY_UPDATE_REQUEST:
    {
      ble_gap_phys_t const phys =
      {
        .rx_phys = BLE_GAP_PHY_2MBPS,
        .tx_phys = BLE_GAP_PHY_2MBPS,
      };
      sd_ble_gap_phy_update(p_ble_evt-&amp;gt;evt.gap_evt.conn_handle, &amp;amp;phys);
    }
    break;

    case BLE_GATTC_EVT_TIMEOUT:
      // Disconnect on GATT Client timeout event.
      sd_ble_gap_disconnect(p_ble_evt-&amp;gt;evt.gattc_evt.conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
      if( callbackData.cb != NULL )
      {
        struct BleConnectionEventData connectionEventData;
        connectionEventData.connected = false;
        callbackData.cb(BLE_CONNECTION_EVENT, NULL, &amp;amp;connectionEventData, callbackData.arg);
      }
    break;

    case BLE_GATTS_EVT_TIMEOUT:
      // Disconnect on GATT Server timeout event.
      sd_ble_gap_disconnect(p_ble_evt-&amp;gt;evt.gatts_evt.conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
      if( callbackData.cb != NULL )
      {
        struct BleConnectionEventData connectionEventData;
        connectionEventData.connected = false;
        callbackData.cb(BLE_CONNECTION_EVENT, NULL, &amp;amp;connectionEventData, callbackData.arg);
      }
    break;
#if BLE_DVR_DEBUG_PRINT
    default:
    {
      DbgPrintf(&amp;quot;Unknown BLE Event: 0x%x&amp;quot;, p_ble_evt-&amp;gt;header.evt_id);
    }
#endif
  }
}

static void ProcessAdvReport(ble_gap_evt_adv_report_t const * pAdvReport)
{
  struct BleDeviceDiscoveryData deviceDiscoveryData;
  uint8_t* pAdvData;
  uint16_t advDataLen;
  uint16_t fieldLen;
  uint16_t offset = 0;
  uint16_t companyId = 0;

  // Initialize advertisement report for parsing.
  pAdvData = (uint8_t *)pAdvReport-&amp;gt;data.p_data;
  advDataLen = pAdvReport-&amp;gt;data.len;

  // Only report EDGE devices
  if( ble_advdata_name_find(pAdvData, advDataLen, m_bleDeviceNameAdvFilter) == true  )
  {
    // Extract manufacturer data
    offset = 0;
    fieldLen = ble_advdata_search(pAdvData, advDataLen, &amp;amp;offset, BLE_GAP_AD_TYPE_MANUFACTURER_SPECIFIC_DATA);

    // Validate minimal length BleManufacturerData + company ID
    if( fieldLen &amp;gt;= BLE_COMPANY_ID_LEN )
    {
      // Validate company ID
      memcpy(&amp;amp;companyId, &amp;amp;pAdvData[offset], BLE_COMPANY_ID_LEN);
      if( companyId == BLE_COMPANY_ID )
      {
        // Prepare device discovery data
        deviceDiscoveryData.rssi = pAdvReport-&amp;gt;rssi;

        fieldLen -= BLE_COMPANY_ID_LEN;
        if ( fieldLen &amp;gt; sizeof(deviceDiscoveryData.manufacturerData) )
        {
          fieldLen = sizeof(deviceDiscoveryData.manufacturerData);
        }

        memcpy(&amp;amp;deviceDiscoveryData.manufacturerData, &amp;amp;pAdvData[offset+BLE_COMPANY_ID_LEN], fieldLen );

        // Call the user callback
        if( callbackData.cb != NULL )
        {
          callbackData.cb(BLE_DEVICE_DISCOVERY_EVENT, (uint8_t*)pAdvReport-&amp;gt;peer_addr.addr, &amp;amp;deviceDiscoveryData, callbackData.arg);
        }
      }
    }
  }
}

static void DiscoveryCallback(ble_db_discovery_evt_t * p_evt)
{
  nrf_ble_spes_c_on_db_disc_evt(&amp;amp;specInstance, p_evt);
}

static void SpesCallback(nrf_ble_spes_evt_t evt)
{
  int currentSlot = -1;
  int err;
  uint8_t* addr = NULL;

  // Find the proper slot
  currentSlot = GetConnectedSlotFromHandle(evt.conn_handle);
  if( currentSlot != -1 )
  {
    addr = connectionMap[currentSlot].gapAddr.addr;
  }

  switch (evt.evt_type)
  {
    case NRF_BLE_SPES_EVT_NOTIF_ENABLED:
    {
      if (currentSlot != -1)
      {
        connectionMap[currentSlot].dataLinkReady = true;
      }

      // Call the user callback
      if( callbackData.cb != NULL )
      {
        callbackData.cb(BLE_DATA_LINK_READY_EVENT, addr, NULL, callbackData.arg);
      }
    }
    break;

    case NRF_BLE_SPES_EVT_TX_COMPLETED:
    {
      // Call the user callback
      if( callbackData.cb != NULL )
      {
        callbackData.cb(BLE_DATA_SENT_EVENT, addr, NULL, callbackData.arg);
      }
    }
    break;

#if BLE_DVR_DEBUG_PRINT
    default:
    {
      DbgPrintf(&amp;quot;Unknown SPES event: %d&amp;quot;,evt.evt_type );
    }
    break;
#endif
  }
}

static void SpecCallback(nrf_ble_spes_c_t * p_spes_c, nrf_ble_spes_c_evt_t * p_evt)
{
  int currentSlot = -1;
  uint8_t* addr = NULL;

  switch (p_evt-&amp;gt;evt_type)
  {
    case NRF_BLE_SPES_C_EVT_DISCOVERY_COMPLETE:
    {
      // Assign the SPES handle
      nrf_ble_spes_c_handles_assign(p_spes_c, p_evt-&amp;gt;conn_handle, &amp;amp;p_evt-&amp;gt;params.peer_db);

      // Enable notifications
      nrf_ble_spes_c_notif_enable(p_spes_c);
    }
    break;

    case NRF_BLE_SPES_C_EVT_NOTIFICATION:
    {

      // Find the proper slot


      // Find the proper slot
      currentSlot = GetConnectedSlotFromHandle(p_evt-&amp;gt;conn_handle);
      if( currentSlot != -1 )
      {
        addr = connectionMap[currentSlot].gapAddr.addr;
      }

      // Call user callback
      if( callbackData.cb != NULL )
      {
        struct BleDataReceivedEventData dataReceivedEventData;

        dataReceivedEventData.length = p_evt-&amp;gt;params.hvx.dataLen;
        dataReceivedEventData.data = p_evt-&amp;gt;params.hvx.data;
        callbackData.cb(BLE_DATA_RECEIVED_EVENT, addr, &amp;amp;dataReceivedEventData, callbackData.arg);
      }
    }
    break;

#if BLE_DVR_DEBUG_PRINT
    default:
    {
      DbgPrintf(&amp;quot;Unknown SCPEC Event: %d&amp;quot;, p_evt-&amp;gt;evt_type);
    }
    break;
#endif
  }
}

static void HandleTcvrWrite(ble_tcvr_evt_t const * pEvt)
{
  char data[TCVR_CHANNEL_CHAR_LEN] = {0};
  BleTcvrCharacteristics chars = {0};

  // Ensure NUL-termination.
  uint16_t len = pEvt-&amp;gt;u.write.dataLen;
  if (len &amp;gt; sizeof(data) - 1)
  {
    len = sizeof(data) - 1;
  }
  memcpy(data, pEvt-&amp;gt;u.write.data, len);

  switch (pEvt-&amp;gt;u.write.charId)
  {
  case BLE_TCVR_CHAR_CHANNEL_1_UUID:
  {
    char* ptr;
    unsigned long tmp = strtoul(data, &amp;amp;ptr, 10);
    chars.presenceFlags = BLE_TCVR_CHANNEL1_SET_FLAG;
    if (tmp &amp;lt;= UINT8_MAX &amp;amp;&amp;amp; *ptr == 0)
    {
      chars.channel1 = (uint8_t)tmp;
    }
    else
    {
      // Trigger an invalid update so we will rewrite a good value.
      chars.channel1 = 0;
    }
    break;
  }

  case BLE_TCVR_CHAR_CHANNEL_2_UUID:
  {
    char* ptr;
    unsigned long tmp = strtoul(data, &amp;amp;ptr, 10);
    chars.presenceFlags = BLE_TCVR_CHANNEL2_SET_FLAG;
    if (tmp &amp;lt;= UINT8_MAX &amp;amp;&amp;amp; *ptr == 0)
    {
      chars.channel2 = (uint8_t)tmp;
    }
    else
    {
      // Trigger an invalid update so we will rewrite a good value.
      chars.channel2 = 0;
    }
    break;
  }

  case BLE_TCVR_CHAR_IP_ADDRESS_UUID:
  {
    // Writing the IP address using BLE isn&amp;#39;t supported.
    // We should never get here.
    break;
  }

  case BLE_TCVR_CHAR_NAME_UUID:
  {
    // Writing the transceiver name using BLE isn&amp;#39;t supported.
    // We should never get here.
    break;
  }
  }

  if (chars.presenceFlags != 0 &amp;amp;&amp;amp; callbackData.cb != NULL)
  {
    callbackData.cb(BLE_TCVR_CHAR_WRITE_EVENT, NULL, &amp;amp;chars, callbackData.arg);
  }
}

static void TcvrCallback(ble_tcvr_t const* pCtx, ble_tcvr_evt_t const * pEvt)
{
  switch (pEvt-&amp;gt;evt_type)
  {
    case BLE_TCVR_EVT_WRITE:
      HandleTcvrWrite(pEvt);
      break;

    default:
      break;
  }
}

int BlePeripheralDriver_StartTcvrService(void)
{
  return ble_tcvr_init(&amp;amp;tcvrInstance, TcvrCallback);
}

static int WriteTcvrValue(uint16_t charId, void* pValue, uint16_t len)
{
  ble_gatts_value_t gattsValue;
  ble_gatts_hvx_params_t notifParam;
  uint16_t handleIndex = charId - BLE_TCVR_CHAR_CHANNEL_1_UUID;
  int result;
  // Write new attribute value
  gattsValue.len = len;
  gattsValue.offset = 0;
  gattsValue.p_value = (uint8_t*)pValue;
  // Fill notification data
  memset(&amp;amp;notifParam, 0, sizeof(notifParam));
  notifParam.type   = BLE_GATT_HVX_NOTIFICATION;
  notifParam.handle = tcvrInstance.tcvr_char_handles[handleIndex].value_handle;
  notifParam.p_data = gattsValue.p_value;
  notifParam.p_len  = &amp;amp;gattsValue.len;
  result = sd_ble_gatts_hvx(m_conn_handle, &amp;amp;notifParam);
  // Ignore some errors if the length was actually written.
  // It only means that the value could be written but the peer couldn&amp;#39;t
  // be notified for reasons out of our control.
  if (*notifParam.p_len == len &amp;amp;&amp;amp; (result == NRF_ERROR_INVALID_STATE ||
    result == NRF_ERROR_BUSY ||
    result == NRF_ERROR_FORBIDDEN ||
    result == BLE_ERROR_GATTS_SYS_ATTR_MISSING ||
    result == NRF_ERROR_RESOURCES)
    )
  {
    return NRF_SUCCESS;
  }
  return result;
}

///
/// @brief Update the transceiver characteristics.
///
/// @param[in] pTcvr  The transceiver characteristics to update.
int BlePeripheralDriver_UpdateTcvrCharacteristics(BleTcvrCharacteristics* pTcvr)
{
  int result = 0;
  char channel[TCVR_CHANNEL_CHAR_LEN] = {0};
  char ipAddress[TCVR_IP_CHAR_LEN] = {0};
  char name[TCVR_NAME_CHAR_LEN] = {0};
  uint16_t len;
  if (pTcvr-&amp;gt;presenceFlags &amp;amp; BLE_TCVR_CHANNEL1_SET_FLAG)
  {
    len = snprintf(channel, sizeof(channel), &amp;quot;%u&amp;quot;, pTcvr-&amp;gt;channel1);
    result = WriteTcvrValue(BLE_TCVR_CHAR_CHANNEL_1_UUID, channel, len);
    if (result != 0)
    {
      return result;
    }
  }

  if (pTcvr-&amp;gt;presenceFlags &amp;amp; BLE_TCVR_CHANNEL2_SET_FLAG)
  {
    len = snprintf(channel, sizeof(channel), &amp;quot;%u&amp;quot;, pTcvr-&amp;gt;channel2);
    result = WriteTcvrValue(BLE_TCVR_CHAR_CHANNEL_2_UUID, channel, len);
    if (result != 0)
    {
      return result;
    }
  }

  if (pTcvr-&amp;gt;presenceFlags &amp;amp; BLE_TCVR_IP_ADDRESS_SET_FLAG)
  {
    uint8_t* pIp = (uint8_t*)&amp;amp;pTcvr-&amp;gt;ipAddress;
    len = snprintf(ipAddress, sizeof(ipAddress), &amp;quot;%u.%u.%u.%u&amp;quot;, pIp[0], pIp[1], pIp[2], pIp[3]);
    result = WriteTcvrValue(BLE_TCVR_CHAR_IP_ADDRESS_UUID, ipAddress, len);
    if (result != 0)
    {
      return result;
    }
  }

  if (pTcvr-&amp;gt;presenceFlags &amp;amp; BLE_TCVR_NAME_SET_FLAG)
  {
    len = snprintf(name, sizeof(name), &amp;quot;%s&amp;quot;, pTcvr-&amp;gt;name);
    result = WriteTcvrValue(BLE_TCVR_CHAR_NAME_UUID, name, len);
    if (result != 0)
    {
      return result;
    }
  }
  return result;
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;When the issue occurs, I have these logs:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="text"&gt;83357822 Device Discovery: -92 c5ea83387d3c 000F4251 00000CAB 0 0 132

83357828 Device Discovery: -87 e1a462b70c8b 00000001 00000CE9 99 59 50

83358444 Device Discovery: -77 e3ae212d9835 000F4241 00000CAB 99 44 53

83358754 Device Discovery: -88 f4de99e3458b 000F4244 00000CE9 0 0 131

83358763 Device Discovery: -83 f912898349f4 000F424B 00002000 99 55 24

83359373 Device Discovery: -82 e1a462b70c8b 00000001 00000CE9 99 59 50

83359393 Device Discovery: -77 e3ae212d9835 000F4241 00000CAB 99 44 53

83359709 Device Discovery: -88 f4de99e3458b 000F4244 00000CE9 0 0 131

83359713 Device Discovery: -83 f912898349f4 000F424B 00002000 99 55 24

83360333 Device Discovery: -83 e1a462b70c8b 00000001 00000CE9 99 59 50

83360938 Device Discovery: -86 f0bae1e36357 000F4250 00000CAB 0 0 132

83361252 Device Discovery: -88 f4de99e3458b 000F4244 00000CE9 0 0 131

83361274 Device Discovery: -93 c5ea83387d3c 000F4251 00000CAB 0 0 132

83361888 Device Discovery: -87 f0bae1e36357 000F4250 00000CAB 0 0 132

83362219 BLE Scan Completed

83392377 BLE Scan Starting

83392737 Device Discovery: -78 f912898349f4 000F424B 00002000 99 55 24

83393021 Device Discovery: -88 f4de99e3458b 000F4244 00000CE9 0 0 131

83393052 Device Discovery: -76 e3ae212d9835 000F4241 00000CAB 99 44 53

83394260 Device Discovery: -83 f912898349f4 000F424B 00002000 99 55 24

83394571 Device Discovery: -84 f4de99e3458b 000F4244 00000CE9 0 0 131

83394586 Device Discovery: -72 e3ae212d9835 000F4241 00000CAB 99 44 53

83395231 Device Discovery: -83 f912898349f4 000F424B 00002000 99 55 24

83395526 Device Discovery: -89 c5ea83387d3c 000F4251 00000CAB 0 0 132

83395531 Device Discovery: -84 f4de99e3458b 000F4244 00000CE9 0 0 131

83395533 Device Discovery: -85 f0bae1e36357 000F4250 00000CAB 0 0 132

83395541 Device Discovery: -72 e3ae212d9835 000F4241 00000CAB 99 44 53

83396147 Device Discovery: -87 e1a462b70c8b 00000001 00000CE9 99 59 50

83396764 Device Discovery: -89 f912898349f4 000F424B 00002000 99 55 24

83397073 Device Discovery: -87 f4de99e3458b 000F4244 00000CE9 0 0 131

83397080 Device Discovery: -70 e3ae212d9835 000F4241 00000CAB 99 44 53

83397110 Device Discovery: -87 e1a462b70c8b 00000001 00000CE9 99 59 50

83397117 BLE Scan Completed

83427281 BLE Scan Starting

83427300 Device Discovery: -88 c5ea83387d3c 000F4251 00000CAB 0 0 132

83427613 Device Discovery: -88 f4de99e3458b 000F4244 00000CE9 0 0 131

83428257 Device Discovery: -88 c5ea83387d3c 000F4251 00000CAB 0 0 132

83428264 Device Discovery: -72 e3ae212d9835 000F4241 00000CAB 99 44 53

83428547 Device Discovery: -89 f912898349f4 000F424B 00002000 99 55 24

83429168 Device Discovery: -84 f0bae1e36357 000F4250 00000CAB 0 0 132

83429795 Device Discovery: -69 e3ae212d9835 000F4241 00000CAB 99 44 53

83429809 Device Discovery: -87 e1a462b70c8b 00000001 00000CE9 99 59 50

83430135 Device Discovery: -86 f0bae1e36357 000F4250 00000CAB 0 0 132

83430750 Device Discovery: -67 e3ae212d9835 000F4241 00000CAB 99 44 53

83430767 Device Discovery: -87 e1a462b70c8b 00000001 00000CE9 99 59 50

83431061 Device Discovery: -85 f4de99e3458b 000F4244 00000CE9 0 0 131

83431347 Device Discovery: -82 e1a462b70c8b 00000001 00000CE9 99 59 50

83432001 Device Discovery: -79 f912898349f4 000F424B 00002000 99 55 24

83432022 BLE Scan Completed

83462183 BLE Scan Starting

83462530 Device Discovery: -87 e1a462b70c8b 00000001 00000CE9 99 59 50

83462541 Device Discovery: -83 f912898349f4 000F424B 00002000 99 55 24

83462827 Device Discovery: -85 f0bae1e36357 000F4250 00000CAB 0 0 132

83463460 Device Discovery: -67 e3ae212d9835 000F4241 00000CAB 99 44 53

83463791 Device Discovery: -86 f0bae1e36357 000F4250 00000CAB 0 0 132

83464071 Device Discovery: -82 e1a462b70c8b 00000001 00000CE9 99 59 50

83464082 Device Discovery: -90 f912898349f4 000F424B 00002000 99 55 24

83464107 Device Discovery: -88 f4de99e3458b 000F4244 00000CE9 0 0 131

83465019 Device Discovery: -76 e3ae212d9835 000F4241 00000CAB 99 44 53

83465039 Device Discovery: -82 e1a462b70c8b 00000001 00000CE9 99 59 50

83465652 Device Discovery: -85 f4de99e3458b 000F4244 00000CE9 0 0 131

83465977 Device Discovery: -77 e3ae212d9835 000F4241 00000CAB 99 44 53

83512360 BLE Scan Starting

83512360 scan is in progress, restarting process received evt -1
83562536 BLE Scan Starting

83562536 scan is in progress, restarting process received evt -1
83612699 BLE Scan Starting

83612699 scan is in progress, restarting process received evt -1
83662866 BLE Scan Starting

83662866 scan is in progress, restarting process received evt -1
83713032 BLE Scan Starting

83713032 scan is in progress, restarting process received evt -1
83763200 BLE Scan Starting

83763200 scan is in progress, restarting process received evt -1
83813369 BLE Scan Starting

83813369 scan is in progress, restarting process received evt -1
83863529 BLE Scan Starting

83863529 scan is in progress, restarting process received evt -1
83913692 BLE Scan Starting

83913692 scan is in progress, restarting process received evt -1
83963858 BLE Scan Starting&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;So you will be able to see that we scan for 5 seconds ( we should receive a SCAN_COMPLETED_EVENT) and re-launch scanning after 30 seconds. When the issue appears, we never completed the previous scan. Then I attempt to stop the &amp;quot;unfinished&amp;quot; scan to be able to restart scanning again but it fails because I am not able to perform any discovery... the softdevice seems to be &amp;quot;stucked&amp;quot;. Let me know if you understand my issue with the additional information provided. Thanks!&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: nRF52840 unexpectedly stops scanning</title><link>https://devzone.nordicsemi.com/thread/208962?ContentTypeID=1</link><pubDate>Tue, 10 Sep 2019 13:14:10 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:ceb44870-67a2-494b-947e-90f81a3d0c5a</guid><dc:creator>Vidar Berg</dc:creator><description>&lt;p&gt;Hello,&amp;nbsp;&lt;/p&gt;
&lt;p&gt;I&amp;#39;m afraid can&amp;#39;t think of any obvious reasons for this behavior. Are you able to share your project or relevant pieces of your code so I can try to review it here? I can make the ticket private if needed.&amp;nbsp;&lt;/p&gt;
[quote user=""]After 5 seconds, the scan callback should receive a &amp;quot;NRF_BLE_SCAN_EVT_SCAN_TIMEOUT&amp;quot; event from the softdevice which should trigger a scan completed event in my code.[/quote]
&lt;p&gt;&amp;nbsp;Will the timer handler start scanning every 30 seconds even if you don&amp;#39;t get this event. Also, does your code check the return value from &amp;quot;scan start&amp;quot;?&amp;nbsp;&lt;/p&gt;
[quote user=""]Unfortunately the software is not able to get out of the previous uncompleted scanning and is not able to perform device discoveries anymore even if I stopped the previous scan. Can somebody help me with this problem? Thanks.[/quote]
&lt;p&gt;Is it possible that the program may have become &amp;quot;stuck&amp;quot; in the app error handler or the hardfault handler?&amp;nbsp;Maybe you can attach a debugger to the device when this happens and read out the program counter value to check if this may be the case. You can use the&amp;nbsp;nrfjprog command &amp;#39;--readregs&amp;#39; command&amp;nbsp;for reading the core registers.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item></channel></rss>