Facts checked on 16 October 2026

Short answer

In 2026 developers reported on Qorvo’s forum that FiRa sessions on the DWM3001CDK with DW3_QM33 SDK 1.1.1 stop ranging without any notification; in one report each stop followed a late delayed transmission (HPDWARN). As of 16 October 2026 Qorvo had published no root cause or fix, and the FiRa MAC ships only as a pre-compiled library.

Forum data points to Bluetooth LE advertising and tight timing margins. Instrument the driver, count warnings, capture the air interface, check memory, soak-test against pass criteria and escalate with evidence. Meanwhile, a watchdog that restarts the whole MAC keeps devices working.

What has been reported

Thread and dateSetupSymptomStatus
“FiRa controller session stops producing ranging rounds silently”, July 2026DWM3001CDK, SDK 1.1.1 on FreeRTOS, CLI-based app, SoftDevice S113 7.2.0 advertising, one-to-many DS-TWR, channel 9, 200 ms blockRounds stop; “No SESSION_STATUS_NTF — no state change, no reason code is ever delivered”. Mean time between failures 5–27 min on one board, about 1–4 h on another with identical firmwareUnresolved; Qorvo staff asked diagnostic questions
Same thread, September 2026 replyQANI accessory as responder, iPhone as controller, S113 7.2.0Freezes tied to “BLE advertising while a UWB session is running”Unresolved; workaround below
“FiRa Coordinator Scheduler Behavior Following Delayed-TX HPDWARN Abort”, October 2026Coordinator with 5 controlees, 200 ms block, FiRa library R12.7.0Two hangs in 8,871 blocks; each after a delayed transmission saw HPDWARN; callbacks stopped while the task stayed aliveUnanswered
“UWB Ranging Failure with Recovery on Reset”, January 2026SDK 1.1.1 QANI“Fira Report: err 0xFF”; “Only a full device reset resolves the issue temporarily”Qorvo staff could not reproduce; unresolved
“SDK v1.1.1 examples enter HardFault immediately”, June 2026Driver examples on the DWM3001CDKHardFault at debug startA community member noted the examples target other boards
“FiRa applications: INITF in 1.1.0 and 1.1.1”, February 2026Prebuilt CLI firmwareTX_FAILED after INITFResolved: erase the chip completely before flashing

The September reply contains the most useful data so far. With Bluetooth LE advertising every 200 ms while connected, the developer saw about one to five freezes per hour. With advertising stopped there were none in 92 minutes, and with advertising every second there was one. “BLE connection events alone (30 ms connection interval, no advertising) do not cause it.”

Chart from one developer's forum report: about 1–5 session freezes per hour with BLE advertising every 200 ms, 1 in 92 minutes at 1 s and none in 92 minutes with advertising off.

Not every stop is silent. A session that goes to IDLE with a reason code is FiRa doing its job. In 2025, Qorvo staff explained one such case, “Session stopped due to inband signal”: the parameter IN_BAND_TERMINATION_ATTEMPT_COUNT “needs to be set to 0” to disable in-band termination on the initiator side.

Why a FiRa session can stop without telling you

Three layers run on the DWM3001CDK’s nRF52833: Qorvo’s DW3000 driver, delivered as source; the MCPS layer; and the FiRa MAC, delivered as a library. Qorvo staff are explicit: “We do not provide source code to the FiRa MAC.” Another Qorvo engineer described the MCPS layer as “the interface between the driver and the higher level stack”, adding that it “is not especially documented because it is mainly used by the Qorvo library”. When the MAC stops scheduling rounds, your code sees nothing unless you look for it.

Ranging rounds depend on exact timing. The MAC programs the DW3000 to transmit or receive at a precise future time. If the host is late, the chip cannot comply, and Qorvo’s API guide describes the result:

  • HPDWARN, the half-period warning. “The IC has a status flag warning when the specified start time is more than a half period (of the system clock) away.” The system counter wraps every 17.20 seconds, so a start time “half a period away” in practice means the moment has already passed.
  • Aborted transmission. If the host calls dwt_starttx() too late, “the transmission is aborted (transceiver off) and the dwt_starttx() function returns the -1 error indication.”

