SDK for TESAIoT Dev Kit
API reference & tutorials (ModusToolbox)
Loading...
Searching...
No Matches

Functions

void radio_scheduler_set_on_state (radio_scheduler_on_state_fn_t cb)
 Install the state hook; must precede radio_scheduler_init() or the first transition is missed.
bool radio_scheduler_init (const radio_scheduler_config_t *cfg)
 Create the arbiter (legal pre-scheduler); true on success or double-init.
void nus_radio_emit_state_event (const struct radio_status_s *st)
 The shipped on_state hook — only ever used as a function pointer, never called directly.
radio_mode_t radio_scheduler_get_mode (void)
 Lock-free mode read — the canonical single-RF Wi-Fi/BLE exclusivity guard.
void radio_scheduler_get_status (radio_status_t *out)
 Full status snapshot under the scheduler mutex, 50 ms timeout; copy ssid out.
bool radio_scheduler_request_mode (radio_mode_t target)
 Queue an asynchronous mode transition; confirm via the hook or by polling the mode.
bool radio_scheduler_set_wifi_creds (const char *ssid, const char *password, const char *security, bool auto_switch)
 Save Wi-Fi credentials through the consumer's LFS hook, optionally queueing the switch.
void radio_scheduler_set_boot_mode (radio_boot_mode_t mode)
 Persist a boot preference through the persist hook; with NULL hooks nothing survives reboot.
radio_boot_mode_t radio_scheduler_get_boot_mode (void)
 The persisted boot mode; with the shipped NULL hooks every boot loads as AUTO.
const char * radio_mode_str (radio_mode_t m)
 Pure mode-to-string map; static literal, out-of-range returns "invalid" — s is safe.

Detailed Description

Ten symbols: the single-RF BLE / Wi-Fi arbiter (radio_scheduler_*, radio_mode_str) and its state-event emitter (nus_radio_emit_state_event). Compiled only with ENABLE_PAGE_BENTO_BUDDY=1 (default 0, proj_cm33_ns/Makefile:64, :305); rebuild after make getlibs — Flag gate (read first).

Declarations: radio_scheduler.h (all radio_scheduler_*, radio_mode_str, the radio_status_t / radio_scheduler_config_t types) and nus_commands.h (nus_radio_emit_state_event). Implementation radio_scheduler.c / nus_commands.c is archived in libbento_secure.a.

The three symbols radio_scheduler_set_on_state(), radio_scheduler_init() and nus_radio_emit_state_event() occur in one shipped block (proj_cm33_ns/main.c:325-357) — documenting them together is what the firmware does. That block, rendered once:

#if ENABLE_PAGE_BENTO_BUDDY
/* Two-layer BLE bring-up:
*
* 1. bento_buddy_auto_start_install — the legacy 3-s-delayed task
* that brings up the AIROC BLE host stack. Proven path: kept as
* the boot-time owner of ble_nus_init. Smoke tests showed that
* calling ble_nus_init from any other context (notably the
* radio_scheduler worker) fails with state=ERROR even with the
* same 3-s delay — the original task's stack/priority is what
* the AIROC HCI bring-up actually needs.
*
* 2. radio_scheduler — runtime arbiter for BLE↔Wi-Fi mode switches.
* Initialised AFTER auto_start so it doesn't race the AIROC init.
* Phase 1 only services the verbs (radio.status / radio.switch /
* wifi.set_creds) and persists creds; the actual swap-radio path
* is exercised by user action, not at boot. Saved-creds auto-Wi-Fi
* moves to Phase 2 once the persistence hooks (LFS boot_mode +
* LCD long-press) are wired. */
{
/* Replace bento_buddy_auto_start_install with our chip-power-then-BLE
* variant — the legacy task skipped the WL_REG_ON / WCM init step,
* which CYW55513 needs for BLE controller bring-up. */
install_chip_power_then_ble();
extern void nus_radio_emit_state_event(const struct radio_status_s *st);
.persist_boot_mode = NULL,
.load_boot_mode = NULL,
};
(void)radio_scheduler_init(&cfg);
}
#endif
Variant
mtb-mpy and mtb-only

Function Documentation

◆ radio_scheduler_set_on_state()

void radio_scheduler_set_on_state ( radio_scheduler_on_state_fn_t cb)

Install the state hook; must precede radio_scheduler_init() or the first transition is missed.

