BLE Usage Scenarios#

This page describes step-by-step Bluetooth Low Energy (BLE) flows in the SiWx917 WiSeConnect SDK. It links to per-area scenario pages (operating modes, GAP, GATT, SMP) and lists SDK BLE example projects under examples/snippets/ble/ so you can open the matching project in Simplicity Studio or the SDK tree.

SDK paths: Relative to the WiseConnect SDK content root, BLE example applications live under wiseconnect/examples/snippets/ble/<example_folder>/. The same tree is published in the Silicon Labs wiseconnect GitHub repository as examples/snippets/ble/. Each <example_folder> contains a readme.md with hardware, build, and test steps.

Scenario Documentation by Area#

Area

Page

Focus

Processing modes (SoC, NCP, RCP)

Processing modes - usage scenarios

Host–Network Processor (NWP) integration and mode-specific setup

GAP (roles, advertising, scanning, privacy, DLE, connection parameters)

GAP — usage scenarios

Peripheral, central, broadcaster, observer, extended advertising, periodic advertising / sync, privacy, DLE, LL connection parameter update

GATT (server, client, profiles)

GATT — usage scenarios

Services, discovery, read/write, notify/indicate, profiles

SMP (pairing, bonding, encryption)

SMP — usage scenarios

Pairing methods, bonding, encryption

Per-area pages (for example, GAP — usage scenarios) add illustrative C implementation examples next to each scenario, consistent with other SiWx917 developer guides. This hub table below stays focused on SDK example folder names and cross-area reading order.

Example ble_config.h and BLE SAPI#

Each BLE example project includes a project-local ble_config.h next to app.c under examples/snippets/ble/<example_folder>/. That header is part of the compile unit for both your application and the WiSeConnect BLE implementation: stack-side sources #include it so compile-time macros apply consistently across the build.

Typical contents (names and values vary by example project):

  • Host/stack capacity: GATT record counts, connection event budget, record buffer sizing (for example RSI_BLE_MAX_NBR_ATT_REC, RSI_BLE_NUM_CONN_EVENTS, RSI_BLE_NUM_REC_BYTES).

  • GAP — advertising: RSI_BLE_ADV_TYPE (for example UNDIR_CONN vs UNDIR_NON_CONN), filter type, interval min/max, channel map, power index options.

  • GAP — scanning: RSI_BLE_SCAN_TYPE, RSI_BLE_SCAN_FILTER_TYPE, start/stop scan constants used with rsi_ble_start_scanning() / extended scan helpers.

  • Connection defaults: Scan interval/window and supervision timeout style defines used when forming or updating links.

  • Optional features: Accept-list or advertising-payload filter defines, and other example-specific tuning.

As a result, many rsi_ble_* entry points take no runtime argument for the same value—the implementation fills internal request structures from these macros before sending commands to the NWP.

Example (GAP, legacy advertising): rsi_ble_start_advertising() does not take RSI_BLE_ADV_TYPE or interval arguments at runtime; GAP code copies RSI_BLE_ADV_TYPE, RSI_BLE_ADV_INT_MIN, RSI_BLE_ADV_INT_MAX, and related fields into the advertise request before RSI_BLE_REQ_ADV. Connectable vs non-connectable advertising follows that example’s ble_config.h even when app.c looks similar across projects. Where the API exposes a *_with_values() variant or an explicit parameter struct, you can override the header-driven defaults for that path. Advertise-specific notes: GAP — usage scenarios (peripheral connectable advertising and broadcaster sections). Broader stack and project setup: BLE initialization and configuration.

Example excerpt (ble_central example project): The following is abbreviated from examples/snippets/ble/ble_central/ble_config.h in the WiseConnect SDK; other example projects rename or add sections (for example UNDIR_NON_CONN in ble_ibeacon for non-connectable broadcast advertising).

/* Excerpt — ble_central/ble_config.h (WiseConnect SDK; not exhaustive) */

#define RSI_BLE_MAX_NBR_ATT_REC 20
#define RSI_BLE_MAX_NBR_PERIPHERALS 1
#define RSI_BLE_MAX_NBR_CENTRALS 1
#define RSI_BLE_NUM_CONN_EVENTS 2
#define RSI_BLE_NUM_REC_BYTES 0x40

#define RSI_BLE_ADV_TYPE UNDIR_CONN
#define RSI_BLE_ADV_FILTER_TYPE ALLOW_SCAN_REQ_ANY_CONN_REQ_ANY
#define RSI_BLE_ADV_INT_MIN 0x100
#define RSI_BLE_ADV_INT_MAX 0x200
#define RSI_BLE_ADV_CHANNEL_MAP 0x07

