BERGSONNE

BLE

On the wireless Core, core_ble is a peripheral-mode Bluetooth Low Energy API: advertise a name, define a GATT server with read / write / notify characteristics, and react to connections — all in a few C calls over the ST radio stack.

Overview

Core.ST.W5 only
BLE lives on the wireless Core (STM32WBA55). It needs BLE_ENABLED=1 and the HSE clock. The API is Tier 1 (C-callback driven) — no Studio bindings yet.

The shape of a BLE app: register a service builder before init, bring up the stack, advertise, then pump core_ble_process() from your main loop so the radio gets serviced.

#include "core.h"

int main(void) {
    core_init();
    core_ble_set_services(app_services);   // builder, defined below
    core_ble_enable_pairing();             // optional: Just Works pairing
    core_ble_init();
    core_ble_advertise("Core.ST.W5");

    while (1) {
        core_ble_process();                // must run continuously
    }
}

GATT server

A GATT server is services, each holding characteristics — the values a phone or hub reads, writes, or subscribes to. Build them in your service-builder function. UUIDs are generated from the names you give:

static core_ble_char_t led_char, count_char;

static void on_led_write(const uint8_t *data, uint16_t len, void *ctx) {
    if (data[0]) core_led_on(); else core_led_off();
}

void app_services(void) {
    core_ble_svc_t led = core_ble_add_service("LED Control");
    led_char = core_ble_add_char(led, "LED State", CORE_BLE_RW, CORE_BLE_BOOL,
                                 on_led_write, NULL);

    core_ble_svc_t ctr = core_ble_add_service("Counter");
    count_char = core_ble_add_char(ctr, "Count", CORE_BLE_READ | CORE_BLE_NOTIFY,
                                   CORE_BLE_UINT8, NULL, NULL);
}

Push a new value with core_ble_set_value; if the characteristic is notify-enabled and the central subscribed, core_ble_notify sends it:

uint8_t n = ++counter;
core_ble_set_value(count_char, &n, 1);
core_ble_notify(count_char);

Connections

Poll core_ble_connected(), or register callbacks to react the moment a central connects or drops:

static void on_connect(void *ctx)    { core_led_on(); }
static void on_disconnect(void *ctx) { core_led_off(); }

core_ble_on_connect(on_connect, NULL);
core_ble_on_disconnect(on_disconnect, NULL);

Pairing is optional Just Works — call core_ble_enable_pairing() before init and the phone shows a one-time pair prompt, then reconnects automatically. Central/scanner mode and bonded keys aren’t implemented yet.

Cross-architecture support

BLE is hardware-verified on the wireless Core; the other ST Cores have no radio. The Nordic (nRF54) family will bring BLE to a second architecture behind the same intent.

·L0M0+·L4M4W5M33·H5M33WCH (RISC-V) · Nordic (nRF54) — in development
·L0M0+·L4M4W5M33·H5M33WCH (RISC-V) · Nordic (nRF54) — in development

See the implementation status for the full matrix.

API reference