The October report shows this chain: HPDWARN set, the driver returns an error, the layer above turns it into a timeout error, and ranging callbacks stop. Whether the MAC should recover by itself is exactly the question the thread asks. Qorvo has not answered it.

What UCI notifications can and cannot tell you

In FiRa’s UCI, SESSION_STATUS_NTF carries the session ID or handle, the new state and a reason code. Android’s open-source UCI definitions list the states INIT (0x00), DEINIT (0x01), ACTIVE (0x02) and IDLE (0x03), and reasons such as 0x01 (maximum ranging round retries reached). Results arrive in SESSION_INFO_NTF with a 32-bit sequence number and a status per measurement, such as 0x21 (RX timeout). Android’s UWB service gives 0 as the UCI default for MAX_RR_RETRY: “Termination is disabled and ranging round attempt is infinite”. So a lost peer shows a growing sequence number with failed measurements, while a silent stall shows a frozen sequence number, no SESSION_STATUS_NTF and a state still reading ACTIVE. A host with UCI access can probe a quiet session, if the firmware implements these commands:

Host -> UWBS  SESSION_GET_STATE_CMD          GID 0x1, OID 0x06, session ID
UWBS -> Host  SESSION_GET_STATE_RSP          status, session_state
Host -> UWBS  SESSION_GET_RANGING_COUNT_CMD  GID 0x2, OID 0x03, session ID
UWBS -> Host  SESSION_GET_RANGING_COUNT_RSP  status, count (32 bits)

session_state 0x02 (ACTIVE) and a count that stops growing = silent stall

Why would the host be late?

  • Interrupt contention with Bluetooth LE. Nordic’s SoftDevice reserves interrupt priority 0 for “timing critical processing”, and “the priorities of the interrupts reserved by the SoftDevice cannot be changed”. UWB handling therefore always runs below the radio work of Bluetooth LE.
  • Bursts of radio events. Nordic’s figures for a three-packet advertising event add up to about 257 µs of processor time. Nordic also warns that “the application developer must add the latency of the first and last interrupt for all combinations of roles that are used”.
  • Other threads and interrupts. LEAPS, a Qorvo partner, explained a similar case on the forum: “dwt_starttx may return error if another thread or interrupt happens, and cpu has to spend time for that.”
  • Task context. The July snapshot lists the stack’s FreeRTOS tasks (llhw_mcps, qworkqueue), and any interrupt can delay them, including the SoftDevice’s levels 0, 1 and 4.
  • Flash operations. On the nRF52833, “the CPU is halted if the CPU executes code from the flash while the NVMC is writing to the flash”, and a page erase can take up to 87.5 ms. The SoftDevice schedules flash access around its own radio events, not around UWB rounds.
  • Too little lead time. A DW3000 erratum, quoted on Qorvo’s forum from the user manual, describes a case where “neither the HPDWARN event gets set nor does the packet get transmitted” unless the start time is at least the preamble length plus the SFD length plus 20 µs ahead. For a 64-symbol preamble and 8-symbol SFD at 64 MHz PRF, that is about 93 µs. The October report logged residual lead times of about 38.5 and 40.9 µs. That is a hypothesis to test, not a confirmed cause.

Memory is the other usual suspect. One community member traced a similar silent stop to a failed heap allocation at ranging start-up and moved some allocations to static variables; the same user calls the nRF52833 on the kit, which has 128 KB of RAM, “very memory constrained”. In the July snapshot, taken while wedged, the Control task showed 1992/2048 stack usage. Stack and heap margins deserve a check before anyone blames the radio.

Symptom, possible cause, test

