BL54l15µ DVK: SPIM20/SPIM21 not working on P2 dedicated pins

Hello everyone,

I'm encountering a pin routing issue on the BL54L15µ DVK and hope someone can clarify the documentation. The core problem is that SPIM20 and SPIM21 do not seem to work on the dedicated P2 SPI pins, even though the documentation suggests this is possible.

  • Hardware: BL54L15µ DVK (Rev 1)

  • SDK: nRF Connect SDK Toolchain v3.1.1

Documentation Reference

According to the nRF54L15 documentation, the peripherals have the following capabilities:

Configuration Overview:

SPIM00 : ... Use dedicated pins on GPIO port P2 ...
SPIM20 : ... Use GPIO port P1, or dedicated pins on P2
SPIM21 : ... Use GPIO port P1, or dedicated pins on P2

Found on : docs.nordicsemi.com/.../pin.html

-> SPIM00: Has dedicated pins on P2... ... SPIM20/21: Can use any pins on P1... Can connect across power domains to dedicated pins on P2

This "connect across power domains" phrase is key, it implies we should be able to use SPIM20 or SPIM21 on the same P2 pins that SPIM00 uses.

In reality, the only thing that works is the SPI00 on P2.

To establish a baseline, I configured &spi00 to use the P2 pins (connected to the mikroBUS connector) to communicate with a BHI260AP sensor. This works perfectly.

Here is my working overlay file for &spi00:

&mx25r64 {
    status = "disabled";
};
/delete-node/ &mx25r64;

&spi00 {
    compatible = "nordic,nrf-spim";
    status = "okay";
    pinctrl-0 = <&spi00_default>;
    pinctrl-1 = <&spi00_sleep>;
    pinctrl-names = "default", "sleep";
    cs-gpios = <&gpio2 9 GPIO_ACTIVE_LOW>;   /* P2.09 mikroBUS CS */

    bhi260ap: bhi260ap@0 {
        compatible = "bosch,bhi2xy";
        status = "okay";
        reg = <0>;
        spi-max-frequency = <DT_FREQ_M(2)>;
        variant = "BHI260AP";
        reset-gpios = <&gpio0 4 GPIO_ACTIVE_LOW>;   /* P0.04 mikroBUS RST */
    };
};

&pinctrl {
    spi00_default: spi00_default {
        group1 {
            psels = <NRF_PSEL(SPIM_SCK, 2, 1)>,    /* P2.01 mikroBUS SCK */
                    <NRF_PSEL(SPIM_MOSI, 2, 2)>;   /* P2.02 mikroBUS MOSI */
        };
        group2 {
            psels = <NRF_PSEL(SPIM_MISO, 2, 4)>;   /* P2.04 mikroBUS MISO */
            bias-pull-up;
        };
    };
    /* ... sleep config ... */
};


What Does NOT Work: SPIM20 / SPIM21 on P2.

Based on the documentation, I expected to be able to simply change the instance from &spi00 to &spi21 (or &spi20) and have it work over the same P2 pins.

When I try this, the SPI communication fails completely.

Here is my non-working overlay file (example using &spi21):

&mx25r64 {
    status = "disabled";
};
/delete-node/ &mx25r64;

&spi21 {
    compatible = "nordic,nrf-spim";
    status = "okay";
    pinctrl-0 = <&spi21_default>;
    pinctrl-1 = <&spi21_sleep>;
    pinctrl-names = "default", "sleep";
    cs-gpios = <&gpio2 9 GPIO_ACTIVE_LOW>;   /* P2.09 mikroBUS CS */

    bhi260ap: bhi260ap@0 {
        compatible = "bosch,bhi2xy";
        status = "okay";
        reg = <0>;
        spi-max-frequency = <DT_FREQ_M(2)>;
        variant = "BHI260AP";
        reset-gpios = <&gpio0 4 GPIO_ACTIVE_LOW>;   /* P0.04 mikroBUS RST */
    };
};

