I've read many similar issues that were raised regarding high SPI power consumption, looked at various examples, but can't seem to find any issue that is close to what i'm observing.
I am developing a custom firmware for the RuuviTag that uses sdk17.0.2, based off the nrf sdk ble_app_template peripheral example. I have backported an spi wrapper and lis2dh12 accelerometer driver source from the original RuuviTag FW that uses sdk12. In terms of functionality, everything works correctly, but I am struggling with high power usage whenever the accelerometer is in use.
So far i believe i have narrowed down the problem to the SPI peripheral. The way my FW works is that every 1s, an app timer calls a handler that reads out axis acceleration values from the lis2dh12 via SPI (code snippet below). My guess is that the SPI peripheral randomly fails go to sleep properly after an SPI event happens. Please see the scope charts below:


The higher step is usually between 2-4mA.
What makes me believe that the issue lies with SPI is that the high/low power consumption interval duration is always a multiple of 1 second, same as the period of SPI transfers.
I have tried various configuration changes, enabling/disabling easyDMA, trying different wait/sleep functions in the wait loop, nothing has had any effect.
Additionally, no other code is really suspect as the original sdk12 based FW also reads accelerometer data via SPI at, what i believe, is 1s intervals, yet current usage (excluding transmitting peaks from bluetooth) is never over maybe 100-200uA. Furthermore, commenting out the entire SPI (and accelerometer) initialization gets the power usage permanently at the lower level, but leaving the initialization and removing the periodic data transfers results in the device getting stuck at the higher power level. Something else that draws suspicion to the SPI driver is that the SPI driver backend has been rewritten between the versions.
Below is the code used for the SPI transfer (originally taken from the sdk12 FW version, i updated the code to use nrfx)
static const nrfx_spim_t spi = NRFX_SPIM_INSTANCE(SPI_INSTANCE);
volatile bool spi_xfer_done;
static bool initDone = false;
extern void spi_init(void)
{
nrfx_spim_config_t spi_config = NRFX_SPIM_DEFAULT_CONFIG;
spi_config.sck_pin = SPIM0_SCK_PIN;
spi_config.miso_pin = SPIM0_MISO_PIN;
spi_config.mosi_pin = SPIM0_MOSI_PIN;
spi_config.frequency = NRF_DRV_SPI_FREQ_1M;
nrf_gpio_pin_dir_set(SPIM0_SS_ACC_PIN, NRF_GPIO_PIN_DIR_OUTPUT);
nrf_gpio_cfg_output(SPIM0_SS_ACC_PIN);
nrf_gpio_pin_set(SPIM0_SS_ACC_PIN);
APP_ERROR_CHECK(nrfx_spim_init(&spi, &spi_config, spi_event_handler, NULL));
spi_xfer_done = true;
initDone = true;
}
extern bool spi_isInitialized(void)
{
return initDone;
}
extern SPI_Ret spi_transfer_lis2dh12(uint8_t* const p_toWrite, uint8_t count, uint8_t* const p_toRead)
{
SPI_Ret retVal = SPI_RET_OK;
if ((NULL == p_toWrite) || (NULL == p_toRead))
{
retVal = SPI_RET_ERROR;
}
/* check if an other SPI transfer is running */
if ((true == spi_xfer_done) && (SPI_RET_OK == retVal))
{
spi_xfer_done = false;
nrf_gpio_pin_clear(SPIM0_SS_ACC_PIN);
nrfx_spim_xfer_desc_t xfer_desc = NRFX_SPIM_XFER_TRX(p_toWrite, count, p_toRead, count);
nrfx_spim_xfer(&spi, &xfer_desc, 0);
while (!spi_xfer_done)
{
nrf_pwr_mgmt_run();
}
nrf_gpio_pin_set(SPIM0_SS_ACC_PIN);
retVal = SPI_RET_OK;
}
else
{
retVal = SPI_RET_BUSY;
}
return retVal;
}
Any tips would be greatly appreciated, so thank you very much in advance for the help