Eight FiRa session failure symptoms on the DWM3001CDK with possible causes and tests.
SymptomPossible causeTest
Rounds stop, no notification, tasks aliveThe MAC stopped scheduling after a late transmission or an internal errorRead the DW3000 half-period warning counter; log driver return codes; capture the last frames with a sniffer
Stops come with Bluetooth LE activityInterrupt or processor contention with the SoftDeviceRepeat with advertising off, at 1 s and at 200 ms; compare mean time between failures
HPDWARN before the stopLead time for delayed transmission too shortLog the margin between programmed and current time; try 2 ms slots instead of 1 ms; shorten work in the transmit path
Stop after hours, worse on one boardHeap exhaustion, stack overflow, crystal or temperature effectsTrack minimum free heap and stack high-water marks; swap boards; check crystal trim
“Fira Report: err 0xFF”, only reset helpsSession state lost between phone and accessoryLog out-of-band messages and session IDs; compare session restart with full reset
HardFault when examples startBuild for the wrong target, or a library built for another floating-point ABICheck the target board, compiler flags and linker map
TX_FAILED right after startOld flash content or calibrationErase the whole chip, reload calibration, flash again
Session goes IDLE with a reasonNormal FiRa behaviour, such as in-band terminationRead the reason code and adjust the parameter

Two Qorvo answers support the last rows. On slot timing, a Qorvo engineer wrote that “setting a slot to 1ms makes the scheduling very tight”, so you “may need to relax this setting”. On a custom board, a Qorvo account noted that a crystal trim value of 255 “suggests that your custom design isn’t calibrated/configured properly”.

Four failure patterns: confirm and fix

  1. Stop after a half-period warning. Likely cause: a late delayed start after which the MAC stops scheduling. Confirm: HPW rises in the last block; the lead time is below preamble plus SFD plus 20 µs. Fix: 2 ms slots (SLOT_DURATION 2400 RSTU, the UCI default) instead of 1 ms, and less interrupt and flash load near rounds.
  2. Stops with advertising. Likely cause: processor contention. Confirm: Radio Notification markers next to the last delayed start; a rate difference between soak-test arms. Fix: stop advertising once connected, as stock QANI does, or advertise every second or slower.
  3. Thin memory margins. Likely cause: a failed allocation or stack overflow. Confirm: configUSE_MALLOC_FAILED_HOOK, a non-zero configCHECK_FOR_STACK_OVERFLOW, the largest free heap block, stack high-water marks. Fix: static allocation, larger stacks.
  4. Console silence, ranging alive. Likely cause: the USB or console path. Confirm: the peer still reports or TXF still grows, as Qorvo staff asked in July. Fix: decouple logging from ranging.

A debugging method in eight steps

Eight-step method for debugging FiRa sessions that stop silently, from bench reproduction to an escalation package for Qorvo.
  1. Reproduce on a bench. Run the same firmware on several boards with a scripted peer or phone, log automatically and measure mean time between failures. “Sometimes” is not a measurement.
  2. Log three layers. Application callbacks (rounds per block), FiRa notifications such as SESSION_STATUS_NTF, and driver return codes. On the DW3000, reading the system time latches it: “any subsequent read will return the same value” until an SPI write, so naive timing logs can lie.
  3. Count events in hardware. The DW3000 event counters include an 8-bit count of half-period warnings, which “relate to late invocation of delayed transmission or reception functionality”. Enable them and log the count with every report.
  4. Capture the air interface. A UWB sniffer with FiRa decoders shows whether the controller still transmits, whether responders answer and which round was the last. A Bluetooth LE companion capture puts advertising events on the same timeline.
  5. Build the timing budget. Write down block length, slots per round, slot duration and the delayed-transmission lead time, then add the worst-case interrupt latency of every Bluetooth LE role you run.
  6. Isolate Bluetooth LE. Vary advertising and connection intervals one at a time. Nordic’s Radio Notification signals, which fire before and after each radio event, help you correlate stops with Bluetooth LE activity.
  7. Check memory. Record the minimum free heap and the stack high-water mark of every UWB task over long runs, and keep static analysis in the build.
  8. Compare versions and escalate. Test 1.0.2, 1.1.0 and 1.1.1 where possible; some bugs were fixed between releases. Because the FiRa MAC is closed, a fix must come from Qorvo, so send a complete package: SDK and library version, configuration, failure rate, logs from all three layers, sniffer captures, warning counts and a minimal reproducer.