Lower-level · Tier 1
void core_ble_set_services(void);
Register a service builder function. Called before core_ble_init(). The builder is invoked during init after the GATT server is ready.
void core_ble_init(void);
Initialize the BLE stack. Call once after core_init().
int core_ble_advertise(const char * name);
Start advertising. Call after init + at least one core_ble_process().
int core_ble_stop_advertise(void);
Stop advertising.
void core_ble_process(void);
Process BLE events. Call continuously from main loop.
core_ble_svc_t core_ble_add_service(const char * name);
Add a GATT service. Returns a handle for adding characteristics. The UUID is auto-assigned SEQUENTIALLY by registration order (0000B000-…, 0000B100-…, …). Convenient, but the UUIDs shift if you reorder or insert services — so for a contract shared with client apps, prefer core_ble_add_service_id() to pin a stable, order-independent UUID.
core_ble_svc_t core_ble_add_service_id(const char * name, uint16_t id);
Add a GATT service with an EXPLICIT 16-bit ID. The full UUID is 0000<id>-8E22-4541-9D4C-21EDAE82ED19. Pinning the ID makes the GATT contract independent of registration order — the recommended path when the service map is a source of truth shared with phone / desktop client apps.
core_ble_char_t core_ble_add_char(core_ble_svc_t svc, const char * name, uint8_t access, uint8_t type, core_ble_write_cb on_write, void * ctx);
Add a characteristic to a service.
core_ble_char_t core_ble_add_char_id(core_ble_svc_t svc, const char * name, uint16_t id, uint8_t access, uint8_t type, core_ble_write_cb on_write, void * ctx);
Add a characteristic with an EXPLICIT 16-bit ID (0000<id>-8E22-…), the order-independent counterpart to core_ble_add_char(). Use for the stable contract shared with client apps.
core_ble_svc_t core_ble_add_service_sig(const char * name, uint16_t uuid16);
Add a SIG-adopted service by its 16-bit Bluetooth UUID (e.g. 0x180F Battery Service, 0x180A Device Information). Use adopted services for standardised profiles so generic clients and the host OS recognise them; use the _id variants for custom application-specific data.
core_ble_char_t core_ble_add_char_sig(core_ble_svc_t svc, const char * name, uint16_t uuid16, uint8_t access, uint8_t type, core_ble_write_cb on_write, void * ctx);
Add a SIG-adopted characteristic by its 16-bit Bluetooth UUID (e.g. 0x2A19 Battery Level, 0x2A29 Manufacturer Name) to a service.
int core_ble_set_value(core_ble_char_t ch, const void * data, uint16_t len);
Update a characteristic's value. For readable characteristics, this is what the central will read. For notify characteristics, call core_ble_notify() after to push the update.
int core_ble_notify(core_ble_char_t ch);
Send a notification to the connected central. The central must have enabled notifications (CCCD) for this to work. Sends the current value set by core_ble_set_value().
int core_ble_connected(void);
Returns 1 if a central is connected.
void core_ble_on_connect(void * ctx);
Set callback for connection events.
void core_ble_on_disconnect(void * ctx);
Set callback for disconnection events.
void core_ble_set_tx_power(uint8_t level);
TX power: 0=low(-20dBm), 1=medium(0dBm), 2=high(+10dBm). Default: 1.
void core_ble_set_adv_interval(uint16_t min_ms, uint16_t max_ms);
Advertising interval in ms (20-10240). Default: 100/150.
void core_ble_set_conn_params(uint16_t min_ms, uint16_t max_ms, uint16_t latency, uint16_t timeout_ms);
Request a preferred connection parameter set from the central. The central ultimately owns the connection timing, but a peripheral can ask for parameters that suit its traffic. After each connection the SDK sends an L2CAP update request (retrying until the stack accepts it, since the link is busy with pairing/discovery right after connecting). May also be called while connected to re-request — e.g. tighten the interval while streaming, relax it when idle. For Apple hosts, keep within their guidelines: interval_min >= 15 ms, interval_max >= interval_min + 15 ms, interval_max * (latency + 1) <= 2 s, and timeout in 2000..6000 ms. A short interval lowers latency for high-rate notifications at the cost of power; latency > 0 saves power when the peripheral often has nothing to send.
void core_ble_enable_pairing(void);
Enable OS-level pairing + bonding (Just Works). When enabled, every characteristic is registered behind an encrypted link, so on first access the host runs its pairing flow (a "Pair?" prompt on most OSes; silent for Just Works on macOS). Keys are persisted in flash NVM, so the bond survives resets — the host doesn't re-pair on the next connection and the device stays listed in OS Bluetooth settings. (Reconnect itself is the central's choice; the peripheral simply re-advertises after a drop.) Call before core_ble_init(). Default: disabled (characteristics open, no pairing). Note that once enabled, *all* clients must pair to read/write.

Generated from core_ble.htiles@990ad75.