#define UNDIR_CONN 0x80
#define UNDIR_NON_CONN 0x83
/* ... additional advertise type and filter constants... */

#define LE_SCAN_INTERVAL 0x0100
#define LE_SCAN_WINDOW 0x0050
#define CONNECTION_INTERVAL_MIN 0x00A0
#define CONNECTION_INTERVAL_MAX 0x00A0
#define CONNECTION_LATENCY 0x0000
#define SUPERVISION_TIMEOUT 0x07D0

#define RSI_BLE_SCAN_TYPE SCAN_TYPE_ACTIVE
#define RSI_BLE_SCAN_FILTER_TYPE SCAN_FILTER_TYPE_ALL

Related: BLE architecture, BLE initialization and configuration, BLE API reference.


Application Task and BLE Event Handling (Recommended)#

WiSeConnect BLE stack callbacks run in the stack’s context. Do not perform long work, blocking waits, or long sequences of rsi_ble_* calls directly inside those callbacks. The SDK example projects use a single application thread (for example ble_central() in ble_central) that:

  1. Maintains a bit-mapped application event map (often two uint32_t values for up to 64 distinct event IDs).

  2. Implements rsi_ble_app_set_event() / rsi_ble_app_clear_event() / rsi_ble_app_get_event() (names vary slightly by example project) so callbacks only record state and raise an app event, then wake the application thread (commonly osSemaphoreRelease(ble_main_task_sem)).

  3. Runs a while (1) loop that waits for the semaphore when idle, then dispatches the next pending event in a switch and runs GAP / GATT / SMP procedures there.

That keeps re-entrancy and ordering predictable: callback context stays minimal; the application task owns the BLE procedure state machine.

Event Map and Helpers (illustrative)#

#include "cmsis_os2.h"

#define RSI_APP_EVENT_ADV_REPORT   0
#define RSI_APP_EVENT_CONNECTED    1
#define RSI_APP_EVENT_DISCONNECTED 2
// ... additional application-specific event IDs

static volatile uint32_t ble_app_event_map;
static volatile uint32_t ble_app_event_map1; // optional: events 32..63
osSemaphoreId_t ble_main_task_sem;

static void rsi_ble_app_init_events(void)
{
  ble_app_event_map  = 0;
  ble_app_event_map1 = 0;
}

void rsi_ble_app_set_event(uint32_t event_num)
{
  if (event_num < 32) {
    ble_app_event_map |= (1UL << event_num);
  } else {
    ble_app_event_map1 |= (1UL << (event_num - 32));
  }
  osSemaphoreRelease(ble_main_task_sem);
}

static void rsi_ble_app_clear_event(uint32_t event_num)
{
  if (event_num < 32) {
    ble_app_event_map &= ~(1UL << event_num);
  } else {
    ble_app_event_map1 &= ~(1UL << (event_num - 32));
  }
}

static int32_t rsi_ble_app_get_event(void)
{
  for (uint32_t ix = 0; ix < 64; ix++) {
    if (ix < 32) {
      if (ble_app_event_map & (1UL << ix)) {
        return (int32_t)ix;
      }
    } else if (ble_app_event_map1 & (1UL << (ix - 32))) {
      return (int32_t)ix;
    }
  }
  return -1;
}

Callbacks: Set Event and Return#

GAP handlers copy data into static or module-level buffers, then signal the application task. Example (central: advertising report matched filter):

void rsi_ble_simple_central_on_adv_report_event(rsi_ble_event_adv_report_t *adv_report)
{
  // ... extract name/address, set device_found, etc.
  rsi_ble_app_set_event(RSI_APP_EVENT_ADV_REPORT);
}

Connection and disconnect handlers follow the same pattern with RSI_APP_EVENT_CONNECTED / RSI_APP_EVENT_DISCONNECTED (or example-specific names such as RSI_BLE_CONN_EVENT in other example projects).

Application Task: Wait, Get Event, switch#

After rsi_ble_gap_register_callbacks(), rsi_ble_gatt_register_callbacks(), and rsi_ble_smp_register_callbacks() as required, the task creates ble_main_task_sem, calls rsi_ble_app_init_events(), then enters the loop. Illustrative core:

  ble_main_task_sem = osSemaphoreNew(1, 0, NULL);
  rsi_ble_app_init_events();
  // ... rsi_ble_start_scanning() or rsi_ble_start_advertising(), etc.

  while (1) {
    int32_t ev = rsi_ble_app_get_event();
    if (ev < 0) {
      osSemaphoreAcquire(ble_main_task_sem, osWaitForever);
      continue;
    }

    switch ((uint32_t)ev) {
      case RSI_APP_EVENT_ADV_REPORT:
        rsi_ble_app_clear_event(RSI_APP_EVENT_ADV_REPORT);
        // rsi_ble_stop_scanning(); rsi_ble_connect(...);...
        break;
      case RSI_APP_EVENT_CONNECTED:
        rsi_ble_app_clear_event(RSI_APP_EVENT_CONNECTED);
        // pairing, GATT discovery,...
        break;
      case RSI_APP_EVENT_DISCONNECTED:
        rsi_ble_app_clear_event(RSI_APP_EVENT_DISCONNECTED);
        // rsi_ble_start_scanning();...
        break;
      default:
        break;
    }
  }

