This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Increased idle current draw in nRF5340 when SPI4 chosen over SPI1

Platform: nRF5340-DK

Tools: I am using SDK 1.5.0 (but seen on earlier SDKs too)

Configuration: Using high speed spi pins whether for SPI1 or SPI4

&spi1 {
compatible = "nordic,nrf-spim";
status = "okay";
mosi-pin = <9>;
miso-pin = <10>;
sck-pin = <8>;
};

If I use SPI1 I see around 40uA idle current draw when running my application 

If I change to  use SPI4 I see around 640uA idle current draw when running my application.

See attached screenshots taken from the power profiler app.

I would like to use SPI4 to enable the higher data rates, so I can get the SPI transfers over quicker and hence save power

However the jump from 40uA to 640uA idle current makes this unworkable

I was expecting maybe slightly higher current during operation, but not a huge jump in current when idle.

Is this a known issue?

  • We have reproduced the issue on two boards. We are working on some theories and will keep you updated.

  • Below follows findings about this issue and a proposed temporary workaround. We can confirm different harwdware behaviour between SPI1 and SPI4, and our team is working on a proper workaround.

    First, for SPI1, current consumption should also be lower than 40uA. If you add CONFIG_SERIAL=n to prj.conf, then idle should drop to around 3uA(measured in the blinky sample you posted).

    When it comes to SPI4, only disabling logging does not help as we are still seeing around 600uA. However, if we comment out SPI_sendData, then the current consumption becomes normal. This shows us the current draw is related to SPI4 and TX.

    The following code demonstrates the increased current, and also how it could be minimized.

    typedef struct ArrayList
    {
        uint8_t buffer[100];
    } ArrayList_type;
    
    static ArrayList_type spi_tx[100];
    static ArrayList_type * spi_tx_p = spi_tx;
    static ArrayList_type spi_rx[100];
    static ArrayList_type * spi_rx_p = spi_rx; 
    
    void main(void)
    {
        NRF_SPIM4->PSEL.MOSI = 11;
        NRF_SPIM4->PSEL.MISO = 12;
        NRF_SPIM4->PSEL.SCK = 13;
        NRF_SPIM4->RXD.PTR = (uint32_t)spi_rx_p;
        NRF_SPIM4->RXD.MAXCNT = 100;
        NRF_SPIM4->TXD.PTR = (uint32_t)spi_tx_p;
        NRF_SPIM4->TXD.MAXCNT = 100;
        NRF_SPIM4->ENABLE = 7;    
        
        while (1) {
            NRF_SPIM4->ENABLE = 7;
            NRF_SPIM4->TXD.PTR = (uint32_t)spi_tx_p;
            NRF_SPIM4->TXD.MAXCNT = 100;
            NRF_SPIM4->TASKS_START = 1;
            k_msleep(100);
    
            NRF_SPIM4->TASKS_STOP = 1;
            NRF_SPIM4->ENABLE = 0;
            k_msleep(500);
        }
    }

    The code sets up an SPI transaction every 600ms. After it starts, it waits 100ms, then runs ENABLE=0. This makes the device go back to a "normal" idle and it now draws 3uA.

    If one remove ENABLE=0, then the current draw stays at 700uA in idle(which it, of course, should not).

    So, the temporary proposal is to disable SPI after the transaction. I could get back to you regarding the best way to do this in harmony with the driver. It might be either to use the ENABLE register directly after the transaction, or perhaps, to use the driver's uninit function.

  • Thank you for looking into this, I will try your initial workaround and see if I can see the same current drop as yourselves.

  • I can confirm this works for my application. I am using the method with the ENABLE register directly. Also I see no additional latency either due to the enabling and disabling which is good. I will leave this in my code until there is a more formal fix.

    Thanks again for you help

Related