&pinctrl {
    spi21_default: spi21_default {
        group1 {
            psels = <NRF_PSEL(SPIM_SCK, 2, 1)>,    /* P2.01 mikroBUS SCK */
                    <NRF_PSEL(SPIM_MOSI, 2, 2)>;   /* P2.02 mikroBUS MOSI */
        };
        group2 {
            psels = <NRF_PSEL(SPIM_MISO, 2, 4)>;   /* P2.04 mikroBUS MISO */
            bias-pull-up;
        };
    };
    /* ... sleep config ... */
};

(Note: The same test fails when using &spi20)

My Question:

The hardware (pins, sensor, DVK) is proven to work with &spi00. The documentation explicitly states that SPIM20/21 "Can connect across power domains to dedicated pins on P2."

Why does this fail in practice? Am I misinterpreting the documentation? Or am I missing a specific configuration step (e.g., in Kconfig, or an extra devicetree property) that is required to correctly enable and route this "cross-domain" connection for SPIM20/21 to the P2 pins?

Any clarification on this discrepancy would be greatly appreciated.

Thank you.

  • Hi,

    Constant latency is a requirement for this (see Cross power-domain use). Have you enabled that? One way to do it is to add CONFIG_NRFX_POWER=y to prj.conf and enable constant latency using nrfx_power_constlat_mode_request().

    PS: Note that constant latency mode increased the idle current consumption.

  • Hi,

    Thank you for the suggestion regarding constant latency mode. I have implemented this as recommended, but unfortunately SPIM20/21 still fail to communicate on the P2 pins.

    What I implemented:

    1. Added this to prj.conf:
      CONFIG_NRFX_POWER=y
    2. Enabled constant latency mode early in boot sequence using a SYS_INIT hook at PRE_KERNEL_1 priority:
      #include <zephyr/init.h>
      #include <hal/nrf_power.h>
      
      static int enable_constant_latency_early(void)
      {
          printk("PRE_KERNEL_1: Triggering CONSTLAT task for cross-domain SPI...\n");
          nrf_power_task_trigger(NRF_POWER, NRF_POWER_TASK_CONSTLAT);
          k_busy_wait(100);  /* Small delay to ensure mode is active */
          printk("PRE_KERNEL_1: Constant latency mode activated\n");
          return 0;
      }
      
      SYS_INIT(enable_constant_latency_early, PRE_KERNEL_1, 0);
  • Hi,

    I missed that the driver supports handling constant latency automatically in SDK 3.1  and newer which I see you are using. So you should be fine with this as long as you add CONFIG_NRF_SYS_EVENT=y to your prj.conf. I did a quick test with a modified spi_loopback test and that works on the nRF54L15 DK:

    diff --git a/tests/drivers/spi/spi_loopback/boards/nrf54l15dk_nrf54l15_cpuapp.overlay b/tests/drivers/spi/spi_loopback/boards/nrf54l15dk_nrf54l15_cpuapp.overlay
    index de3eaf4514d..91c804ca023 100644
    --- a/tests/drivers/spi/spi_loopback/boards/nrf54l15dk_nrf54l15_cpuapp.overlay
    +++ b/tests/drivers/spi/spi_loopback/boards/nrf54l15dk_nrf54l15_cpuapp.overlay
    @@ -4,23 +4,38 @@
      * SPDX-License-Identifier: Apache-2.0
      */
     
    + / {
    +    chosen {
    +        zephyr,console = &uart30;
    +        zephyr,shell-uart = &uart30;
    +    };
    +};
    +
    +&uart30 {
    +    status = "okay";
    +};
    +
    +&uart20 {
    +    status = "disabled";
    +};
    + 
     &pinctrl {
    -	spi00_default: spi00_default {
    +	spi20_default: spi20_default {
     		group1 {
    -			psels = <NRF_PSEL(SPIM_MISO, 2, 9)>;
    +			psels = <NRF_PSEL(SPIM_MISO, 2, 4)>;
     		};
     		group2 {
    -			psels = <NRF_PSEL(SPIM_SCK, 2, 6)>,
    -				<NRF_PSEL(SPIM_MOSI, 2, 8)>;
    +			psels = <NRF_PSEL(SPIM_SCK, 2, 1)>,
    +				<NRF_PSEL(SPIM_MOSI, 2, 2)>;
     			nordic,drive-mode = <NRF_DRIVE_E0E1>;
     		};
     	};
     
    -	spi00_sleep: spi00_sleep {
    +	spi20_sleep: spi20_sleep {
     		group1 {
    -			psels = <NRF_PSEL(SPIM_SCK, 2, 6)>,
    -				<NRF_PSEL(SPIM_MISO, 2, 9)>,
    -				<NRF_PSEL(SPIM_MOSI, 2, 8)>;
    +			psels = <NRF_PSEL(SPIM_SCK, 2, 1)>,
    +				<NRF_PSEL(SPIM_MISO, 2, 4)>,
    +				<NRF_PSEL(SPIM_MOSI, 2, 2)>;
     			low-power-enable;
     		};
     	};
    @@ -28,10 +43,10 @@
     
     /delete-node/ &mx25r64;
     
    -&spi00 {
    +&spi20 {
     	status = "okay";
    -	pinctrl-0 = <&spi00_default>;
    -	pinctrl-1 = <&spi00_sleep>;
    +	pinctrl-0 = <&spi20_default>;
    +	pinctrl-1 = <&spi20_sleep>;
     	pinctrl-names = "default", "sleep";
     	overrun-character = <0x00>;
     	zephyr,pm-device-runtime-auto;
    diff --git a/tests/drivers/spi/spi_loopback/prj.conf b/tests/drivers/spi/spi_loopback/prj.conf
    index cde4871f305..b90c62363ab 100644
    --- a/tests/drivers/spi/spi_loopback/prj.conf
    +++ b/tests/drivers/spi/spi_loopback/prj.conf
    @@ -5,3 +5,4 @@ CONFIG_SPI_ASYNC=y
     CONFIG_SPI_LOG_LEVEL_INF=y
     CONFIG_ZTEST=y
     CONFIG_ZTEST_THREAD_PRIORITY=1
    +CONFIG_NRF_SYS_EVENT=y
    

    Log with P2.02 and P2.04 connected:

    *** Booting nRF Connect SDK v3.1.1-e2a97fe2578a ***
    *** Using Zephyr OS v4.1.99-ff8f0c579eeb ***
    SPI test on buffers TX/RX 0x20004620/0x20004600, frame size = 8
    Polling...Running TESTSUITE spi_extra_api_features
    ===================================================================
    START - test_spi_hold_on_cs
     PASS - test_spi_hold_on_cs in 0.001 seconds
    ===================================================================
    START - test_spi_lock_release
     PASS - test_spi_lock_release in 0.001 seconds
    ===================================================================
    TESTSUITE spi_extra_api_features succeeded
    Running TESTSUITE spi_extra_api_features
    ===================================================================
    START - test_spi_hold_on_cs
     PASS - test_spi_hold_on_cs in 0.001 seconds
    ===================================================================
    START - test_spi_lock_release
     PASS - test_spi_lock_release in 0.001 seconds
    ===================================================================
    TESTSUITE spi_extra_api_features succeeded
    Running TESTSUITE spi_loopback
    ===================================================================
    Testing loopback spec: SLOW
    START - test_nop_nil_bufs
     PASS - test_nop_nil_bufs in 0.001 seconds
    ===================================================================
    START - test_spi_async_call
     PASS - test_spi_async_call in 0.035 seconds
    ===================================================================
    START - test_spi_complete_large_transfers
     PASS - test_spi_complete_large_transfers in 0.034 seconds
    ===================================================================
    START - test_spi_complete_loop_mode_0
     PASS - test_spi_complete_loop_mode_0 in 0.001 seconds
    ===================================================================
    START - test_spi_complete_loop_mode_1
     PASS - test_spi_complete_loop_mode_1 in 0.001 seconds
    ===================================================================
    START - test_spi_complete_loop_mode_2
     PASS - test_spi_complete_loop_mode_2 in 0.001 seconds
    ===================================================================
    START - test_spi_complete_loop_mode_3
     PASS - test_spi_complete_loop_mode_3 in 0.001 seconds
    ===================================================================
    START - test_spi_complete_multiple
     PASS - test_spi_complete_multiple in 0.001 seconds
    ===================================================================
    START - test_spi_complete_multiple_timed
    Transfer took 306 us vs theoretical minimum 216 us
    Latency measurement: 90 us
     PASS - test_spi_complete_multiple_timed in 0.008 seconds
    ===================================================================
    START - test_spi_concurrent_transfer_different_spec
     PASS - test_spi_concurrent_transfer_different_spec in 0.001 seconds
    ===================================================================
    START - test_spi_concurrent_transfer_same_spec
     PASS - test_spi_concurrent_transfer_same_spec in 0.001 seconds
    ===================================================================
    START - test_spi_deinit
      zephyr,user miso-gpios or mosi-gpios are not defined
     SKIP - test_spi_deinit in 0.005 seconds
    ===================================================================
    START - test_spi_null_rx_buf_set
     PASS - test_spi_null_rx_buf_set in 0.001 seconds
    ===================================================================
    START - test_spi_null_tx_buf
     PASS - test_spi_null_tx_buf in 0.001 seconds
    ===================================================================
    START - test_spi_null_tx_buf_set
     PASS - test_spi_null_tx_buf_set in 0.001 seconds
    ===================================================================
    START - test_spi_null_tx_rx_buf_set
     PASS - test_spi_null_tx_rx_buf_set in 0.001 seconds
    ===================================================================
    START - test_spi_rx_bigger_than_tx
     PASS - test_spi_rx_bigger_than_tx in 0.001 seconds
    ===================================================================
    START - test_spi_rx_every_4
     PASS - test_spi_rx_every_4 in 0.001 seconds
    ===================================================================
    START - test_spi_rx_half_end
     PASS - test_spi_rx_half_end in 0.001 seconds
    ===================================================================
    START - test_spi_rx_half_start
     PASS - test_spi_rx_half_start in 0.001 seconds
    ===================================================================
    START - test_spi_same_buf_cmd
     PASS - test_spi_same_buf_cmd in 0.001 seconds
    ===================================================================
    START - test_spi_word_size_16
    E: Word sizes other than 8 bits are not supported
    Spi config invalid for this controller
     SKIP - test_spi_word_size_16 in 0.008 seconds
    ===================================================================
    START - test_spi_word_size_24
    E: Word sizes other than 8 bits are not supported
    Spi config invalid for this controller
     SKIP - test_spi_word_size_24 in 0.008 seconds
    ===================================================================
    START - test_spi_word_size_32
    E: Word sizes other than 8 bits are not supported
    Spi config invalid for this controller
     SKIP - test_spi_word_size_32 in 0.008 seconds
    ===================================================================
    START - test_spi_word_size_7
    E: Word sizes other than 8 bits are not supported
    Spi config invalid for this controller
     SKIP - test_spi_word_size_7 in 0.008 seconds
    ===================================================================
    START - test_spi_word_size_9
    E: Word sizes other than 8 bits are not supported
    Spi config invalid for this controller
     SKIP - test_spi_word_size_9 in 0.008 seconds
    ===================================================================
    START - test_spi_write_back
     PASS - test_spi_write_back in 0.001 seconds
    ===================================================================
    TESTSUITE spi_loopback succeeded
    Running TESTSUITE spi_loopback
    ===================================================================
    Testing loopback spec: FAST
    START - test_nop_nil_bufs
     PASS - test_nop_nil_bufs in 0.001 seconds
    ===================================================================
    START - test_spi_async_call
     PASS - test_spi_async_call in 0.018 seconds
    ===================================================================
    START - test_spi_complete_large_transfers
     PASS - test_spi_complete_large_transfers in 0.018 seconds
    ===================================================================
    START - test_spi_complete_loop_mode_0
     PASS - test_spi_complete_loop_mode_0 in 0.001 seconds
    ===================================================================
    START - test_spi_complete_loop_mode_1
     PASS - test_spi_complete_loop_mode_1 in 0.001 seconds
    ===================================================================
    START - test_spi_complete_loop_mode_2
     PASS - test_spi_complete_loop_mode_2 in 0.001 seconds
    ===================================================================
    START - test_spi_complete_loop_mode_3
     PASS - test_spi_complete_loop_mode_3 in 0.001 seconds
    ===================================================================
    START - test_spi_complete_multiple
     PASS - test_spi_complete_multiple in 0.001 seconds
    ===================================================================
    START - test_spi_complete_multiple_timed
    Transfer took 199 us vs theoretical minimum 108 us
    Latency measurement: 91 us
     PASS - test_spi_complete_multiple_timed in 0.008 seconds
    ===================================================================
    START - test_spi_concurrent_transfer_different_spec
     PASS - test_spi_concurrent_transfer_different_spec in 0.001 seconds
    ===================================================================
    START - test_spi_concurrent_transfer_same_spec
     PASS - test_spi_concurrent_transfer_same_spec in 0.001 seconds
    ===================================================================
    START - test_spi_deinit
      zephyr,user miso-gpios or mosi-gpios are not defined
     SKIP - test_spi_deinit in 0.005 seconds
    ===================================================================
    START - test_spi_null_rx_buf_set
     PASS - test_spi_null_rx_buf_set in 0.001 seconds
    ===================================================================
    START - test_spi_null_tx_buf
     PASS - test_spi_null_tx_buf in 0.001 seconds
    ===================================================================
    START - test_spi_null_tx_buf_set
     PASS - test_spi_null_tx_buf_set in 0.001 seconds
    ===================================================================
    START - test_spi_null_tx_rx_buf_set
     PASS - test_spi_null_tx_rx_buf_set in 0.001 seconds
    ===================================================================
    START - test_spi_rx_bigger_than_tx
     PASS - test_spi_rx_bigger_than_tx in 0.001 seconds
    ===================================================================
    START - test_spi_rx_every_4
     PASS - test_spi_rx_every_4 in 0.001 seconds
    ===================================================================
    START - test_spi_rx_half_end
     PASS - test_spi_rx_half_end in 0.001 seconds
    ===================================================================
    START - test_spi_rx_half_start
     PASS - test_spi_rx_half_start in 0.001 seconds
    ===================================================================
    START - test_spi_same_buf_cmd
     PASS - test_spi_same_buf_cmd in 0.001 seconds
    ===================================================================
    START - test_spi_word_size_16
    E: Word sizes other than 8 bits are not supported
    Spi config invalid for this controller
     SKIP - test_spi_word_size_16 in 0.008 seconds
    ===================================================================
    START - test_spi_word_size_24
    E: Word sizes other than 8 bits are not supported
    Spi config invalid for this controller
     SKIP - test_spi_word_size_24 in 0.008 seconds
    ===================================================================
    START - test_spi_word_size_32
    E: Word sizes other than 8 bits are not supported
    Spi config invalid for this controller
     SKIP - test_spi_word_size_32 in 0.008 seconds
    ===================================================================
    START - test_spi_word_size_7
    E: Word sizes other than 8 bits are not supported
    Spi config invalid for this controller
     SKIP - test_spi_word_size_7 in 0.008 seconds
    ===================================================================
    START - test_spi_word_size_9
    E: Word sizes other than 8 bits are not supported
    Spi config invalid for this controller
     SKIP - test_spi_word_size_9 in 0.008 seconds
    ===================================================================
    START - test_spi_write_back
     PASS - test_spi_write_back in 0.001 seconds
    ===================================================================
    TESTSUITE spi_loopback succeeded
    
    ------ TESTSUITE SUMMARY START ------
    
    SUITE PASS - 100.00% [spi_extra_api_features]: pass = 2, fail = 0, skip = 0, total = 2 duration = 0.002 seconds
     - PASS - [spi_extra_api_features.test_spi_hold_on_cs] duration = 0.001 seconds
     - PASS - [spi_extra_api_features.test_spi_lock_release] duration = 0.001 seconds
    
    SUITE PASS - 100.00% [spi_loopback]: pass = 21, fail = 0, skip = 6, total = 27 duration = 0.140 seconds
     - PASS - [spi_loopback.test_nop_nil_bufs] duration = 0.001 seconds
     - PASS - [spi_loopback.test_spi_async_call] duration = 0.035 seconds
     - PASS - [spi_loopback.test_spi_complete_large_transfers] duration = 0.034 seconds
     - PASS - [spi_loopback.test_spi_complete_loop_mode_0] duration = 0.001 seconds
     - PASS - [spi_loopback.test_spi_complete_loop_mode_1] duration = 0.001 seconds
     - PASS - [spi_loopback.test_spi_complete_loop_mode_2] duration = 0.001 seconds
     - PASS - [spi_loopback.test_spi_complete_loop_mode_3] duration = 0.001 seconds
     - PASS - [spi_loopback.test_spi_complete_multiple] duration = 0.001 seconds
     - PASS - [spi_loopback.test_spi_complete_multiple_timed] duration = 0.008 seconds
     - PASS - [spi_loopback.test_spi_concurrent_transfer_different_spec] duration = 0.001 seconds
     - PASS - [spi_loopback.test_spi_concurrent_transfer_same_spec] duration = 0.001 seconds
     - SKIP - [spi_loopback.test_spi_deinit] duration = 0.005 seconds
     - PASS - [spi_loopback.test_spi_null_rx_buf_set] duration = 0.001 seconds
     - PASS - [spi_loopback.test_spi_null_tx_buf] duration = 0.001 seconds
     - PASS - [spi_loopback.test_spi_null_tx_buf_set] duration = 0.001 seconds
     - PASS - [spi_loopback.test_spi_null_tx_rx_buf_set] duration = 0.001 seconds
     - PASS - [spi_loopback.test_spi_rx_bigger_than_tx] duration = 0.001 seconds
     - PASS - [spi_loopback.test_spi_rx_every_4] duration = 0.001 seconds
     - PASS - [spi_loopback.test_spi_rx_half_end] duration = 0.001 seconds
     - PASS - [spi_loopback.test_spi_rx_half_start] duration = 0.001 seconds
     - PASS - [spi_loopback.test_spi_same_buf_cmd] duration = 0.001 seconds
     - SKIP - [spi_loopback.test_spi_word_size_16] duration = 0.008 seconds
     - SKIP - [spi_loopback.test_spi_word_size_24] duration = 0.008 seconds
     - SKIP - [spi_loopback.test_spi_word_size_32] duration = 0.008 seconds
     - SKIP - [spi_loopback.test_spi_word_size_7] duration = 0.008 seconds
     - SKIP - [spi_loopback.test_spi_word_size_9] duration = 0.008 seconds
     - PASS - [spi_loopback.test_spi_write_back] duration = 0.001 seconds
    
    ------ TESTSUITE SUMMARY END ------
    
    ===================================================================
    PROJECT EXECUTION SUCCESSFUL

    Can you test this on your end?

Related