Skip to content

zephyr-cp: enable BLE on the Raspberry Pi Pico W - #14

Open
tyeth wants to merge 1 commit into
zephyr-pico2w-blefrom
zephyr-picow-ble
Open

zephyr-cp: enable BLE on the Raspberry Pi Pico W#14
tyeth wants to merge 1 commit into
zephyr-pico2w-blefrom
zephyr-picow-ble

Conversation

@tyeth

@tyeth tyeth commented Sep 8, 2026

Copy link
Copy Markdown
Owner

Stacked on #4 (Pico 2 W BLE). Rebased onto main 121489fe70 on 2026-09-08 — the RP2040 boot fix this once needed from #13 is on main (ffd62e1c59), so the image boots on its own.

Same CYW43439 as the Pico 2 W, and the shared-bus HCI driver needed no board-specific code. Only per-board devicetree/config changes were required:

  • Overlay: hang the infineon,cyw43-bt-hci node off the stock infineon,airoc-wifi node and point zephyr,bt-hci at it.
  • Overlay: the settings partition is too small for NVS. It was originally 2 KB at 0x180800, neither erase-sector aligned nor large enough for one of the RP2040's 4 KB sectors; main has since made it one aligned 4 KB sector at 0x17f000, which is still one short of the two nvs_mount() insists on (-EINVAL), so bt_enable() fails before opening the HCI driver. storage becomes 8 KB at 0x17e000, taking the extra sector from the code partition. nvm (0x180000) and circuitpy (0x181000) stay where ports/raspberrypi has them, as cptools/check_partitions.py requires, so CIRCUITPY is not reformatted.
  • Conf: BT_EXT_ADV=n (this controller rejects the Bluetooth 5 extended commands — see zephyr-cp: BT_EXT_ADV defaults on for every board, asserting a controller capability that is not universal #8) plus a deeper system workqueue stack.

HW_STACK_PROTECTION is deliberately left off here. It earned its place on the Cortex-M33, where it turned several silent corruptions into clean named faults, but it costs RAM and this is the constrained board (and the RP2040 has no MPU anyway).

Verified on hardware

=== BLE SCAN TEST ===
adapter address: <Address 2c:cf:67:d8:d4:a5>
adapter name: CIRCUITPYd4a5
scanning 20s ...
     113ms  rssi= -83  <Address 54:32:04:0c:d7:56>  HUB-D754
  >>> FOUND TARGET: HUB-D754 ... rssi -80 / -83 / -88 / -91  (sustained)

First advertiser at 113 ms, then continuous tracking. The board's WiFi MAC is 2C:CF:67:D8:D4:A3 and the BLE adapter comes up as ...:D8:D4:A5 — MAC + 2, this part's OTP offset, derived through the CYW43439 shared-bus path (the Pico 2 W's is MAC + 1).

That run used the pre-rebase layout (settings at 0x181000). The 0x17e000 placement is build-tested only so far.

Size (post-rebase head)

BOOT_FLASH:       256 B /       256 B  100.00%
FLASH:      1,181,372 B / 1,564,416 B   75.52%
RAM:          228,044 B /      264 KB   84.36%   (~41 KB free)

BLE costs about 26 KB of RAM here. Tight but it fits with no stack trimming.

CI cannot link this until tyeth/zephyr#1 lands and the manifest points at a revision with the driver — see #16.

🤖 Generated with Claude Code

@tyeth

tyeth commented Sep 8, 2026

Copy link
Copy Markdown
Owner Author

⚠️ CI board builds fail to link on this branch — expected, tracked as #16.

undefined reference to __device_dts_ord_8…`` from hci_core.c: the DT node and `CONFIG_BT` are present, but the CYW43 HCI driver that defines that device is not in the zephyr revision the manifest pins (`adafruit/zephyr @ 62e7a3764`). Needs tyeth/zephyr#1 to land and the manifest bumped. Builds fine locally against the fork branch carrying the driver, and `ci/pico2w-ble-assets` is green only because of the CI-only override (#12).

Not the same failure as #11, which is the tests / zephyr native_sim job.

🤖 Generated with Claude Code

Same CYW43439 as the Pico 2 W, and the shared-bus HCI driver needed no
board-specific work, so this is the Pico 2 W change applied to the RP2040
board:

- overlay: hang the infineon,cyw43-bt-hci node off the stock
  infineon,airoc-wifi node and point zephyr,bt-hci at it.
- overlay: the settings partition had the same defect as the Pico 2 W's --
  originally 2K at 0x180800, neither erase-sector aligned nor big enough
  for one of the RP2040's 4K sectors; main has since made it one aligned
  4K sector at 0x17f000, which is still one short of the two nvs_mount()
  insists on, so bt_enable() fails before opening the HCI driver. Give
  settings two sectors at 0x17e000, taken from the code partition. nvm
  and circuitpy stay at 0x180000 and 0x181000 to match ports/raspberrypi
  (cptools/check_partitions.py checks this), so CIRCUITPY is not moved.
- conf: BT_EXT_ADV=n, since this controller rejects the Bluetooth 5
  extended advertising commands, plus a deeper system workqueue stack.

HW_STACK_PROTECTION is deliberately left off here: it earned its place on
the Cortex-M33 but costs RAM, and this is the constrained board.

Builds at 68.67% flash and 84.32% RAM of 264K, so BLE fits with about 42K
to spare.

Verified on hardware after the "ranges" fix (now on main): the adapter
comes up as WiFi MAC + 2 and a legacy LE scan returns nearby advertisers.
That run used the earlier layout with settings at 0x181000; the 0x17e000
placement is build-tested only.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@tyeth

tyeth commented Sep 8, 2026

Copy link
Copy Markdown
Owner Author

Rebased onto main 121489fe70 via the rebased #4 (force-pushed with --force-with-lease). New head 8d2023c6b5, previously 8ac1521d25. One commit, as before.

What moved. main d0f27bfc97 relocated the files this PR edits:

was now
boards/rpi_pico_rp2040_w.overlay boards/raspberrypi/rpi_pico_w_zephyr/board.overlay
boards/rpi_pico_rp2040_w.conf boards/raspberrypi/rpi_pico_w_zephyr/board.conf

Git followed the renames; board.conf and autogen_board_info.toml applied cleanly. board.overlay had the same two conflicts as #4 (#include "../../../app.overlay", and the partition layout) and got the same resolution: storage is 8K at 0x17e000, taken from the code partition (now 0x100..0x17e000); nvm stays at 0x180000 and circuitpy at 0x181000, which main's new check_partitions.py parity check requires for boards with a counterpart. So, unlike the original commit, CIRCUITPY is not reformatted. Commit message reworded accordingly.

ranges; was not re-added by this branch — main already has it (ffd62e1c59), which also means the "also needs #13" dependency in the description is gone; #13 is closed as redundant and this branch boots on its own. The BOOT_FLASH region below shows boot2 is linked.

Build on the new head (make BOARD=raspberrypi_rpi_pico_w_zephyr, local zephyr tree with the driver):

value
BOOT_FLASH 256 B / 256 B
FLASH 1,181,372 B / 1,564,416 B = 75.52%
RAM 228,044 B / 264 KB = 84.36%
CONFIG_BT / CONFIG_BT_CYW43_SHARED_BUS y / y
CONFIG_BT_EXT_ADV not set
CONFIG_HW_STACK_PROTECTION absent (deliberate, and RP2040 has no MPU)
DT_CHOSEN_zephyr_bt_hci .../pio0_spi0/airoc_wifi_0/cyw43_bt_hci
check_partitions.py ok (5 partitions), matches ports/raspberrypi/raspberry_pi_pico_w

RAM is essentially unchanged from the description (84.32% → 84.36%); flash is up from 68.67% because the code partition is 8K smaller and main grew. Still ~41 KB of RAM to spare.

Caveats: the hardware run in the description used the earlier 0x181000 settings placement; 0x17e000 is build-tested only. CI will still fail to link here (#16): the branch now inherits main's west.yml pin (adafruit/zephyr @ 52dc937c7c), which predates the HCI driver.

🤖 Generated with Claude Code

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.

1 participant