Custom nRF52840 board running S140 (SDK 17.1.0). I'm adding USB Mass Storage (SD card exposed as a removable drive) to existing firmware that already does BLE (NUS) + SD-card recording. The USB stack initializes and runs all the way to APP_USBD_EVT_STARTED, but the host never sees a device — no enumeration, no "device connected" chime, nothing in Windows Device Manager (not even an unknown/error device).
I read the USB registers from inside the firmware right after start, and the D+ pull-up is never asserted:
USBREGSTATUS = 0x00000003 (bit0 VBUSDETECT = 1, bit1 OUTPUTRDY = 1)
USBD->ENABLE = 0x00000001
USBD->USBPULLUP = 0x00000000 <-- never becomes 1
So VBUS is detected, the USB regulator output is ready, and the peripheral is enabled — but USBPULLUP stays 0, which is presumably why the host sees nothing.
What works
- Firmware boots fully, BLE + SD recording function normally.
- On USB plug-in I get, in order (my log strings):
USB POWER DETECTED->USB POWER READY->SD Card Relinquished->APP_USBD_START finished->USB STARTED. USBREGSTATUS = 0x3confirms VBUS + regulator ready.USBD->ENABLE = 1confirms the peripheral is enabled.
The problem
USBD->USBPULLUP remains 0x0 even after app_usbd_start(). The device therefore never signals its presence on D+ and the host does not enumerate.
Hardware (believed OK)
- nRF52840, USB D+/D- routed to the dedicated USB pins (verified against schematic).
- VBUS routed to the chip; USBREGSTATUS shows VBUSDETECT=1, so VBUS is present.
- SD card is on SPI (nrf_block_dev_sdc), same instance used by FatFS for recording.
Init sequence (SoftDevice-aware ordering)
Clock and power drivers are initialized BEFORE the SoftDevice is enabled (nrf_drv_power_init returns INVALID_STATE if called after SD enable):
// in power_management_init(), called before ble_stack_init():
nrf_drv_clock_init();
nrf_drv_power_init(NULL);
nrf_pwr_mgmt_init();
// SoftDevice enabled later via nrf_sdh_enable_request() in ble_stack_init()
// after services/SoftDevice up, request HFCLK and wait:
sd_clock_hfclk_request();
uint32_t running = 0;
while (!running) { sd_clock_hfclk_is_running(&running); }
// USB init:
app_usbd_init(&usbd_config); // returns NRF_ERROR_INVALID_STATE (0x08),
// which I tolerate (does not appear fatal)
app_usbd_class_append(msc_class);
app_usbd_power_events_enable();
app_usbd_init() returns NRF_ERROR_INVALID_STATE (0x08) on this SoftDevice build. I currently treat that as non-fatal (a colleague's working-to-STARTED project does the same). Is that correct, or is that INVALID_STATE the root cause?
sdk_config.h (USB-related)
APP_USBD_ENABLED = 1
APP_USBD_MSC_ENABLED = 1
USBD_ENABLED = 1
NRFX_USBD_ENABLED = 1
APP_USBD_CONFIG_EVENT_QUEUE_ENABLE = 1
APP_USBD_CONFIG_POWER_EVENTS_PROCESS = 1
NRF_BLOCK_DEV_SDC_ENABLED / APP_SDCARD_ENABLED = 1
POWER_ENABLED = 1, NRFX_POWER_ENABLED = 1
NRF_SDH_ENABLED = 1, NRF_SDH_SOC_ENABLED = 1
Handoff (drive mode) — where app_usbd_start() is called
Recording/BLE stop, FatFS is unmounted, then USB is started from the main loop when the device is idle. After start I pump the event queue and check USBPULLUP:
f_mount(NULL, "", 0); // unmount FatFS (I do NOT nrf_blk_dev_uninit)
app_usbd_start();
for (uint32_t i = 0; i < 100; i++) {
while (app_usbd_event_queue_process()) { }
if (NRF_USBD->USBPULLUP & 1u) break;
nrf_delay_ms(1);
}
// USBPULLUP still reads 0x00000000 here