Keep your own archive of SDK packages. In August 2026 a user reported that the old 1.0.2 download link served 1.1.1 instead, and in September Qorvo staff acknowledged “some issues with downloading this package”.

Instrumentation that does not disturb timing

Markers, RTT and a logic analyser

Instrumentation must cost far less than the 40 µs margins seen in October, so put GPIO markers, one register write each, on the DW3000 interrupt handler, the driver’s delayed-start call, the ranging callback and the SoftDevice’s Radio Notification handler. The DWM3001CDK gives “Access to all DWM3001C GPIOs and interfaces”, and its on-board J-Link reads RTT. Sample at 10 MS/s or more and trigger on a callback gap longer than two blocks. For text logs, SEGGER states that “an average line of text can be output in one microsecond or less” with RTT, which is non-blocking by default. Never use SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL in timing tests, because then “the application will wait when the buffer is full”. This sketch is illustrative; pin numbers are placeholders.

/* Illustrative: logic analyser markers on an nRF52833 running S113.
 * Check that nothing else in your build uses SWI1. */
#include "nrf_gpio.h"
#include "nrf_soc.h"
#include "nrf_nvic.h"

#define PIN_DW_ISR    NRF_GPIO_PIN_MAP(0, 2)  /* high inside the DW3000 ISR */
#define PIN_DX_START  NRF_GPIO_PIN_MAP(0, 3)  /* pulse at the delayed start */
#define PIN_REPORT    NRF_GPIO_PIN_MAP(0, 4)  /* pulse per ranging report   */
#define PIN_BLE       NRF_GPIO_PIN_MAP(0, 5)  /* toggles on ACTIVE/nACTIVE  */

void RADIO_NOTIFICATION_IRQHandler(void)      /* SWI1 on S113 */
{
    nrf_gpio_pin_toggle(PIN_BLE);
}

void markers_init(void)   /* call right after enabling the SoftDevice */
{
    nrf_gpio_cfg_output(PIN_DW_ISR);
    nrf_gpio_cfg_output(PIN_DX_START);
    nrf_gpio_cfg_output(PIN_REPORT);
    nrf_gpio_cfg_output(PIN_BLE);

    sd_nvic_ClearPendingIRQ(RADIO_NOTIFICATION_IRQn);
    sd_nvic_SetPriority(RADIO_NOTIFICATION_IRQn, 3);  /* delayed only by 0, 1 */
    sd_nvic_EnableIRQ(RADIO_NOTIFICATION_IRQn);
    sd_radio_notification_cfg_set(NRF_RADIO_NOTIFICATION_TYPE_INT_ON_BOTH,
                                  NRF_RADIO_NOTIFICATION_DISTANCE_800US);
}

/* In the driver and the application:
 *   nrf_gpio_pin_set(PIN_DW_ISR);   ...ISR body...   nrf_gpio_pin_clear(PIN_DW_ISR);
 *   nrf_gpio_pin_set(PIN_DX_START); dwt_starttx(...); nrf_gpio_pin_clear(PIN_DX_START);
 */

Catching late transmissions in the driver

The driver is source code, so its delayed-start path can log its own margin, as the October reporter did. Qorvo’s guide gives the start-time resolution as “512/(499.2e6*128) seconds”, about 8 ns, because the lowest bit is ignored; one count is therefore about 4.006 ns, and 9,618 counts are 38.5 µs. A positive margin can still be late, because transmission begins at the programmed time “minus the times it needs to send preamble etc.” An illustrative sketch:

/* Illustrative: margin and abort counters in the delayed-TX path */
#include <stdint.h>
#include "deca_device_api.h"

static int32_t  dx_min_margin = INT32_MAX;  /* counts of about 4.006 ns */
static uint32_t dx_aborts;

