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

Help needed for excessive standby current for SPI slave

Hello, I am using the nRF51822 with SDK 10.0, S110 softdevice, and a SPI slave interface. The SPI slave interface works, but the standby power consumption of the nRF is high, ~300 uA. I suspect that the high speed crystal is running in the background.

I use an interrupt on a pin to wake the nRF and perform the SPI transfer. Upon waking I signal the master that I am ready with a separate output pin. When the transfer is done I go back into power management via sd_app_evt_wait().

Here is the wake-up pin initialization:

err_code = nrf_drv_gpiote_init();
APP_ERROR_CHECK(err_code);

// Configure event handler for EXTERNAL_WAKEUP_PIN, low accuracy for low power
nrf_drv_gpiote_in_config_t wakePinConfig = GPIOTE_CONFIG_IN_SENSE_LOTOHI(false);

err_code = nrf_drv_gpiote_in_init(EXTERNAL_WAKEUP_PIN, &wakePinConfig, wakeupHandler);

APP_ERROR_CHECK(err_code);

nrf_drv_gpiote_in_event_enable(EXTERNAL_WAKEUP_PIN, true);

SPI Slave initialization:

nrf_drv_spis_config_t spis_config = NRF_DRV_SPIS_DEFAULT_CONFIG(SPIS_INSTANCE_NUMBER);

spis_config.miso_pin = SPIS_MISO_PIN;
spis_config.mosi_pin = SPIS_MOSI_PIN;
spis_config.sck_pin = SPIS_SCK_PIN;
spis_config.csn_pin = SPIS_CSN_PIN;
spis_config.mode = NRF_DRV_SPIS_MODE_1;
spis_config.bit_order = NRF_DRV_SPIS_BIT_ORDER_MSB_FIRST;
spis_config.def = DEF_CHARACTER;
spis_config.orc = ORC_CHARACTER;

// Open the SPI peripheral
err_code = nrf_drv_spis_init(&m_spis, &spis_config, spi_slave_event_handler);
APP_ERROR_CHECK(err_code);

I have tried enabling the SPI interface on-the-fly in my wakeup handler but this did not help. It worked, but the power consumption is the same, e.g.:

Wakeup event:

nrf_drv_spis_init(...)
raise_handshake_output()
wait for transfer event...
lower_handshake_output()
nrf_drv_spis_uninit(...)
sd_app_evt_wait() // wait for next Wakeup Event.

I know that my CSN input pin is high at all times except when the handshake output has been raised to signal the master.

Other details:

// Initialize the SoftDevice handler module.
SOFTDEVICE_HANDLER_INIT(NRF_CLOCK_LFCLKSRC_RC_250_PPM_TEMP_4000MS_CALIBRATION, NULL);

The standby current is measured with a high speed current to voltage device in series with VCC and an oscilloscope where the advertising interval can also be observed.

  • It looks like you are using the GPIOTE IN event to wake your device. This is known to burn a lot of power on the nRF51822. You should use the PORT event instead if you need a lower power solution. Search this forum and you'll find a lot of information on how to do this.

  • Hi jhartmann

    Have you looked at the nRF51 current consumption guide, troubleshooting section? That could give some hints. As stated in the nrF51 current consumption guide, the current consumption of the nRF51 SPIS should be very low when CSN line is set high, i.e. when the SPI master is not transmitting.

    I have seen high current consumption in the past when trying nRF51 SPIS connected to SPI master. That was because the nRF51 was powered through the SPIS configured GPIO pins (from the SPI master device) and did not power reset when I cut power from the board. I had to disconnect the SPIS pins from the SPI master, power reset, then connect the SPIS and SPI master together again. It is anyway also possible to reset the nRF51 with the command

    nrfjprog --pinreset
    

    so you dont need to disconnect the SPIS. Perhaps that does not apply directly to your case anyway as lack of reset after programming should add ~1mA but not the ~300uA that you are seeing.

    I have tested the SPIS current consumption when connected with another board that runs SPI master in SDK 11.0.0. It is low current. For that to happen, I have disabled constant latency mode and disabled logging. I have tried SPIS current consumption in older SDK versions and it has been low current as well.

    So my question, have you tried standard SPIS example in SDK 10 without softdevice, in order to see if you get low current consumption?

    Perhaps you can incrementally comment out initialization code in your example to see when you get the desired current consumption. That way you can narrow down what the source of the high current consumption is.

  • correct me if Im wrong John, but I was under the impression that using

    GPIOTE_CONFIG_IN_SENSE_LOTOHI(false);
    

    uses the PORT event, which is low current, while the

    GPIOTE_CONFIG_IN_SENSE_LOTOHI(true);
    

    would use the GPIOTE IN events, which are high current.

    Seems like jhartmann is using the former.

  • Yes thanks, I've gone through the current consumption guide thoroughly and finally decided to post here because I feel I've tried everything. I will try incrementally disabling initialization as you suggest.

  • This was also my understanding of how it is supposed to work. We initially had "true" (high accuracy) and the current was higher. Disabling high accuracy lowered the current significantly but not to the level we need.

Related