Contract
Must precede radio_scheduler_init() — it is a bare assignment with no lock (radio_scheduler.c:418-421), and radio_scheduler_init() fires the first state transition at radio_scheduler.c:319; a hook set afterwards misses that transition. The shipped firmware wires it to nus_radio_emit_state_event(). Template call sites: 1 (the block rendered in Radio scheduler).
Variant
mtb-mpy and mtb-only

◆ radio_scheduler_init()

bool radio_scheduler_init ( const radio_scheduler_config_t * cfg)

Create the arbiter (legal pre-scheduler); true on success or double-init.

Contract
Legal pre-scheduler — it uses xSemaphoreCreateMutexStatic, xQueueCreateStatic and xTaskCreate (radio_scheduler.c:279-287) and the shipped call is from main() before vTaskStartScheduler(). Initialise it after the BLE auto-start is queued so it does not race the AIROC init (main.c:336-337). Returns true on success or on double-init (deliberate re-entry guard, :271-275); false only if xTaskCreate fails. cfg.persist_boot_mode / cfg.load_boot_mode may legitimately be NULL (:291-294, :403-416 null-check them and fall back to RADIO_BOOT_AUTO). The worker task delays 3000 ms before servicing the queue (radio_scheduler.c:238) for the AIROC-settle reason. The shipped caller (void)-casts the return. Template call sites: 1 (the block rendered in Radio scheduler).
Variant
mtb-mpy and mtb-only

◆ nus_radio_emit_state_event()

void nus_radio_emit_state_event ( const struct radio_status_s * st)

The shipped on_state hook — only ever used as a function pointer, never called directly.

Contract
Only ever used as a function pointer — passed to radio_scheduler_set_on_state(), never called directly. Its body (nus_commands.c:1443-1469) null-checks st, formats a bento.radio.state event and calls nus_emit_event(); it lives in nus_commands.c so radio_scheduler.c need not depend on the NUS framer. Template call sites: 1 (the block rendered in Radio scheduler, as a pointer; the local extern at main.c:349 uses the forward-declared struct tag).
Variant
mtb-mpy and mtb-only
Origin
Lifted from BENTO-TESAIoT-libraries/claw/common/ble_nus/nus_commands.c:1443-1469 (compiled into the prebuilt archive; not shipped as source).

◆ radio_scheduler_get_mode()

radio_mode_t radio_scheduler_get_mode ( void )

Lock-free mode read — the canonical single-RF Wi-Fi/BLE exclusivity guard.

Contract
Lock-free — "Reads of a single enum are atomic on Cortex-M33; skip the mutex" (radio_scheduler.c:387); callable from any context including the MicroPython REPL. Returns RADIO_MODE_UNKNOWN before radio_scheduler_init(). It is the canonical single-RF Wi-Fi/BLE exclusivity guard, and that guard is build-conditional: skipped under BENTO_HAS_DUAL_BAND == 1 because CYW55513's on-die COEX time-slices Wi-Fi and BLE. Wi-Fi is permitted only in RADIO_MODE_WIFI_ACTIVE, RADIO_MODE_SWITCHING_TO_WIFI and RADIO_MODE_WIFI_FAILED (retry path). For a full snapshot use radio_scheduler_get_status() (mutex, 50 ms timeout). Template call sites: 1.
Variant
mtb-mpy and mtb-only
Only template call site (mtb-mpy zip only, cited as text)
bento_libs/claw/common/mpy/modwifi.c:52-79, marker tag ble_radio_scheduler_single_rf_guard — under BENTO_HAS_BLE_NUS == 1 && !BENTO_HAS_DUAL_BAND, wifi.connect() reads the mode and raises OSError("WiFi unavailable: BLE is active. Use the Desktop Buddy or call bento_buddy.stop() to switch radio mode first.") unless one of the three Wi-Fi modes is current.

The archived definition (rendered with radio_scheduler_get_status()) shows the mutex-free read.

◆ radio_scheduler_get_status()

void radio_scheduler_get_status ( radio_status_t * out)

Full status snapshot under the scheduler mutex, 50 ms timeout; copy ssid out.

Contract
Takes the scheduler mutex with a 50 ms timeout; on timeout it zeroes *out and fills only mode (radio_scheduler.c:391-401). The ssid field points into scheduler-owned storage, valid until the next mode transition — copy it out before leaving the calling context. NULL out is ignored. Task context (mutex). Template call sites: 0; archived call site nus_commands.c:1349 (radio_scheduler_get_status(&st);, the status verb — compiled into libbento_secure.a, not shipped as source).
Variant
mtb-mpy and mtb-only
Origin
Lifted from BENTO-TESAIoT-libraries/claw/common/ble_nus/radio_scheduler.c:385-401 (compiled into the prebuilt archive; not shipped as source).