Some example projects combine semaphore wait with power-save branches when no event is pending; others nest get_event() checks after rsi_ble_connect() to handle timeout (see ble_central app.c).

Reference implementations: examples/snippets/ble/ble_central/app.c, ble_secureconnection/app.c, ble_hid_on_gatt/app.c (event names and map layout differ; the structure is the same).


BLE NWP Power Save Example#

The ble_power_save example project demonstrates WLAN + BLE coexistence power save on SiWx91x: the NWP enters a power save profile (PSP) for Bluetooth, and the Wi‑Fi stack is moved to a matching performance profile, so both radios cooperate under SL_SI91X_WLAN_BLE_MODE.

When to Read This#

  • You enable ENABLE_NWP_POWER_SAVE in the example project (compile-time) and need the order of operations: initialize wireless/BLE, start GAP advertise or scan per BLE_ROLE, then request NWP sleep; on disconnect, return to active radio policy, optionally restart advertise/scan, and re-enter PSP.

Setup (Illustrative)#

Boot configuration (abbreviated): the device configuration passed to sl_wifi_init() sets low-power–oriented feature bits (for example SL_SI91X_EXT_FEAT_LOW_POWER_MODE, SL_SI91X_ENABLE_ENHANCED_MAX_PSP) alongside SL_SI91X_WLAN_BLE_MODE. Exact bit maps are in the example project’s app.c.

Entering power save after GAP is running: the example project defines rsi_initiate_power_save() (guarded by ENABLE_NWP_POWER_SAVE) to call rsi_bt_power_save_profile(PSP_MODE, PSP_TYPE) for BLE, then sl_wifi_set_performance_profile_v2(&wifi_profile) with a profile such as ASSOCIATED_POWER_SAVE_LOW_LATENCY. The main task calls it once after rsi_ble_start_advertising() / rsi_ble_start_scanning() when powersave_cmd_given is clear.

#if ENABLE_NWP_POWER_SAVE
int32_t rsi_initiate_power_save(void)
{
  int32_t status = rsi_bt_power_save_profile(PSP_MODE, PSP_TYPE);
  if (status != RSI_SUCCESS) {
    return status;
  }
  status = sl_wifi_set_performance_profile_v2(&wifi_profile); // ASSOCIATED_POWER_SAVE_LOW_LATENCY in this example
  return status;
}
#endif

// After start advertising / start scanning:
#if ENABLE_NWP_POWER_SAVE
  if (!powersave_cmd_given) {
    status = rsi_initiate_power_save();
    if (status != RSI_SUCCESS) {
      return;
    }
    powersave_cmd_given = 1;
  }
#endif

Idle application task: when no BLE app event is pending, the example either waits on ble_main_task_sem or, with SL_SI91X_TICKLESS_MODE == 0 and MCU interface builds, calls sl_si91x_power_manager_sleep() when the handshake allows M4 sleep.

Disconnect path: the example sets active Bluetooth profile (rsi_bt_power_save_profile(RSI_ACTIVE, PSP_TYPE)), switches Wi‑Fi profile to high performance, restarts advertise or scan if needed, then applies rsi_bt_power_save_profile(PSP_MODE, PSP_TYPE) again with wifi_profile.profile = ASSOCIATED_POWER_SAVE and sl_wifi_set_performance_profile_v2() to return to coordinated sleep.

Further reading: the example project’s readme.md, Power Management Developer Guide, GAP — usage scenarios for role-based advertise/scan (BLE_ROLE) without repeating NWP policy here.


SDK Example Projects (examples/snippets/ble/)#

The table lists example folder names and how they map to this guide. Descriptions are summarized from each example’s readme.md Purpose/Scope in the SDK (Bluetooth demonstration scope, not a verbatim copy). Application source files in those folders are not reproduced here; open the project in the SDK or clone the GitHub examples tree.

Example folder

Summary (from SDK readme intent)

Typical guide links

ble_central

SiWx91x as central, connects to a remote BLE device

Central role, GATT client

ble_ae_central

Extended advertising central: scan sets, 1M and Coded PHY

Central role, Extended advertising

ble_ae_peripheral

