Skip to content

nrf5x: request HFCLK in USB_EVT_READY to fix post-SoftDevice deadlock#3633

Merged
hathach merged 1 commit into
masterfrom
fix/nrf5x-hfclk-wait-post-sd
May 8, 2026
Merged

nrf5x: request HFCLK in USB_EVT_READY to fix post-SoftDevice deadlock#3633
hathach merged 1 commit into
masterfrom
fix/nrf5x-hfclk-wait-post-sd

Conversation

@hathach
Copy link
Copy Markdown
Owner

@hathach hathach commented May 8, 2026

Summary

Fix a deadlock in tusb_hal_nrf_power_event(USB_EVT_READY) when fired after the SoftDevice has been enabled.

USB_EVT_DETECTED runs hfclk_enable() which, when SD is not yet enabled, starts HFXO via direct CLOCK register access. After sd_softdevice_enable() takes over the CLOCK peripheral, HFXO is physically off again and SD's HFCLK reference count is 0.

If USB_EVT_READY is then fired post-SD (e.g. on nRF52 via Bluefruit's usb_softdevice_post_enable() when the pre-SD nrfx_power READY callback didn't get to run before nrfx_power was uninited), the wait loop

while (!hfclk_running()) {}

calls sd_clock_hfclk_is_running() which returns false forever — deadlock that blocks both USB enumeration and any further app code on the calling thread.

The fix calls hfclk_enable() immediately before the wait, so HFCLK is requested in whichever context (SD or direct) is current. hfclk_enable() is idempotent.

Reproduction

Adafruit Feather nRF52840 Express running the bleuart example, flashed via JLink (cold start, race-prone). Without the patch the chip wedges in sd_clock_hfclk_is_running SVC: no USB enumeration, no BLE advertising. With the patch USB enumerates as 239a:8029 and BLE advertises as Feather nRF52840 Express.

Test plan

  • Verified on Feather nRF52840 Express (S140 v6.1.1, FreeRTOS): USB CDC + BLE both working post-fix
  • No-SD nRF52840 sketch (TinyUSB device-only): the added hfclk_enable() is idempotent and takes the same direct-register branch as before, so behavior should be unchanged
  • nRF52833 / nRF5340 (if applicable): logic is identical; should be a no-op for paths that already work

USB_EVT_DETECTED runs hfclk_enable() which, when SoftDevice is not yet
enabled, starts HFXO via direct CLOCK register access. After
sd_softdevice_enable() takes over CLOCK, HFXO is physically off again
and SD's HFCLK reference count is 0.

