QSPI flash hangs after BLE bonding on nRF54L15 (sQSPI / LittleFS)

We are experiencing an issue with the QSPI driver on nRF54L15 where external flash access stops working after a BLE bonding procedure.

The system works correctly until bonding occurs. After a mobile device bonds with the board, any access to external flash via QSPI becomes unusable and the calling thread hangs indefinitely.

During investigation we temporarily added a guard/timeout around the _ASB(...) macro inside the driver. With this modification the driver sometimes returns:

flash_mspi_nor: perform_xfer: transceive() failed: -116

However, without this modification the system hangs indefinitely.


Hardware

  • Board: nRF54L15-DK

  • External flash: MX25R6435F

  • Interface: QSPI (quad mode)

The flash wiring matches the reference design used on the development kit.


Software

  • nRF Connect SDK project built from command line

  • File system: LittleFS over sQSPI flash

  • Application features:

    • BLE advertising

    • BLE connections

    • BLE bonding

    • shell commands for NVM access

Steps to Reproduce

  1. Start BLE advertising

  1. Connect from a mobile device.

  2. Perform bonding.

  3. Execute any command that accesses external flash.

Observed Behavior

External flash works correctly in the following situations:

  • before BLE advertising

  • while advertising (most of the time)

  • while a mobile device is connected but not bonded

After bonding, access to external flash becomes unusable.

When a command attempts to access flash (e.g. nvm ls), the thread performing the operation hangs indefinitely.

When a temporary timeout was added around _ASB(...), the operation sometimes fails with:

flash_mspi_nor: perform_xfer: transceive() failed: -116

But without this modification the system deadlocks.


Expected Behavior

External flash access over QSPI should continue working normally regardless of BLE bonding state.

Bonding a BLE device should not affect the operation of the external flash driver.

Workaround

Switching the external flash interface from QSPI to hardware SPI (single line) avoids the issue.

With SPI the flash works correctly even after BLE bonding.

However, this significantly reduces flash throughput compared to QSPI.


Additional Observations

While debugging with a debugger attached, the blocked execution appeared to be stuck inside the _ASB(...) macro. This observation is not fully confirmed, but it appeared consistently when inspecting the hanging thread.


Things Already Tested

We tried the following without resolving the issue:

Disable auto runtime PM for sQSPI

Lowering the operational frequency down to 1MBit

Disable Deep Power Down for MX25R6435F
(removed the following from dts):

has-dpd
t-enter-dpd
t-exit-dpd
reset timings

The issue still occurs.

If possible, could you please help investigate why BLE bonding affects QSPI flash access on nRF54L15?

Device Tree, part related to sqspi configuration:

&sqspi {
	mx25r64: mx25r6435f@0 {
		compatible = "mxicy,mx25r", "jedec,mspi-nor";
		status = "okay";
		reg = <0>;
		jedec-id = [c2 28 17];
		quad-enable-requirements = "S1B6";
		sfdp-bfp = [
			e5 20 f1 ff  ff ff ff 03  44 eb 08 6b  08 3b 04 bb
			ee ff ff ff  ff ff 00 ff  ff ff 00 ff  0c 20 0f 52
			10 d8 00 ff  23 72 f5 00  82 ed 04 cc  44 83 68 44
			30 b0 30 b0  f7 c4 d5 5c  00 be 29 ff  f0 d0 ff ff
		];
		size = <DT_SIZE_M(64)>; /* 8 MB (64 Mbit) */
		has-dpd;
		t-enter-dpd = <10000>;
		t-exit-dpd = <35000>;
		t-reset-pulse = <10000>;
		t-reset-recovery = <35000>;
		mspi-max-frequency = <DT_FREQ_M(80)>;
		mspi-io-mode = "MSPI_IO_MODE_QUAD_1_4_4";
		mspi-data-rate = "MSPI_DATA_RATE_SINGLE";
		mspi-hardware-ce-num = <1>;
		mspi-cpp-mode = "MSPI_CPP_MODE_0";
		mspi-endian = "MSPI_BIG_ENDIAN";
		mspi-ce-polarity = "MSPI_CE_ACTIVE_LOW";
		transfer-timeout = <100>;
	};
};

Parents
  • Hello,

    Thanks for the detailed report. Before I attempt to investigate this further, could you please confirm if the bonding data (settings_storage) is located in the internal or external memory?

    Thank you,

    Vidar 

  • Hello,

    In an internal storage, as could be seen from generated `partitions.yml` below.

    app:
      address: 0x0
      end_address: 0x17b000
      region: flash_primary
      size: 0x17b000
    bootconf:
      address: 0xffd080
      end_address: 0xffd084
      region: bootconf
      size: 0x4
    external_flash:
      address: 0x0
      device: MX25R64
      end_address: 0x800000
      region: external_flash
      size: 0x800000
    littlefs_storage:
      address: 0x0
      device: MX25R64
      end_address: 0x800000
      region: external_flash
      size: 0x800000
    otp:
      address: 0xffd500
      end_address: 0xffd9fc
      region: otp
      size: 0x4fc
    settings_storage:
      address: 0x17b000
      end_address: 0x17d000
      placement:
        after:
        - app
        before:
        - end
      region: flash_primary
      size: 0x2000
    sram_primary:
      address: 0x20000000
      end_address: 0x2003c000
      region: sram_primary
      size: 0x3c000
    

    I hope it helps. let me know if you need any additional information, please

Reply
  • Hello,

    In an internal storage, as could be seen from generated `partitions.yml` below.

    app:
      address: 0x0
      end_address: 0x17b000
      region: flash_primary
      size: 0x17b000
    bootconf:
      address: 0xffd080
      end_address: 0xffd084
      region: bootconf
      size: 0x4
    external_flash:
      address: 0x0
      device: MX25R64
      end_address: 0x800000
      region: external_flash
      size: 0x800000
    littlefs_storage:
      address: 0x0
      device: MX25R64
      end_address: 0x800000
      region: external_flash
      size: 0x800000
    otp:
      address: 0xffd500
      end_address: 0xffd9fc
      region: otp
      size: 0x4fc
    settings_storage:
      address: 0x17b000
      end_address: 0x17d000
      placement:
        after:
        - app
        before:
        - end
      region: flash_primary
      size: 0x2000
    sram_primary:
      address: 0x20000000
      end_address: 0x2003c000
      region: sram_primary
      size: 0x3c000
    

    I hope it helps. let me know if you need any additional information, please

Children
  • Hello,

    The only relation I could think of between the bonding procedure and littlefs was if both were trying to store something to the same flash device and there was some potential issue with concurrency handling. Would you be able to provide a minimal project here or in a private ticket that would allow me to reproduce this issue here on a nRF54L15 DK?

    Best regards,

    Vidar

    EDIT: Please also let me know what SDK version you are using. Perhaps the issue you are seeing may have been fixed in a later version?

Related