Environment
- SoC: nRF54LM20 (DK; silicon reports nRF54LM20B ENGB — also reproduces built for the LM20A target)
- nRF Connect SDK: v3.3.0-rc2, west v1.5.0
- Bluetooth: SoftDevice Controller (peripheral), TrustZone NS build (TF-M)
- Display: AMOLED driven by the sQSPI softperipheral running on the FLPR (VPR) core, QSPI/Quad, SCK 32 MHz, FLPR HSFLL 128 MHz. Display Buffer streamed in ~52 KB slices via WRMEMST/WRMEMCONT.
Symptom
The sQSPI transfer aborts mid-buffer with NRF_SQSPI_RESULT_ABORTED (TXUNEXPECTEDIDLE). The display driver retries, but the aborts are frequent enough to be a problem.Occastionally a full system halt.
Aborts occur only while BLE is advertising, and only once a bond exists on the device.
Connecting stops the aborts; disconnecting (back to advertising) restarts them.
Clean reproducible toggle: CONFIG_BT_CTLR_PRIVACY=y and make a bond with a central → aborts; CONFIG_BT_CTLR_PRIVACY=n → zero aborts. or delete bond → zero aborts.
Advertising is legacy connectable + scannable (ADV_IND), 200 ms interval. Abort rate scales with advertising frequency (FAST_2 ~24 aborts/5 s; SLOW ~2–4/5 s).
So the trigger appears to be the controller privacy / address-resolution machinery running inside the advertising event (RPA + AAR resolution of incoming SCAN_REQ/CONNECT_IND). But its closed source so I can't see. Connected state runs the same RADIO/EasyDMA traffic with zero aborts.
What I have already ruled out
- M33 CPU load / ISR latency — DWT_PCSR + SystemView sampling puts the radio ISR at ~1/13000 samples. The M33 is not busy; FPU on/off makes no difference to aborts. The FLPR is autonomous during a slice, so M33 latency shouldn't matter anyway.
- sQSPI notify-IRQ priority — raising the VPR notify IRQ to the max the NS app is allowed (peer with MPSL HIGH) did not help. We cannot go above MPSL prio 0 from NS (AIRCR.PRIS).
- Clock gating by MPSL — pinning HFXO had zero effect.
- DMA-source RAM-bank contention as per documenation — we pointed the display buffer DMA at a static, quiescent buffer in a different RAM bank (RAM01), away from sdc_mempool/framebuffers in RAM00 (verified in .map). Same byte count/commands. Aborts unchanged. So it is not subordinate-side RAM contention on the source read.
- Shared programmable hardware — source review of the sQSPI softperipheral (nrf_sqspi.c / softperipheral_regif.h) shows it uses only VPR00, nrf_qspi2, VPR-internal TASKS_TRIGGER/EVENTS_TRIGGERED (VPR00 IRQ 76), P2 GPIO, and the 128 MHz HSFLL. It reserves no system DPPI/PPIB/TIMER/GPIOTE — so no channel/timer clash with the AAR/privacy path.
- AAR work magnitude — CONFIG_BT_CTLR_RL_SIZE 8 → 1 made no difference. The abort does not scale with resolving-list size / AES count — it's the per-event AAR machinery being active at all that matters. This looks latency-driven, not bandwidth-driven (a single arbitration stall on the FLPR is enough to underrun the FIFO).
I can't really solve this one as all the parts are closed source.
Look forward to hearing back!
Dominic