int traced_delayed_tx(uint32_t dx_time, uint8_t mode)
{
    uint32_t now = dwt_readsystimestamphi32();  /* latches SYS_TIME       */
    int32_t margin = (int32_t)(dx_time - now);  /* valid within +/-8.6 s  */
    int ret;

    dwt_setdelayedtrxtime(dx_time);             /* SPI write unlatches it */
    ret = dwt_starttx(mode | DWT_START_TX_DELAYED);
    if (margin < dx_min_margin) {
        dx_min_margin = margin;
    }
    if (ret == DWT_ERROR) {
        dx_aborts++;                            /* late: TX was aborted   */
    }
    return ret;
}

Enable the chip’s counters with dwt_configeventcounters(1) and read them per block with dwt_readeventcounters(), from the driver’s context, because the stack owns the SPI bus. HPW counts half-period warnings in 8 bits and TXF sent frames in 12 bits; on a controller, a TXF delta of zero means it has stopped transmitting. An illustrative per-block reader:

/* Illustrative: per-block counter deltas, called from the driver context */
void diag_block(uint8_t *hpw_delta, uint16_t *txf_delta)
{
    static uint8_t  hpw_prev;
    static uint16_t txf_prev;
    dwt_deviceentcnts_t c;

    dwt_readeventcounters(&c);
    *hpw_delta = (uint8_t)(c.HPW - hpw_prev);               /* 8-bit  */
    *txf_delta = (uint16_t)((c.TXF - txf_prev) & 0x0FFFu);  /* 12-bit */
    hpw_prev = c.HPW;
    txf_prev = c.TXF;
}

If HPW rises before every stall, late starts are the likely trigger. If it also rises in blocks that continue, the warning-to-stall ratio is useful evidence for Qorvo. If stalls come without HPW, look at memory.

Timing the Bluetooth LE interaction

Configure Radio Notification with sd_radio_notification_cfg_set() right after enabling the SoftDevice, with a distance between 800 and 5,500 µs. When radio events are closer together than that distance, the signals between them are skipped. Nordic’s timing figures:

Bluetooth LE activityTime
Connectable advertising, 3 channels2,750–5,500 µs
Non-connectable advertising, 3 channels2,150–2,950 µs
Preparation at priority 0 before an event167–1,542 µs
Longest advertiser interrupt128 µs
Connection event, LE 1M PHYfrom 310 µs

For each stall, compare the gap from the nearest ACTIVE marker to the last delayed start with healthy blocks. A 5.5 ms advertising event every 200 ms covers 2.75 % of the time, at 1 s only 0.55 %, which agrees in direction with the forum data.

Reading a frozen board

Capture the state before restarting. With a J-Link, the September reporter found the DW3000 IRQ pin low, nothing pending in GPIOTE or the NVIC and no MCU timer armed: in their words, it looks like “the next round was never programmed into the DW3000”. Add SYS_STATUS from dwt_readsysstatuslo() (HPDWARN is bit mask 0x08000000), the counters and memory data, and set the nRF52833 watchdog to pause while the debugger halts the CPU.

What to put in the escalation package

In July, Qorvo staff asked whether ranging had really stopped or only the console output, and for “an example command with run_fira_twr” that replicates the settings. Answer both first. The October report shows useful detail, down to the stack archive’s build hash (R12.7.0-00405-gb33c5c42726c).

ItemInclude
VersionsSDK, stack archive, dwt_version_string(), SoftDevice, compiler flags
HardwareBoard revision, dwt_getpartid(), dwt_getlotid(), crystal trim
ConfigurationUWB and Bluetooth LE parameters, flash writes
Reproducerrun_fira_twr command or CLI sequence, plus the smallest triggering change
StatisticsStall times and MTBF per board, one factor varied at a time
EvidenceLast notifications, return codes, HPW, TXF, margins, SYS_STATUS, memory
CapturesSniffer capture of the stall, Bluetooth LE activity on the same timeline
Ruled outEach exclusion with its experiment

Qorvo’s one-to-many tutorial gives a baseline for both firmware types; -t -1 runs the scripts “forever until the return/enter key is pressed”:

# UCI firmware: controller first, then each controlee
run_fira_twr -t -1 --node onetomany --dest-mac '[0x1, 0x2]' --n_controlees 2
run_fira_twr -t -1 --node onetomany --mac 0x1 --controlee
run_fira_twr -t -1 --node onetomany --mac 0x2 --controlee

