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) | Host–Network Processor (NWP) integration and mode-specific setup | |
GAP (roles, advertising, scanning, privacy, DLE, connection parameters) | Peripheral, central, broadcaster, observer, extended advertising, periodic advertising / sync, privacy, DLE, LL connection parameter update | |
GATT (server, client, profiles) | Services, discovery, read/write, notify/indicate, profiles | |
SMP (pairing, bonding, encryption) | 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 exampleUNDIR_CONNvsUNDIR_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 withrsi_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_ALLRelated: 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:
Maintains a bit-mapped application event map (often two
uint32_tvalues for up to 64 distinct event IDs).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 (commonlyosSemaphoreRelease(ble_main_task_sem)).Runs a
while (1)loop that waits for the semaphore when idle, then dispatches the next pending event in aswitchand 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_SAVEin the example project (compile-time) and need the order of operations: initialize wireless/BLE, start GAP advertise or scan perBLE_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;
}
#endifIdle 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 |
|---|---|---|
| SiWx91x as central, connects to a remote BLE device | |
| Extended advertising central: scan sets, 1M and Coded PHY | |
| AE peripheral: two advertising sets; extended advertising (Use Case 5); periodic advertising when | |
| iBeacon payload in advertising (peripheral-oriented) | |
| Accept list / filtered connection (controller LL) | |
| Data Length Extension with a connected peer (central role in readme) | |
| PHY update (Coded vs 2M) | |
| NWP + Wi‑Fi coordinated power save (PSP, performance profiles); GAP advertise/scan by | BLE NWP power save example, Peripheral role, Power Management Developer Guide |
| LE privacy, IRK, resolving list; peripheral and central test paths in readme | |
| Peripheral connection, SMP pairing, encryption enabled | |
| Multiple connections as central or peripheral | |
| Throughput / continuous data for measurement | |
| Extended advertising central/peripheral in a coex-oriented app | |
| HID over GATT — GATT server and client read/notify/indicate | |
| Heart Rate service as GATT server, indications | |
| Long read when data exceeds negotiated MTU | |
| 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#
Initialize wireless and BLE stack; register callbacks per BLE initialization and configuration.
Configure scanning (legacy or extended per application); start scan (see Central role).
Connect to the selected peer when discovered.
Pair if the application requires authenticated or encrypted access (see Pairing and bonding); confirm encryption active through stack events.
Discover services and characteristics; read/write/subscribe as required (see GATT client).
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 |
| Readme: connect SiWx91x as central to a remote device |
Pairing + encryption (peripheral-oriented demo) |
| Readme: peripheral role, pairing, SMP encryption |
GATT client/server interaction |
| Readme: server and client procedures |
APIs Used in This Section#
Topic | APIs / symbols | Reference |
|---|---|---|
Hub (navigation) | (none specific) | |
Application task and BLE event handling | Application-defined | Example project |
BLE NWP power save ( |
|
|
Typical cross-area flow |
| GAP, Synchronous Client, Register Callbacks, Callbacks Declarations |
Integration: BLE API reference; stack setup BLE initialization and configuration; Developing with WiSeConnect SDK.