◆ radio_scheduler_request_mode()

bool radio_scheduler_request_mode ( radio_mode_t target)

Queue an asynchronous mode transition; confirm via the hook or by polling the mode.

Contract
Idempotent — requesting the current mode is a no-op. Returns true if the transition was queued, false if rejected (e.g. Wi-Fi without saved credentials). The change is asynchronous: confirm via the on_state hook or by polling radio_scheduler_get_mode(). Template call sites: 0; archived call site nus_commands.c:1389 (if (!radio_scheduler_request_mode(want)) { — the bento.radio.set verb nacks on false; compiled into libbento_secure.a, not shipped as source).
Variant
mtb-mpy and mtb-only

◆ radio_scheduler_set_wifi_creds()

bool radio_scheduler_set_wifi_creds ( const char * ssid,
const char * password,
const char * security,
bool auto_switch )

Save Wi-Fi credentials through the consumer's LFS hook, optionally queueing the switch.

Contract
Saves credentials through the consumer's lfs_save_wifi_creds hook (WiFi overridables (implement, don't call)); with auto_switch = true it also queues a transition to Wi-Fi after the save. Returns false on validation failure (SSID too long, etc.) or LFS write failure. Task context (the hook writes flash). Template call sites: 0; archived call site nus_commands.c:1429 (if (!radio_scheduler_set_wifi_creds(ssid, pass, sec[0] ? sec : NULL, ... — empty security string is passed as NULL; compiled into libbento_secure.a, not shipped as source).
Variant
mtb-mpy and mtb-only

◆ radio_scheduler_set_boot_mode()

void radio_scheduler_set_boot_mode ( radio_boot_mode_t mode)

Persist a boot preference through the persist hook; with NULL hooks nothing survives reboot.

Contract
Persists a boot preference through the persist_boot_mode hook supplied at init. With NULL hooks — the shipped default (main.c:350-353) — nothing survives the reboot and the next boot decides as RADIO_BOOT_AUTO. It does not switch the radio; that is radio_scheduler_request_mode(). No caller anywhere.
Variant
mtb-mpy and mtb-only
Example (authored — no shipped call site)
static void bento_ex_radio_scheduler_set_boot_mode(void)
{
/* LCD long-press handler: pin this board to BLE across reboots
* (takes effect only if persistence hooks were supplied at init): */
/* Escape hatch after a router move — force the next boot to try
* Wi-Fi even though the last three connects failed:
* radio_scheduler_set_boot_mode(RADIO_BOOT_FORCE_WIFI);
*/
}

◆ radio_scheduler_get_boot_mode()

radio_boot_mode_t radio_scheduler_get_boot_mode ( void )

The persisted boot mode; with the shipped NULL hooks every boot loads as AUTO.

Contract
Returns the persisted boot mode (AUTO / FORCE_BLE / FORCE_WIFI). Same NULL-hook story as radio_scheduler_set_boot_mode(): with the shipped configuration every boot loads as RADIO_BOOT_AUTO. No caller anywhere.
Variant
mtb-mpy and mtb-only
Example (authored — no shipped call site)
static void bento_ex_radio_scheduler_get_boot_mode(void)
{
if (bm != RADIO_BOOT_AUTO) {
/* User override in force (FORCE_BLE / FORCE_WIFI) — render the
* "override" badge. With NULL persistence hooks this branch is
* unreachable across reboots: everything loads as AUTO. */
}
}

◆ radio_mode_str()

const char * radio_mode_str ( radio_mode_t m)

Pure mode-to-string map; static literal, out-of-range returns "invalid" — s is safe.

Contract
Pure, reentrant, no init required. Returns a static string literal — never free or mutate it. Out-of-range values return "invalid" (radio_scheduler.c:116), so s is unconditionally safe. Wire vocabulary: unknown | ble_adv | ble_paired | switching_to_wifi | wifi_active | switching_to_ble | wifi_failed. Template call sites: 0 (archived: 3).
Variant
mtb-mpy and mtb-only
Origin
Lifted from BENTO-TESAIoT-libraries/claw/common/ble_nus/nus_commands.c:1443-1469 (compiled into the prebuilt archive; not shipped as source).