# CLI firmware: the same set-up
initf -multi -paddr=[1,2]
respf -multi -addr=1
respf -multi -addr=2

A safety net while you wait for a fix

Two forum users describe the same workaround. Watch a ranging counter in the application; if it stops for a set time, stop every session and the MAC, then start again. One restarted after 15 seconds of silence and ranging resumed in under a second; the other used 2 seconds and saw recovery in about 200 ms.

Three details from those reports matter:

  • The teardown calls “all return success on the wedged session — the stack does not know it is wedged”. Your watchdog must judge progress, not return codes.
  • “Restarting only the frozen session does NOT recover it when two sessions exist – the whole MAC must be restarted.”
  • Log every restart with context and count restarts in field telemetry. A watchdog keeps devices usable; it does not replace a root cause.

One QANI developer found that a MAC restart did not recover every case and that sometimes “only Watchdog can restore it”, so recover in levels: MAC restart first, chip reset if restarts bring no progress.

A progress watchdog in code

This illustrative sketch counts reports in the callback, which in the July set-up “fires on every block, including all-miss blocks”, so a lost peer does not trigger it.

/* Illustrative: progress watchdog for FiRa sessions on FreeRTOS + S113.
 * uwb_restart_all() is your function that stops every session and the
 * MAC and starts them again; diag_snapshot() saves the stall state. */
#include "FreeRTOS.h"
#include "task.h"
#include "timers.h"
#include "nrf_nvic.h"

#define CHECK_MS      500u
#define STALL_MS      2000u          /* 10 blocks at 200 ms */
#define MAX_RESTARTS  3u             /* then reset the chip */

extern void uwb_restart_all(void);
extern void diag_snapshot(void);

static volatile uint32_t reports;    /* +1 in every ranging report callback */
static volatile uint32_t restarts_in_row;
static TaskHandle_t recovery_task;

void on_ranging_report(void) { reports++; }

static void check_cb(TimerHandle_t t)
{
    static uint32_t last, quiet_ms;

    (void)t;
    if (reports != last) {
        last = reports;
        quiet_ms = 0;
        restarts_in_row = 0;
    } else if ((quiet_ms += CHECK_MS) >= STALL_MS) {
        quiet_ms = 0;
        xTaskNotifyGive(recovery_task);  /* restart outside the timer task */
    }
}

static void recovery_fn(void *arg)
{
    (void)arg;
    for (;;) {
        ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
        diag_snapshot();                 /* capture first, then restart */
        if (++restarts_in_row > MAX_RESTARTS) {
            sd_nvic_SystemReset();       /* level 2: full reset */
        }
        uwb_restart_all();               /* level 1: MAC restart */
    }
}

void progress_watchdog_start(void)
{
    xTaskCreate(recovery_fn, "uwb_rec", 512, NULL, tskIDLE_PRIORITY + 2,
                &recovery_task);
    xTimerStart(xTimerCreate("uwb_wd", pdMS_TO_TICKS(CHECK_MS), pdTRUE,
                             NULL, check_cb), 0);
}

Keep restart counts, the HPW total, the smallest margin, xPortGetMinimumEverFreeHeapSize(), the largest free block from vPortGetHeapStats() and uxTaskGetStackHighWaterMark() (in words) across resets. Behind it all, keep the nRF52833 hardware watchdog. Its timeout is (CRV + 1) / 32768 s, and even with its interrupt enabled the reset follows the TIMEOUT event after only two 32.768 kHz cycles, about 61 µs, so write telemetry continuously.

Prevent it before production

  • Soak tests: run many boards for days with realistic Bluetooth LE traffic, because many timing faults appear after hours.
  • Release gates: set a minimum mean time between failures for every firmware release and every SDK upgrade.
  • Field telemetry: report watchdog restarts, warning counters and minimum free heap from devices in use.
  • Architecture options: if Bluetooth LE load is heavy, move Bluetooth LE to its own core. Qorvo staff wrote in September 2026 that the “nRF5340 should be a good option using the M33 build”.

