|
SDK for TESAIoT Dev Kit
API reference & tutorials (ModusToolbox)
|
The BLE bring-up block in proj_cm33_ns/main.c is independent of BENTO_HAS_MPY. The MicroPython guard and bindings shown as text are mtb-mpy only.
Bring the BLE NUS stack up in the two-layer order the firmware uses, understand why the chip-power task must own ble_nus_init, and see the single-RF exclusivity rule refuse WiFi from Python — and the one build in which that rule is skipped.
Layer 1 — the chip-power task. WL_REG_ON is asserted after a 1.5 s settle, then 50 ms for the HCI controller to power up, then bento_buddy_request_start():
bento_buddy_request_start returns 0 = newly started, 1 = already running, −1 = init failed or mutex timeout (ble_nus_lazy.c:152-156). It takes a mutex with a 1000 ms timeout (:161) — FreeRTOS task only, never main() or an ISR. The boot-time owner of ble_nus_init must be this dedicated task: calling it from any other context fails with state=ERROR (main.c:326-334).
Layer 2 — the radio scheduler, initialised after the auto-start is queued so it does not race AIROC init; set_on_state is a bare assignment and must precede init, which fires the first state transition (radio_scheduler.c:319):
radio_scheduler_init is legal pre-scheduler (static mutex/queue + xTaskCreate); it returns true on success or on double-init, false only when xTaskCreate fails; persist_boot_mode/load_boot_mode may be NULL (fallback RADIO_BOOT_AUTO). Its worker delays 3000 ms before servicing the queue. nus_radio_emit_state_event is used only as a function pointer — never called directly.
The CM33-side IPC receiver must be armed before the first CM55 tap; on mtb-mpy it is registered at boot in mpy_main.c:604-623 (ipc_bento_buddy_rx_init(), printing [MPY] bento_buddy IPC RX init: OK), and is also lazily self-registered inside bento_buddy_request_start (ble_nus_lazy.c:183-186) — double registration is documented and tolerated.
Stop is soft. bento_buddy_request_stop() (ble_nus_lazy.c:227-245) is void with no error signal; the AIROC stack stays resident, so a later start takes ble_nus_rearm_advertising() (:176) rather than re-init. The MicroPython bindings are modbentobuddy.c:29-44 (bento_buddy.start() raises OSError on −1; stop() returns None).
The single-RF rule. CYW55513 has one RF path. The canonical guard is the [ble_radio_scheduler_single_rf_guard] marker region at modwifi.c:54-81 (mtb-mpy), quoted here with one elision, marked:
(modwifi.c:54-81 less the elided comment, shown as text because that file is not shipped in the mtb-only package. Note the #include "../ble_nus/radio_scheduler.h" at modwifi.c:70 — code that copies this guard needs it.) radio_scheduler_get_mode() is a lock-free single-enum read, callable from any context, and returns RADIO_MODE_UNKNOWN before init. The exception: under BENTO_HAS_DUAL_BAND == 1 the guard is compiled out, because the on-die COEX arbiter time-slices WiFi and BLE.
What you should observe. Without getlibs, the build stops at the $(error) quoted above. With it, three cores report complete.
Flash, power-cycle, open the console at 115200.
What you should observe, in this order and exactly these strings:
On mtb-mpy, [MPY] bento_buddy IPC RX init: OK precedes them. The topbar BLE glyph follows the 500 ms ble_nus_get_state() poll (Chapter I2).
What you should observe. OSError: WiFi unavailable: BLE is active. Use the Desktop Buddy or call bento_buddy.stop() to switch radio mode first. No [wifi-glue] line appears — the refusal is before app_wifi_init().
What you should observe. The desktop receives a bento.radio.state event (Chapter I2 shows its shape) as the scheduler transitions; a subsequent wifi.connect() proceeds and [wifi-glue] retry lines appear (wifi_init.c:225-242). bento_buddy.start() afterwards takes the rearm path and returns 1 if the stack was still resident.
| mtb-mpy | mtb-only | |
|---|---|---|
| Bring-up block | main.c:325-357, identical | identical |
| Start/stop from user code | bento_buddy.start()/stop() | Your own task calling bento_buddy_request_start()/stop(); CM55 page buttons over IPC |
| Single-RF refusal | Python OSError | No Python path; the C app_wifi_* overrides in wifi_init.c are not guarded by the scheduler — your own code must consult radio_scheduler_get_mode() |
| Console | [MPY] RX-init line + [boot] lines | [boot] lines + [HB] |