AE peripheral: two advertising sets; extended advertising (Use Case 5); periodic advertising when PERIODIC_ADV_EN is enabled (Use Case 6)

Peripheral role, Extended advertising

ble_ibeacon

iBeacon payload in advertising (peripheral-oriented)

Broadcaster role

ble_accept_list

Accept list / filtered connection (controller LL)

Central role

ble_datalength

Data Length Extension with a connected peer (central role in readme)

Data length extension

ble_longrange_2mbps

PHY update (Coded vs 2M)

BLE initialization and configuration (PHY), GAP

ble_power_save

NWP + Wi‑Fi coordinated power save (PSP, performance profiles); GAP advertise/scan by BLE_ROLE

BLE NWP power save example, Peripheral role, Power Management Developer Guide

ble_privacy

LE privacy, IRK, resolving list; peripheral and central test paths in readme

LE Privacy, Pairing and bonding

ble_secureconnection

Peripheral connection, SMP pairing, encryption enabled

Pairing and bonding, GATT server

ble_multiconnection_gatt_test

Multiple connections as central or peripheral

Central role, GATT client

ble_throughput_app

Throughput / continuous data for measurement

BLE architecture, Data length extension

ble_unified_ae_coex_app

Extended advertising central/peripheral in a coex-oriented app

Extended advertising

ble_hid_on_gatt

HID over GATT — GATT server and client read/notify/indicate

GATT server, GATT client

ble_heart_rate_profile

Heart Rate service as GATT server, indications

GATT server, SIG profiles support

gatt_long_read

Long read when data exceeds negotiated MTU

GATT client, GATT server

bt_stack_bypass

Raw HCI over UART

RCP mode (HCI-oriented flows)

Wi‑Fi + BLE: Larger samples under examples/snippets/wlan_ble/ (for example unified coex apps) are summarized on Processing modes - usage scenarios .


Cross-Area Scenario (Example): Central, Connect, Pair, and Access GATT#

This flow combines GAP (central), SMP, and GATT client behavior. Use it as a reading order; detailed steps and APIs are on the linked topic pages and in SDK readmes.

Overview#

A device in central role scans for a peripheral, establishes a link, runs pairing so encryption can be used, then performs GATT discovery and read/write as needed. The SDK example ble_secureconnection emphasizes peripheral-side pairing and encryption with a remote device; a central-centric path is covered in ble_central and GATT-oriented examples (ble_hid_on_gatt, ble_heart_rate_profile) depending on profile.

Procedure#

  1. Initialize wireless and BLE stack; register callbacks per BLE initialization and configuration.

  2. Configure scanning (legacy or extended per application); start scan (see Central role).

  3. Connect to the selected peer when discovered.

  4. Pair if the application requires authenticated or encrypted access (see Pairing and bonding); confirm encryption active through stack events.

  5. Discover services and characteristics; read/write/subscribe as required (see GATT client).

  6. Disconnect or maintain the link per product logic; handle errors per Debugging and error handling.

SDK Examples to Open First#

Goal

Example folder

Notes

Central connection

ble_central

Readme: connect SiWx91x as central to a remote device

Pairing + encryption (peripheral-oriented demo)

ble_secureconnection

Readme: peripheral role, pairing, SMP encryption

GATT client/server interaction

ble_hid_on_gatt

Readme: server and client procedures


APIs Used in This Section#

Topic

APIs / symbols

Reference

Hub (navigation)

(none specific)

BLE API Reference guide

Application task and BLE event handling

Application-defined RSI_APP_EVENT_*, rsi_ble_app_set_event(), rsi_ble_app_clear_event(), rsi_ble_app_get_event(), osSemaphoreNew / osSemaphoreAcquire / osSemaphoreRelease (CMSIS-RTOS2); not WiSeConnect BLE API symbols

Example project app.c files; CMSIS-RTOS2

BLE NWP power save (ble_power_save)

rsi_bt_power_save_profile(), sl_wifi_set_performance_profile_v2(), optional sl_si91x_power_manager_sleep(); PSP_MODE / PSP_TYPE / RSI_ACTIVE from example project headers

examples/snippets/ble/ble_power_save/app.c; Wi‑Fi API as used for profiles; Power Management Developer Guide

Typical cross-area flow

rsi_ble_gap_register_callbacks(), rsi_ble_gatt_register_callbacks(), rsi_ble_smp_register_callbacks(), rsi_ble_start_scanning(), rsi_ble_connect(), pairing/encryption and GATT APIs as used in your build

GAP, Synchronous Client, Register Callbacks, Callbacks Declarations

Integration: BLE API reference; stack setup BLE initialization and configuration; Developing with WiSeConnect SDK.