A soak-test harness

Qorvo staff call the CLI commands “meant for being human readable” and recommend the UCI build for scripting. A practical harness:

  • Boards: four or more controllers; the July boards ran 5–27 minutes and 1–4 hours between failures on identical firmware.
  • Load: the product’s real Bluetooth LE pattern and flash writes.
  • Detection: a stall is ten blocks without a new SESSION_INFO_NTF sequence number; probe the console separately.
  • Records per board: hours, stalls, restarts, HPW, smallest margin, heap and stack minima, temperature.

An illustrative test plan for comparing advertising settings:

{
  "boards": ["A", "B", "C", "D"],
  "firmware": "<SDK 1.1.1 build id>",
  "block_ms": 200,
  "stall_after_blocks": 10,
  "arms": [
    {"name": "adv_off",  "adv_interval_ms": null},
    {"name": "adv_1s",   "adv_interval_ms": 1000},
    {"name": "adv_200",  "adv_interval_ms": 200}
  ],
  "order": "interleaved per board",
  "pass": {"target_mtbf_h": 24, "confidence": 0.95, "stalls_allowed": 0}
}

How long to run and when to pass

For a constant failure rate, NIST’s reliability handbook gives the test time as the MTBF target times a factor: with no failures allowed, 2.30 at 90 % confidence and 3.00 at 95 %; with one failure, 3.89 and 4.74.

Target MTBFConfidenceStalls allowedBoard-hours
24 h90 %055
24 h95 %072
24 h90 %193
72 h95 %0216

Report per board as well as in total, because pooling board-hours assumes identical boards. The same arithmetic limits the forum data: 92 freeze-free minutes show, at 90 % confidence, only an MTBF above about 40 minutes; showing more than 10 hours would take 23 freeze-free hours.

From our engineering work

Inside Qorvo’s UWB programme, needCode engineers developed firmware, drivers and protocol stacks, including the MAC layer built to the FiRa specification and multi-session scheduling. They also build Qorvo’s public QM35 SDK. Our Modular UWB Sniffer decodes FiRa traffic and adds Bluetooth LE capture of the out-of-band session setup.

How needCode helps

We debug and stabilise products built on the DWM3001C, QM33 and DW3000: bench reproduction with hardware-in-the-loop, logging and sniffer captures, timing and memory analysis, Bluetooth LE scheduling, and escalation packages for Qorvo. For products in the field we add watchdogs, telemetry and soak tests to the release pipeline, and we can take over sustaining engineering for the product.

Frequently asked questions

Why does my FiRa controller session stop ranging on the DWM3001CDK?

Qorvo has not published a root cause. Reports on Qorvo’s forum point to late delayed transmissions (HPDWARN), Bluetooth LE advertising during UWB sessions and memory pressure on the nRF52833. Measure which one applies with three-layer logs, the DW3000 warning counter and a sniffer capture.

What does HPDWARN mean on the DW3000?

It is the half-period warning. Qorvo’s API guide says the chip raises it when a delayed transmit or receive start time is “more than a half period (of the system clock) away”, which in practice means the time has already passed. A late dwt_starttx() is aborted and returns -1.

Why do DW3_QM33 SDK 1.1.1 examples crash with HardFault?

In a June 2026 thread the driver examples were built for a different target than the DWM3001CDK’s nRF52833. Check the target board, compiler flags and the floating-point ABI of the pre-compiled libraries; a mismatch often shows up as a HardFault rather than a link error.

Can I fix the FiRa MAC myself?

Not in the stack itself. Qorvo states: “We do not provide source code to the FiRa MAC.” You can change timing, Bluetooth LE scheduling, memory use and your application, add a MAC-level watchdog and escalate to Qorvo with evidence.

Does Bluetooth LE advertising affect UWB ranging on the DWM3001C?

It can. One developer measured one to five session freezes per hour with advertising every 200 ms, none in 92 minutes without advertising and one with advertising every second. Connection events alone did not cause freezes in that test.

How do I recover a stalled session in the field?

