Skip to content

zephyr-cp/wifi: bound the scan wait and run background tasks - #11214

Open
mikeysklar wants to merge 1 commit into
adafruit:mainfrom
mikeysklar:fix/zephyr-scan-poll-timeout-upstream
Open

zephyr-cp/wifi: bound the scan wait and run background tasks#11214
mikeysklar wants to merge 1 commit into
adafruit:mainfrom
mikeysklar:fix/zephyr-scan-poll-timeout-upstream

Conversation

@mikeysklar

Copy link
Copy Markdown
Collaborator

What

common_hal_wifi_scannednetworks_next() waited with k_poll(K_FOREVER). That wait ends only on a result, a channel_done signal, or ctrl-C. Nothing guarantees any of those arrive, so if the driver stops reporting there is no way out of the loop.

This is a defensive bound, not a fix for an observed field failure. A normal scan is unaffected: results arrive steadily and the loop cycles well inside the limit.

Why

espressif and raspberrypi both bound their equivalent loops and run background tasks inside them:

  • ports/espressif/common-hal/wifi/ScannedNetworks.c:39
  • ports/raspberrypi/common-hal/wifi/ScannedNetworks.c:67

zephyr-cp did neither.

How

Poll in 50 ms slices with background tasks between them, and end the scan if nothing arrives for 10 s. The window restarts whenever a channel completes, so the limit is on the driver going quiet rather than on how long a full sweep takes.

Elapsed time is an unsigned subtraction from the start, which stays correct across the 32-bit millisecond rollover. The start timestamp is a local, so this adds no per-object state.

Testing

One board, one host, before and after builds from the same tree on the same day.

  • Board: Silicon Labs SiWx917 Dev Kit, DK2605A Rev A00 (BRD2605A), part SiWG917M111MGTBA
  • Host: Linux, flashed with Simplicity Commander over the onboard J-Link
  • CircuitPython 10.3.0-alpha.4-63-g88c0b27e1a-dirty, built 2026-08-18

Both builds report the same version string, because only working tree files differ between them and that is what -dirty covers. The two images are distinguished by the build log: RUN_BACKGROUND_TASKS appears 0 times in the before image and 1 time in the after image.

Method: hard reset the board, run one scan to completion, and poll /cp/version.json from the host every 0.25 s throughout, recording HTTP status and response time for the samples that fall inside the scan window.

before after
RUN_BACKGROUND_TASKS in build 0 1
networks found 64 56
scan duration 7.66 s 7.79 s
web workflow during scan 12/12 HTTP 200 20/20 HTTP 200
response time during scan 0.13 s to 0.70 s 0.13 s to 0.20 s
flash 2388276 B 2388419 B (+143)

No regression: scanning works the same and the web workflow stays served.

The difference in network count is ordinary RF variance between runs, not an effect of the patch. A separate clean scan on the before image returned 73 networks in 6.68 s.

Worst case response time during a scan was lower on the after image, which is the direction adding RUN_BACKGROUND_TASKS would predict. This is one run per side, so treat it as an observation rather than a measured result.

Not tested: the timeout path itself. Reaching it needs the driver to stop delivering results, which I could not induce on demand. A second DK2605A was available but on a host without flashing tools, so all results above are from a single board.

Scope

Bounds the wait and runs background tasks. Does not change how results are collected or deduplicated.

AI assistance

Written with Claude Code. I ran the hardware myself. The numbers above are from the board, not from a model.

common_hal_wifi_scannednetworks_next() waited with k_poll(K_FOREVER). That wait
ends only on a result, a channel_done signal, or ctrl-C. Nothing guarantees any
of those arrive, so if the driver stops reporting there is no way out of the
loop.

This is a defensive bound, not a fix for an observed field failure. A normal
scan is unaffected: results arrive steadily and the loop cycles well inside the
limit.

espressif and raspberrypi both bound their equivalent loops and run background
tasks inside them (ports/espressif/common-hal/wifi/ScannedNetworks.c:39,
ports/raspberrypi/common-hal/wifi/ScannedNetworks.c:67). zephyr-cp did neither.

Poll in 50 ms slices with background tasks between them, and end the scan if
nothing arrives for 10 s. The window restarts whenever a channel completes, so
the limit is on the driver going quiet rather than on how long a full sweep
takes. Elapsed time is an unsigned subtraction from the start, which stays
correct across the 32-bit millisecond rollover.

No new state: the start timestamp is a local, so this costs no RAM.
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