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

SPI instance taking up a lot of power when enabled.

SDK version: 15.3

Soft-device version: 6.1.1

Hi,

I've been working on a low power application where every 10's of uA is important. My application requires SPI as Master on nRF52832 but as soon as I enable my SPI my current shoots up to mA range from uA. 

I used "SPI"example present in "..\nRF5_SDK_15.3.0_59ac345\examples\peripheral" to understand the configuration of SPI. Could you please tell my why would this happen?

I read a couple of articles where people faced similar current consumption issue. Or do I have to do some disabling of SPI to save power?

  • Hi, the SPI example is not power optimized. nrf_delay_ms() is just using a loop of NOP instructions. You should start the SPI transfer from an RTC interrupt or similar, and keep the CPU in a WFE loop.

    I modified the SPI example to include an app_timer which uses the RTC to give you an interrupt every 100ms. The power consumption is 2uA between the transfers. Also remember to disable logging in sdk_config.h.

    #include "nrf_drv_spi.h"
    #include "app_util_platform.h"
    #include "nrf_gpio.h"
    #include "nrf_delay.h"
    #include "boards.h"
    #include "app_error.h"
    #include <string.h>
    #include "nrf_log.h"
    #include "nrf_log_ctrl.h"
    #include "nrf_log_default_backends.h"
    #include "app_timer.h"
    
    #define SPI_INSTANCE  0 /**< SPI instance index. */
    static const nrf_drv_spi_t spi = NRF_DRV_SPI_INSTANCE(SPI_INSTANCE);  /**< SPI instance. */
    
    #define TEST_STRING "Nordic"
    static uint8_t       m_tx_buf[] = TEST_STRING;           /**< TX buffer. */
    static uint8_t       m_rx_buf[sizeof(TEST_STRING) + 1];    /**< RX buffer. */
    static const uint8_t m_length = sizeof(m_tx_buf);        /**< Transfer length. */
    
    /**
     * @brief SPI user event handler.
     * @param event
     */
    void spi_event_handler(nrf_drv_spi_evt_t const * p_event,
                           void *                    p_context)
    {
        NRF_LOG_INFO("Transfer completed.");
        if (m_rx_buf[0] != 0)
        {
            NRF_LOG_INFO(" Received:");
            NRF_LOG_HEXDUMP_INFO(m_rx_buf, strlen((const char *)m_rx_buf));
        }
    }
    
    static void spi_transfer_handler(void * p_context){
            memset(m_rx_buf, 0, m_length);
            APP_ERROR_CHECK(nrf_drv_spi_transfer(&spi, m_tx_buf, m_length, m_rx_buf, m_length));
    }
    
    int main(void)
    {
        bsp_board_init(BSP_INIT_LEDS);
    
        APP_ERROR_CHECK(NRF_LOG_INIT(NULL));
        NRF_LOG_DEFAULT_BACKENDS_INIT();
    
        nrf_drv_spi_config_t spi_config = NRF_DRV_SPI_DEFAULT_CONFIG;
        spi_config.ss_pin   = SPI_SS_PIN;
        spi_config.miso_pin = SPI_MISO_PIN;
        spi_config.mosi_pin = SPI_MOSI_PIN;
        spi_config.sck_pin  = SPI_SCK_PIN;
        APP_ERROR_CHECK(nrf_drv_spi_init(&spi, &spi_config, spi_event_handler, NULL));
    
        NRF_CLOCK->TASKS_LFCLKSTART = 1;
        while(NRF_CLOCK->EVENTS_LFCLKSTARTED == 0){
        }
        NRF_CLOCK->EVENTS_LFCLKSTARTED = 0;
        APP_ERROR_CHECK(app_timer_init());
        APP_TIMER_DEF(spi_timer_id);
        APP_ERROR_CHECK(app_timer_create(&spi_timer_id, APP_TIMER_MODE_REPEATED, spi_transfer_handler));
        APP_ERROR_CHECK(app_timer_start(spi_timer_id, APP_TIMER_TICKS(100), NULL));
    
        NRF_LOG_INFO("SPI example started.");
    
        while (1)
        {
            NRF_LOG_FLUSH();
            __WFE();
        }
    }

  • Hi,

    I had figured it out on my own and had done the implementation with SW timer. 

    There's a weird thing that I'm noticing that, the current consumption is not same in every transaction.

    I make a transaction in every 2 seconds, sometimes the current consumption is as low as 1.3mA and sometimes it's as high as 7mA. RF and data logging is disabled only SPI is running on every 2 second interrupt.

    What is the number shall I believe?

    Test Setup:

    1.  I'm using nRF52DK with PPK.

    2.  PPK is in DK mode and powered by DK.

    3.  DK is powered using USB (I understand that the document mentions that there will be uncertainty in measurements when powered with USB), but will the number be that bad? I've done my previous analysis with an Oscilloscope and that time it was powered with USB only so I want to keep the setup same by only swapping Oscilloscope with PPK.

  • So when you get an interrupt the CPU wakes up and starts the SPI transfer. The CPU is on for a very sort time, but the run current can be as high as 8mA, depending on configuration.: https://infocenter.nordicsemi.com/topic/com.nordic.infocenter.nrf52832.ps.v1.1/cpu.html?cp=3_1_0_6_1#topic

    The resolution on the PPK is probably not good enough to capture every CPU spike, but only the actual SPI run current which is 1.2-2mA depending on configuration. That's probably why the peak current is varying.

    Can you try to use the trigger window instead? It has a higher resolution.

Related