Monitor ranging progress in the application and, after a few seconds without new rounds, stop all sessions and the MAC and start again. Forum users report recovery in about 200 ms to under a second; restarting only the frozen session was not enough when two sessions existed.

Which DW3000 counters show late transmissions?

Enable them with dwt_configeventcounters(1) and read them with dwt_readeventcounters(). HPW counts half-period warnings and TXF sent frames. HPW rising before a stall supports the late-start hypothesis; TXF not growing on a controller shows that it has stopped transmitting.

How long should a soak test run?

For a constant failure rate and no failures allowed, NIST’s factors give the MTBF target times 2.30 at 90 % confidence or 3.00 at 95 %. A 24-hour target at 95 % needs 72 stall-free board-hours, spread over several boards and reported per board.

Sources

  1. Qorvo Tech Forum: “FiRa controller session stops producing ranging rounds silently” (July–September 2026)
  2. Qorvo Tech Forum: “FiRa Coordinator Scheduler Behavior Following Delayed-TX HPDWARN Abort” (October 2026)
  3. Qorvo Tech Forum: “UWB Ranging Failure with Recovery on Reset” (January 2026)
  4. Qorvo Tech Forum: “SDK v1.1.1 examples enter HardFault immediately on DWM3001CDK” (June 2026) and “FiRa applications: INITF in 1.1.0 and 1.1.1” (February 2026)
  5. Qorvo Tech Forum: in-band termination (staff, July 2025) and MCPS layer and 1 ms slots (staff, 2024)
  6. Qorvo Tech Forum: FiRa MAC source code (staff, August 2026)
  7. Qorvo DW3xxx/QM33xxx Device Driver API Guide (forum attachment, April 2025)
  8. Qorvo Tech Forum: “DW3000 HPDWARN errata: need clarification” (2022) and DW3000 datasheet v1.1 (distributor copy)
  9. Qorvo Tech Forum: “Delayed dwt_starttx randomly fails” (2025) and “DW3000 packet transmission aborted” (2024)
  10. Nordic S140 SoftDevice Specification: interrupt priority levels and advertiser processor usage
  11. Nordic S113 SoftDevice Specification: interrupt latency with multiple roles and Radio Notification signals
  12. Qorvo Tech Forum: nRF5340 with DWM3000 for Apple NI (staff, September 2026)
  13. Qorvo Tech Forum: crystal trim on a custom design (2025) and SDK 1.1.1 download issues (staff, September 2026)
  14. Qorvo Tech Forum: “Tutorial: How to Use DW3 QM33 SDK for One to Many FiRa Ranging” (staff, December 2024)
  15. Qorvo Tech Forum: format of the INITF/RESPF log message (staff reply, July 2025) and “Type2AB board calibration” (heap allocation report, September 2026)
  16. Android Open Source Project: UCI packet definitions (uci_packets.pdl) and FiraOpenSessionParams.java (UCI defaults)
  17. Nordic S113 SoftDevice headers: nrf_soc.h and nrf_nvic.h (copies in the nrf-softdevice repository)
  18. Nordic nRF52833 Product Specification: NVMC and WDT
  19. Nordic S113 SoftDevice Specification: Flash memory API
  20. Nordic nRF52833 product page, nrfx 2.5.0 GPIO HAL and nRF52 compatibility names
  21. FreeRTOS kernel: task.h, portable.h, timers.h, projdefs.h and heap_4.c
  22. SEGGER Knowledge Base: RTT
  23. NIST/SEMATECH e-Handbook of Statistical Methods, 8.3.1.1: Exponential life distribution (or HPP model) tests
  24. Qorvo DWM3001CDK product page

About needCode

needCode is an independent embedded engineering company from Kraków, Poland, and an official UWB business partner of Qorvo. Its engineers have worked inside Qorvo’s wireless programmes for more than eight years, including on the public QM35 SDK. needCode is certified to ISO 9001:2015 and ISO/IEC 27001:2022 and is a member of the UWB Alliance. This article does not represent Qorvo. All trademarks belong to their respective owners.