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

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.
This commit is contained in:
hathach
2026-05-08 21:27:53 +07:00
parent d21fdd98f3
commit 6af4ee2c50

View File

@ -1049,6 +1049,12 @@ void tusb_hal_nrf_power_event(uint32_t event) {
NVIC_EnableIRQ(USBD_IRQn);
}
// Ensure HFCLK is requested in the current context. The hfclk_enable() in
// USB_EVT_DETECTED may have been pre-SoftDevice. After Softdevice is
// enabled, HFXO is physically off again. So any caller that fires
// USB_EVT_READY post-SD would hang here.
hfclk_enable();
// Wait for HFCLK
while (!hfclk_running()) {}