If USB_EVT_READY is fired post-SD (e.g. on nRF52 via Bluefruit's
usb_softdevice_post_enable() when the pre-SD nrfx_power READY callback
didn't get to run before nrfx_power was uninited), the wait loop
'while (!hfclk_running()) {}' calls sd_clock_hfclk_is_running() which
returns false forever -> deadlock that blocks both USB enumeration and
any further app code on the calling thread.

Call hfclk_enable() right before the wait so HFCLK is requested in
whichever context (SD or direct) is current. hfclk_enable() is
idempotent.

Reproduces reliably with bleuart on Feather nRF52840 Express flashed
via JLink: chip wedges in sd_clock_hfclk_is_running SVC, no USB
enumeration, no BLE advertising. With the fix, USB enumerates and BLE
advertises as expected.
Copilot AI review requested due to automatic review settings May 8, 2026 14:28
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes a potential deadlock in the nRF5x DCD power-event handling when USB_EVT_READY is delivered after the SoftDevice has been enabled, by ensuring HFCLK is (re-)requested in the currently active clock-control context before waiting for it to become running.

Changes:

  • Request HFCLK again in USB_EVT_READY via hfclk_enable() immediately before the hfclk_running() wait loop.
  • Add an explanatory comment describing the pre-SoftDevice vs post-SoftDevice HFCLK ownership scenario that can otherwise lead to an infinite wait.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 8, 2026

Size Difference Report

Because TinyUSB code size varies by port and configuration, the metrics below represent the averaged totals across all example builds.

Note: If there is no change, only one value is shown.

Changes >1% in size

No entries.

Changes <1% in size

file .text .bss size % diff
dcd_nrf5x.c 2916 ➙ 2940 (+24) 292 3208 ➙ 3232 (+24) +0.7%
TOTAL 2916 ➙ 2940 (+24) 292 3208 ➙ 3232 (+24) +0.7%
No changes
file .text .rodata .data .bss size % diff
audio_device.c 2896 0 1259 1625 4515 +0.0%
cdc_device.c 1239 16 1092 735 1972 +0.0%
cdc_host.c 6381 487 15 985 7579 +0.0%
dcd_ch32_usbfs.c 1475 0 0 2444 3919 +0.0%
dcd_ch32_usbhs.c 1468 0 0 448 1916 +0.0%
dcd_ci_fs.c 1924 0 0 1290 3214 +0.0%
dcd_ci_hs.c 1758 0 0 1344 2535 +0.0%
dcd_da146xx.c 3067 0 0 144 3211 +0.0%
dcd_dwc2.c 4245 19 0 265 4529 +0.0%
dcd_eptri.c 2272 0 0 259 2531 +0.0%
dcd_ft9xx.c 3280 0 0 172 3452 +0.0%
dcd_khci.c 1952 0 0 1290 3242 +0.0%
dcd_lpc17_40.c 1478 0 0 648 1802 +0.0%
dcd_lpc_ip3511.c 1463 0 0 264 1683 +0.0%
dcd_mm32f327x_otg.c 1477 0 0 1290 2767 +0.0%
dcd_msp430x5xx.c 1799 0 0 176 1975 +0.0%
dcd_musb.c 2226 0 0 171 2396 +0.0%
dcd_nuc120.c 1095 0 0 78 1173 +0.0%
dcd_nuc121.c 1168 0 0 101 1270 +0.0%
dcd_nuc505.c 0 0 1532 157 1689 +0.0%
dcd_rp2040.c 841 0 764 653 2258 +0.0%
dcd_rusb2.c 2917 0 0 156 3073 +0.0%
dcd_samd.c 1036 0 0 266 1302 +0.0%
dcd_samg.c 1321 0 0 72 1393 +0.0%
dcd_stm32_fsdev.c 2558 0 0 291 2849 +0.0%
dfu_device.c 777 28 712 138 914 +0.0%
dfu_rt_device.c 157 0 134 0 157 +0.0%
dwc2_common.c 603 22 0 0 615 +0.0%
ecm_rndis_device.c 1047 0 1 2759 3807 +0.0%
ehci.c 2763 0 0 6043 7597 +0.0%
fsdev_common.c 180 0 0 0 180 +0.0%
hcd_ch32_usbfs.c 2485 0 0 498 2983 +0.0%
hcd_ci_hs.c 184 0 0 0 184 +0.0%
hcd_dwc2.c 5007 25 1 513 5545 +0.0%
hcd_khci.c 2442 0 0 449 2891 +0.0%
hcd_musb.c 3073 0 0 157 3230 +0.0%
hcd_pio_usb.c 262 0 240 0 502 +0.0%
hcd_rp2040.c 2000 17 4 321 2342 +0.0%
hcd_rusb2.c 2923 0 0 245 3168 +0.0%
hcd_samd.c 2220 0 0 324 2544 +0.0%
hcd_stm32_fsdev.c 3259 0 1 420 3680 +0.0%
hid_device.c 1125 44 997 119 1244 +0.0%
hid_host.c 1240 0 0 1251 2491 +0.0%
hub.c 1384 8 8 30 1418 +0.0%
midi_device.c 1151 0 1007 624 1773 +0.0%
midi_host.c 1341 7 7 3635 4979 +0.0%
msc_device.c 2517 108 2281 806 3323 +0.0%
msc_host.c 1587 0 0 394 1982 +0.0%
mtp_device.c 1696 22 735 588 2292 +0.0%
ncm_device.c 1544 28 720 4452 6010 +0.0%
ohci.c 1940 0 0 2414 4353 +0.0%
printer_device.c 830 0 706 566 1394 +0.0%
rp2040_usb.c 366 35 647 11 1060 +0.0%
rusb2_common.c 160 0 16 0 176 +0.0%
tusb.c 451 0 383 3 453 +0.0%
tusb_fifo.c 850 0 483 0 845 +0.0%
typec_stm32.c 820 8 2 12 842 +0.0%
usbc.c 420 2 20 166 608 +0.0%
usbd.c 3522 58 91 355 3941 +0.0%
usbh.c 4637 55 99 1034 5791 +0.0%
usbtmc_device.c 2196 24 68 316 2544 +0.0%
vendor_device.c 641 0 534 565 1204 +0.0%
video_device.c 4443 5 1235 479 4914 +0.0%
TOTAL 115579 1018 15794 45011 162221 +0.0%

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 8, 2026

MemBrowse Memory Report

Top 10 targets by memory change (%) (out of 2233 targets) View Project Dashboard →

target .text .rodata .data .bss total % diff
adafruit_clue/dfu_runtime 11,960 → 11,984 (+24) 12,968 → 12,992 (+24) +0.2%
adafruit_clue/hid_generic_inout 13,080 → 13,104 (+24) 13,912 → 13,936 (+24) +0.2%
adafruit_clue/hid_multiple_interface 13,700 → 13,724 (+24) 14,708 → 14,732 (+24) +0.2%
adafruit_clue/hid_boot_interface 13,756 → 13,780 (+24) 14,716 → 14,740 (+24) +0.2%
adafruit_clue/hid_composite 13,788 → 13,812 (+24) 14,892 → 14,916 (+24) +0.2%
adafruit_clue/midi_test 13,964 → 13,988 (+24) 14,892 → 14,916 (+24) +0.2%
adafruit_clue/cdc_dual_ports 14,632 → 14,656 (+24) 15,816 → 15,840 (+24) +0.2%
adafruit_clue/printer_to_cdc 14,852 → 14,876 (+24) 15,840 → 15,864 (+24) +0.2%
adafruit_clue/audio_test 15,116 → 15,140 (+24) 16,016 → 16,040 (+24) +0.1%
adafruit_clue/webusb_serial 14,920 → 14,944 (+24) 16,200 → 16,224 (+24) +0.1%

@hathach hathach merged commit de112b0 into master May 8, 2026
319 of 320 checks passed
@hathach hathach deleted the fix/nrf5x-hfclk-wait-post-sd branch May 8, 2026 14:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants