Skip to content

extmod/zephyr_ble: Add Zephyr BLE host stack with RP2 port integration.#19

Draft
andrewleech wants to merge 5 commits intoreview/zephyr-ble-corefrom
pr/zephyr-ble-core
Draft

extmod/zephyr_ble: Add Zephyr BLE host stack with RP2 port integration.#19
andrewleech wants to merge 5 commits intoreview/zephyr-ble-corefrom
pr/zephyr-ble-core

Conversation

@andrewleech
Copy link
Owner

Summary

This adds the Zephyr BLE host as a third backend for modbluetooth, integrated as a port-agnostic extmod. The Zephyr host code is compiled against a HAL shim layer (extmod/zephyr_ble/hal/) that replaces Zephyr's kernel primitives (semaphores, work queues, timers, FIFOs, memory slabs) with MicroPython-compatible implementations. This means the Zephyr BLE host runs cooperatively on the main MicroPython task without requiring Zephyr RTOS itself.

This was motivated by limitations in the existing stacks — NimBLE doesn't have an active BLE pre-qualification and is missing some newer BLE features, while BTstack's MicroPython integration lacks pairing/bonding and L2CAP channel support. The Zephyr BLE host stack has active qualification, full feature coverage, and is under active development by multiple silicon vendors.

The RP2 port is the first integration, providing two build variants for Pico W and Pico 2 W:

  • zephyr_ble — cooperative polling from the main task (preferred)
  • zephyr_ble_freertos — HCI processing on a dedicated FreeRTOS task

Also included: a gap_unpair() API addition across all BLE backends, micropython-lib updates for aioble robustness, and bond key persistence via Python secret store callbacks.

flowchart TD
    subgraph "extmod/zephyr_ble (port-agnostic)"
        MOD[modbluetooth_zephyr.c] --> HAL[HAL shim layer]
        HAL --> WORK[work queues]
        HAL --> SEM[semaphores]
        HAL --> TIMER[timers]
        HAL --> FIFO[FIFOs]
        HAL --> H4[HCI H4 transport]
    end

    subgraph "Port integration (e.g. RP2)"
        HCI_DRV[mpzephyrport_rp2.c<br/>CYW43 HCI driver] --> H4
        POLL[main loop polling] --> WORK
    end

    subgraph "Zephyr BLE host (lib/zephyr)"
        HOST[hci_core / gatt / att / smp / l2cap]
    end

    HOST --> MOD
    HCI_DRV --> HOST
Loading

Testing

All 12 BLE multitests passing on Pico W and Pico 2 W (both zephyr_ble variant) with PYBD (NimBLE) as central:
ble_gap_advertise, ble_gap_connect, ble_characteristic, ble_gap_pair, ble_gap_pair_bond, ble_subscribe, ble_irq_calls, ble_gattc_discover_services, ble_l2cap, perf_gatt_notify, perf_l2cap, ble_gap_unpair.

Performance: ~24ms/notification (GATT), ~2184 B/s (L2CAP) on Pico W; ~25ms/notification, ~7956 B/s on Pico 2 W.

Not tested: zephyr_ble_freertos variant on Pico 2 W.

Trade-offs and Alternatives

The HAL shim layer is substantial (~3K lines) because it reimplements Zephyr kernel primitives. The alternative would be running actual Zephyr RTOS, but that would limit this to the Zephyr port only. The shim approach allows any MicroPython port with an HCI transport to use the Zephyr BLE host.

The lib/zephyr submodule adds the full Zephyr BLE host source. Only the host stack files are compiled — no kernel, no drivers, no board support. The submodule is pinned to a specific commit with two small patches (wrapper files for gatt.c and conn.c to expose static internals needed for clean teardown).

MTU is compile-time only (CONFIG_BT_L2CAP_TX_MTU=512); runtime ble.config(mtu=X) is not supported. ble_mtu.py test is skipped.

Generative AI

I used generative AI tools when creating this PR, but a human has checked the code and is responsible for the description above.

Signed-off-by: Andrew Leech <andrew.leech@planetinnovation.com.au>
pi-anl added 4 commits March 6, 2026 16:38
Signed-off-by: Andrew Leech <andrew.leech@planetinnovation.com.au>
Signed-off-by: Andrew Leech <andrew.leech@planetinnovation.com.au>
Signed-off-by: Andrew Leech <andrew.leech@planetinnovation.com.au>
Signed-off-by: Andrew Leech <andrew.leech@planetinnovation.com.au>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants