4 second current spikes during sleep

Hello All,

I am getting these ~3.5mA current spikes very 4 seconds and I can't seem to figure what the cause of them is. some of the spikes have a single spike/pulse while other have multiple. please see the attached images. I have commented out everything except the while in the main function and no difference. I have also commented out the enabling of the DCDC and still the same issue. any help would be greatly appreciate. I have a feeling its in the project config setting but tried commenting out what I thought may be the cause but no change either. 

I am using a custom board with 52833 and nRF Connect SDK 2.0.0. the board does have other ICs(hall sensors) but I measured their consumption and had no spikes.

while (1) {
		//k_sleep(K_SECONDS(1));
		//k_msleep(500);
		
		__WFE();
}

my project config file



#CONFIG_DK_LIBRARY=y

# Config logger
CONFIG_LOG=n
CONFIG_USE_SEGGER_RTT=n
CONFIG_LOG_BACKEND_RTT=n
CONFIG_LOG_BACKEND_UART=n
CONFIG_LOG_DEFAULT_LEVEL=3
CONFIG_DEBUG_OPTIMIZATIONS=n
# CONFIG_LOG_MODE_IMMEDIATE=n


CONFIG_SERIAL=n
CONFIG_CONSOLE=n
CONFIG_UART_CONSOLE=n

# Config Bluetooth
CONFIG_BT=y
##CONFIG_BT_DEBUG_LOG=y
##CONFIG_BT_SMP=y
CONFIG_BT_PERIPHERAL=y
CONFIG_BT_DIS=y
CONFIG_BT_DIS_PNP=n
# CONFIG_BT_BAS=y
# CONFIG_BT_HRS=y
CONFIG_BT_DEVICE_NAME="XXX Sensor"
CONFIG_BT_DEVICE_APPEARANCE=0
#CONFIG_BT_DEVICE_APPEARANCE=833
CONFIG_BT_LL_SOFTDEVICE=y
CONFIG_BT_MAX_CONN=1
CONFIG_BT_GAP_PERIPHERAL_PREF_PARAMS=y
CONFIG_BT_PERIPHERAL_PREF_MIN_INT=40
CONFIG_BT_PERIPHERAL_PREF_MAX_INT=45

CONFIG_BT_BUF_ACL_RX_SIZE=251
CONFIG_BT_BUF_ACL_TX_SIZE=251
CONFIG_BT_L2CAP_TX_MTU=247
CONFIG_BT_CTLR_DATA_LENGTH_MAX=251
CONFIG_BT_BUF_ACL_TX_COUNT=10



# CONFIG_CLOCK_CONTROL_NRF_FORCE_ALT=y wh
CONFIG_CLOCK_CONTROL_NRF=y
CONFIG_CLOCK_CONTROL_NRF_K32SRC_RC=y
CONFIG_CLOCK_CONTROL_NRF_K32SRC_XTAL=n
# CONFIG_CLOCK_CONTROL_NRF_K32SRC_XTAL is not set
# CONFIG_CLOCK_CONTROL_NRF_K32SRC_SYNTH is not set
# CONFIG_CLOCK_CONTROL_NRF_K32SRC_EXT_LOW_SWING is not set
# CONFIG_CLOCK_CONTROL_NRF_K32SRC_EXT_FULL_SWING is not set
CONFIG_CLOCK_CONTROL_NRF_K32SRC_RC_CALIBRATION=y
CONFIG_CLOCK_CONTROL_NRF_CALIBRATION_LF_ALWAYS_ON=y
CONFIG_CLOCK_CONTROL_NRF_K32SRC_500PPM=y
CONFIG_GPIO_AS_PINRESET=n


CONFIG_GPIO=y
CONFIG_GPIO_NRFX=y
CONFIG_NRFX_GPIOTE=y
CONFIG_SPI=y

#CONFIG_ASSERT=y

#CONFIG_NRFX_PRS_BOX_2=y

# CONFIG_NRFX_TIMER0=y
CONFIG_NRFX_TIMER1=y
CONFIG_NRFX_TIMER2=y
CONFIG_NRFX_TIMER3=y
CONFIG_NRFX_TIMER4=y
CONFIG_NRFX_PPI=y
CONFIG_NRFX_GPIOTE_NUM_OF_EVT_HANDLERS=2
CONFIG_NRFX_SPIM0=y
CONFIG_NRFX_SPIM1=y
CONFIG_COUNTER=y
#CONFIG_COUNTER_TIMER1=y


CONFIG_NRFX_RTC2=y
CONFIG_NRFX_POWER=y




##CONFIG_PM=y
# Required to disable default behavior of deep sleep on timeout
##CONFIG_PM_DEVICE=y
#CONFIG_GPIO=y
# Optional select RAM retention (nRF52 only)
#CONFIG_APP_RETENTION=y








Parents
  • Hello, 

    Please set CONFIG_CLOCK_CONTROL_NRF_CALIBRATION_MAX_SKIP=0 and then try to adjust the  CONFIG_CLOCK_CONTROL_NRF_CALIBRATION_PERIOD setting to see if it affects the interval of your current spike. The 2nd screenshot looks could be showing the clock calibration event (The 32K RC oscillator is calibrated periodically against the HF crystal oscillator). 

    Best regards,

    Vidar

  • Hi Vidar,

    That seems to be it. I set the following

    CONFIG_CLOCK_CONTROL_NRF_CALIBRATION_MAX_SKIP=0
    CONFIG_CLOCK_CONTROL_NRF_CALIBRATION_PERIOD=2000
    and period did change accordingly. please see plot.
    So with that said, I have few questions. 
    1) will an external 32kHz crystal use less power? or
    2) Since we know our device will be operating in a fairly temp controlled environment, what do you think would be wise settings to minimize power consumption but not get some egregious clock drift? 
    for example, do the cal every x number of deg change if possible. what do you think that x should be
    or do it every x seconds(what do you think that x should be)
    your help is greatly appreciated.
    Regards,
    Wael
Reply
  • Hi Vidar,

    That seems to be it. I set the following

    CONFIG_CLOCK_CONTROL_NRF_CALIBRATION_MAX_SKIP=0
    CONFIG_CLOCK_CONTROL_NRF_CALIBRATION_PERIOD=2000
    and period did change accordingly. please see plot.
    So with that said, I have few questions. 
    1) will an external 32kHz crystal use less power? or
    2) Since we know our device will be operating in a fairly temp controlled environment, what do you think would be wise settings to minimize power consumption but not get some egregious clock drift? 
    for example, do the cal every x number of deg change if possible. what do you think that x should be
    or do it every x seconds(what do you think that x should be)
    your help is greatly appreciated.
    Regards,
    Wael
Children
  • Hi Wael,

    Wael said:
    1) will an external 32kHz crystal use less power? or

    The internal RC oscillator will lead to a slightly higher average current for the following reasons: 

    1. The Bluetooth controller will need to increase its RADIO RX listening windows to compensate for the additional clock drift compared to the LF crystal oscillator.

    2. Requires periodic calibration,

    3. RC oscillator has a higher run current.

    You can estimate how much impact the clock source will have on your application (in terms of average power consumption) by using our online power profiler here:   

       Online Power Profiler for Bluetooth LE   

    Wael said:
    2) Since we know our device will be operating in a fairly temp controlled environment, what do you think would be wise settings to minimize power consumption but not get some egregious clock drift? 
    for example, do the cal every x number of deg change if possible. what do you think that x should be
    or do it every x seconds(what do you think that x should be)

    I think you can extend the interval to 8 seconds. From the PS:

    Regards,

    Vidar

  • Hi Vidar,

    Thank you for your reply. this makes complete sense. I now have another power consumption issue. My app does the following using PPI, SPIM, GPIOTE, and timers

    the PPI configuration is as follow:

    1) Upon receiving a GPIOTE trigger from an IMU(every 8.3 seconds), read its data (this is operating on a dedicated spi bus, SPIM0)

    2) write a dummy read command to an FRAM IC to wake it up from hibernate state (SPIM1 bus)

    3) trigger timer for 8ms from the start of the FRAM SPIM transaction(step 2)(period for FRAM to become stable from hibernate state)

    4) write the WREN(write enable) command to the FRAM upon completion of the 8ms timer

    5) write the (write command, address, data) to the FRAM

    6) write the hibernate command to the FRAM

    the multiple writes(aside from step 5) can NOT be combined as the bus CS pin needs to be toggled for the memory chip to accept the commands.

    to do this, I used 2 spi buses and 4 timers(one timer mode for the 8ms delay and 4 counters)

    In sum, my code works exactly as described and verified using oscilloscope. 

    my issue is after the first PPI transaction is triggered, something is consuming power and/or is staying on. has between 650 and 850us periods. please see the first plot below. Note: approx. 200uA of the 600uA is from my external peripherals on the board. 

    the 2nd plot shows this issue does not exist prior to the first PPI transaction. 

    I do not think its a timer issue. I have read that the EasyDMA does consume ~1.5mA but that should only be during transmission. and the frequency of these pulses do not correlate to any SPI transaction. I have not been able to isolate the cause of this and your time and effort would be greatly appreciated.

    Regards,

    Wael

  • Hi Wael,

    Could you please try to use a GPIOTE PORT event to detect when the IMU's interrupt line is asserted and trigger the SPI task from your app instead of using PPI? You should see a lower floor current when using GPIOTE PORT event compared to when you have IN events enabled.

    [153] GPIOTE: GPIOTE with low-power latency setting does not register IN events in System ON IDLE

    Regards,

    Vidar

  • Hi Vidar,

    Thank you for your suggestion, but I am not using the 5340 which is what your link, I am using 52833 and SDK 2.0.0.

    with that said, here is my function that initializes the GPIOTE pin

    void configure_imu_int1_gpiote(void)
    {
        nrfx_err_t err = NRFX_SUCCESS;
    
         __ASSERT (!nrfx_gpiote_is_init(),"nrfx_gpiote_is_init Failed");
        
        static const nrfx_gpiote_input_config_t input_config = {
    		.pull = NRF_GPIO_PIN_PULLDOWN,
    	};
    
    	const nrfx_gpiote_trigger_config_t trigger_config = {
    		.trigger = NRFX_GPIOTE_TRIGGER_LOTOHI,
    		.p_in_channel = NULL, //&in_channel,
    	};
    
        err = nrfx_gpiote_input_configure(IMU_INT1_PIN,
    					  &input_config,
    					  &trigger_config,
    					  NULL);
        if (err != NRFX_SUCCESS) {
    		LOG_ERR("Failed to nrfx_gpiote_input_configure, error: 0x%08X", err);
    		return;
    	}
    
        //nrfx_gpiote_in_event_enable(IMU_INT1_PIN, false);
        nrfx_gpiote_trigger_enable(IMU_INT1_PIN, false);
    }

    I am NOT using IN Event per my configuration. Please note this power issue only happens after all configurations and ONLY after the IMU int pin is triggered. so after power on for approx 8 seconds, the current level is as expected. only after the int trigger this issue happens. again, this issue is driving me crazy and eating lots of my time. any other suggestions please? as always, your help is greatly appreciated.

    Regards,

    here is some of my code

    timers setup

    static const nrfx_timer_t m_imu_acq_cnt_timer = NRFX_TIMER_INSTANCE(1);
    static const nrfx_timer_t m_fram_hibernate_delay_timer = NRFX_TIMER_INSTANCE(2);
    static const nrfx_timer_t m_fram_spim_start_cnt_timer = NRFX_TIMER_INSTANCE(3);
    static const nrfx_timer_t m_fram_spim_end_cnt_timer = NRFX_TIMER_INSTANCE(4);
    
    
    void configure_imu_ppi_timer(void)
    {
        nrfx_err_t err = NRFX_SUCCESS;
    
    
        // configure imu/ppi timer
        nrfx_timer_config_t timer_cfg_0 = NRFX_TIMER_DEFAULT_CONFIG;
        timer_cfg_0.mode = NRF_TIMER_MODE_LOW_POWER_COUNTER; //NRF_TIMER_MODE_COUNTER;
        //IRQ_DIRECT_CONNECT(TIMER1_IRQn, 0, nrfx_timer_1_irq_handler, 0);
    
        IRQ_CONNECT(DT_IRQN(DT_NODELABEL(timer1)), 
    		    DT_IRQ(DT_NODELABEL(timer1), priority),
    		    nrfx_isr, nrfx_timer_1_irq_handler, 0);
    
        if(!nrfx_timer_is_enabled(&m_imu_acq_cnt_timer)) {
            err = nrfx_timer_init(&m_imu_acq_cnt_timer,
                                        &timer_cfg_0,
                                        imu_ppi_timer_event_handler);    
            if (err != NRFX_SUCCESS) {
    		    LOG_ERR("nrf_drv_timer_init error: %08x", err);
    		    return;
    	    }                              
        }
    
        nrfx_timer_extended_compare(&m_imu_acq_cnt_timer,
                                       NRF_TIMER_CC_CHANNEL0,
                                       1 /*IMU_SPIM_TRANSFER_COUNT*/,
                                       NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK, 
                                       true);
    
        if(!nrfx_timer_is_enabled(&m_imu_acq_cnt_timer))
            nrfx_timer_enable(&m_imu_acq_cnt_timer);    
    }

    void configure_fram_ppi_timer()
    {
        nrfx_err_t err = NRFX_SUCCESS;
    
        IRQ_CONNECT(DT_IRQN(DT_NODELABEL(timer2)), 
    		    DT_IRQ(DT_NODELABEL(timer2), priority),
    		    nrfx_isr, nrfx_timer_2_irq_handler, 0);
    
        // the fram hibernate timer ~6ms
        nrfx_timer_config_t timer_cfg_1 = NRFX_TIMER_DEFAULT_CONFIG;
        timer_cfg_1.mode = NRF_TIMER_MODE_TIMER;
        timer_cfg_1.frequency = NRF_TIMER_FREQ_31250Hz;
        //timer_cfg_1.bit_width = NRF_TIMER_BIT_WIDTH_32;
    
        if(!nrfx_timer_is_enabled(&m_fram_hibernate_delay_timer)) {
            err = nrfx_timer_init(&m_fram_hibernate_delay_timer,
                                        &timer_cfg_1,
                                        fram_ppi_timer_event_handler);    
            if (err != NRFX_SUCCESS) {
    		    LOG_ERR("nrf_drv_timer_init error: %08x", err);
    		    return;
    	    }                              
        }
        uint32_t ticks = nrfx_timer_ms_to_ticks(&m_fram_hibernate_delay_timer, 8);
        nrfx_timer_extended_compare(&m_fram_hibernate_delay_timer,
                                       NRF_TIMER_CC_CHANNEL2,
                                       ticks,
                                       (NRF_TIMER_SHORT_COMPARE2_CLEAR_MASK | NRF_TIMER_SHORT_COMPARE2_STOP_MASK), 
                                       false);    
    
        nrfx_timer_clear(&m_fram_hibernate_delay_timer);
        //  if(!nrfx_timer_is_enabled(&m_fram_hibernate_delay_timer))
        //  {
        //     nrfx_timer_enable(&m_fram_hibernate_delay_timer);
        //     nrfx_timer_pause(&m_fram_hibernate_delay_timer);
        //     nrfx_timer_clear(&m_fram_hibernate_delay_timer);
        //  }
    
        IRQ_CONNECT(DT_IRQN(DT_NODELABEL(timer3)), 
    		    DT_IRQ(DT_NODELABEL(timer3), priority),
    		    nrfx_isr, nrfx_timer_3_irq_handler, 0);
    
        // configure fram spim start count ppi timer
        nrfx_timer_config_t timer_cfg_2 = NRFX_TIMER_DEFAULT_CONFIG;
        timer_cfg_2.mode = NRF_TIMER_MODE_LOW_POWER_COUNTER; //NRF_TIMER_MODE_COUNTER;
        if(!nrfx_timer_is_enabled(&m_fram_spim_start_cnt_timer)) {
            err = nrfx_timer_init(&m_fram_spim_start_cnt_timer,
                                        &timer_cfg_2,
                                        fram_spim_start_count_ppi_timer_event_handler);    
            if (err != NRFX_SUCCESS) {
    		    LOG_ERR("nrf_drv_timer_init error: %08x", err);
    		    return;
    	    }                              
        }
        nrfx_timer_compare(&m_fram_spim_start_cnt_timer,
                                       NRF_TIMER_CC_CHANNEL0,
                                       1 /*FRAM_SPIM_TRANSFER_COUNT*/, 
                                       true);
    
        nrfx_timer_compare(&m_fram_spim_start_cnt_timer,
                                       NRF_TIMER_CC_CHANNEL1,
                                       2 /*FRAM_SPIM_TRANSFER_COUNT*/, 
                                       true);
    
        nrfx_timer_compare(&m_fram_spim_start_cnt_timer,
                                       NRF_TIMER_CC_CHANNEL2,
                                       3 /*FRAM_SPIM_TRANSFER_COUNT*/, 
                                       true);
        nrfx_timer_extended_compare(&m_fram_spim_start_cnt_timer,
                                       NRF_TIMER_CC_CHANNEL3,
                                       4 /*FRAM_SPIM_TRANSFER_COUNT*/, 
                                       NRF_TIMER_SHORT_COMPARE3_CLEAR_MASK,
                                       true);                               
    
        if(!nrfx_timer_is_enabled(&m_fram_spim_start_cnt_timer))
            nrfx_timer_enable(&m_fram_spim_start_cnt_timer);  
    
        nrfx_timer_clear(&m_fram_spim_start_cnt_timer);
    
        IRQ_CONNECT(DT_IRQN(DT_NODELABEL(timer4)), 
    		    DT_IRQ(DT_NODELABEL(timer4), priority),
    		    nrfx_isr, nrfx_timer_4_irq_handler, 0);
    
        // configure fram spim end count ppi timer
        nrfx_timer_config_t timer_cfg_3 = NRFX_TIMER_DEFAULT_CONFIG;
        timer_cfg_3.mode = NRF_TIMER_MODE_LOW_POWER_COUNTER; //NRF_TIMER_MODE_COUNTER;
        if(!nrfx_timer_is_enabled(&m_fram_spim_end_cnt_timer)) {
            err = nrfx_timer_init(&m_fram_spim_end_cnt_timer,
                                        &timer_cfg_3,
                                        fram_spim_end_count_ppi_timer_event_handler);    
            if (err != NRFX_SUCCESS) {
    		    LOG_ERR("nrf_drv_timer_init error: %08x", err);
    		    return;
    	    }                              
        }
        // we start the 3rd FRAM write
        nrfx_timer_compare(&m_fram_spim_end_cnt_timer,
                                       NRF_TIMER_CC_CHANNEL0,
                                       2 /*SPIM END EVENT COUNT*/,  
                                       false);
        // we start the 4th FRAM write
        nrfx_timer_compare(&m_fram_spim_end_cnt_timer,
                                       NRF_TIMER_CC_CHANNEL1,
                                       3 /*SPIM END EVENT COUNT*/,
                                       false);
        // we want to clear the timer on the end of the 4th spim end 
         nrfx_timer_extended_compare(&m_fram_spim_end_cnt_timer,
                                       NRF_TIMER_CC_CHANNEL2,
                                       4 /*SPIM END EVENT COUNT*/,
                                       NRF_TIMER_SHORT_COMPARE2_CLEAR_MASK,  
                                       false);
                                 
        if(!nrfx_timer_is_enabled(&m_fram_spim_end_cnt_timer))
            nrfx_timer_enable(&m_fram_spim_end_cnt_timer);     
    
        nrfx_timer_clear(&m_fram_spim_end_cnt_timer); 
    
    }

    void fram_spim_start_count_ppi_timer_event_handler(nrf_timer_event_t event_type, void * p_context)
    {
        uint32_t timer_value = 0;
        uint8_t CMD_WRITE_ENABLE;
        uint8_t CMD_HIBERNATE;
    
        if(event_type == NRF_TIMER_EVENT_COMPARE0) // for 2nd fram write
        {
            timer_value = nrfx_timer_capture_get(&m_fram_spim_start_cnt_timer, NRF_TIMER_CC_CHANNEL0);
            CMD_WRITE_ENABLE = ENUM_TO_UINT8(FRAM_CMD_WRITE_ENABLE);
            spim1_fram.p_reg->TXD.PTR = (uint32_t)&CMD_WRITE_ENABLE;
            spim1_fram.p_reg->TXD.MAXCNT = 1;
            spim1_fram.p_reg->RXD.MAXCNT = 0; 
           // LOG_INF("Setup for 2nd fram write.........");
    
            //nrfx_timer_clear(&m_imu_acq_cnt_timer);
            // LOG_HEXDUMP_INF(IMU_Recv_ArrayList->buffer,364,"received FIFO Data");
        }
        else if(event_type == NRF_TIMER_EVENT_COMPARE1) // for 3rd fram write
        {
            timer_value = nrfx_timer_capture_get(&m_fram_spim_start_cnt_timer, NRF_TIMER_CC_CHANNEL1);
            IMU_RX_BUFFER[0] = ENUM_TO_UINT8(FRAM_CMD_WRITE_DATA);
            IMU_RX_BUFFER[1] = (m_current_fram_addr & 0x00FF0000) >> 16;
            IMU_RX_BUFFER[2] = (m_current_fram_addr & 0x0000FF00) >> 8;
            IMU_RX_BUFFER[3] = (m_current_fram_addr & 0x000000FF);
    
            m_current_fram_addr += ADL_MODE_BUFFER_IMU_RXD_SIZE;
    
            spim1_fram.p_reg->TXD.PTR = (uint32_t)&IMU_RX_BUFFER;
            spim1_fram.p_reg->TXD.MAXCNT = ADL_MODE_BUFFER_IMU_RXD_SIZE + 4;
            spim1_fram.p_reg->RXD.MAXCNT = 0;
           // LOG_INF("Setup for 3rd fram write.........");
        }
        else if(event_type == NRF_TIMER_EVENT_COMPARE2) // for 4th fram write
        {
            timer_value = nrfx_timer_capture_get(&m_fram_spim_start_cnt_timer, NRF_TIMER_CC_CHANNEL2);
            CMD_HIBERNATE = ENUM_TO_UINT8(FRAM_CMD_HIBERNATE);
            spim1_fram.p_reg->TXD.PTR = (uint32_t)&CMD_HIBERNATE;
            spim1_fram.p_reg->TXD.MAXCNT = 1;
            spim1_fram.p_reg->RXD.MAXCNT = 0; 
           // LOG_INF("Setup for 4th fram write.........");
        }
        else if(event_type == NRF_TIMER_EVENT_COMPARE3) // for 1st fram write
        {
            timer_value = nrfx_timer_capture_get(&m_fram_spim_start_cnt_timer, NRF_TIMER_CC_CHANNEL3);
          //  nrfx_timer_clear(&m_fram_spim_start_cnt_timer);
            spim1_fram.p_reg->TXD.PTR = (uint32_t)&FRAM_ADL_TX_ArrayList;
            spim1_fram.p_reg->TXD.MAXCNT = 4;
            spim1_fram.p_reg->RXD.MAXCNT = 0; 
            //LOG_INF("Setup for 1st fram write.........");
        }
        else
            LOG_INF("Unknown timer event...............");
    }
    void fram_spim_end_count_ppi_timer_event_handler(nrf_timer_event_t event_type, void * p_context)
    {
        if(event_type == NRF_TIMER_EVENT_COMPARE0) // the 3rd spim end trigger
        {
            LOG_INF("2nd spim end trigger.........");
        }
        else if(event_type == NRF_TIMER_EVENT_COMPARE1) // the 3rd spim end trigger
        {
            //nrfx_timer_clear(&m_fram_spim_end_cnt_timer);
            LOG_INF("3rd spim end trigger.........");
        }
        else
            LOG_INF("Undefind FRAM SPIM End Count Event Type.........");
    }

    void setup_ADL_mode_imu_ppi_spi_transfer(void)
    {
        nrfx_err_t err = NRFX_SUCCESS;
      
        // IMU SPI setup
        spim0_imu.p_reg->TXD.LIST = SPIM_TXD_LIST_LIST_ArrayList;
        spim0_imu.p_reg->RXD.LIST = SPIM_RXD_LIST_LIST_ArrayList;
        spim0_imu.p_reg->TXD.MAXCNT = ADL_MODE_BUFFER_IMU_TXD_SIZE;
        spim0_imu.p_reg->RXD.MAXCNT = ADL_MODE_BUFFER_IMU_RXD_SIZE; 
        nrfx_spim_xfer_desc_t imu_xfer = NRFX_SPIM_XFER_TRX((uint8_t*)IMU_ChannelSwitch_ArrayList,
                                                                            ADL_MODE_BUFFER_IMU_TXD_SIZE,
                                                                            (uint8_t*)&IMU_RX_BUFFER[4],
                                                                            ADL_MODE_BUFFER_IMU_RXD_SIZE);
    
        uint32_t flags = (NRFX_SPIM_FLAG_HOLD_XFER
                          |NRFX_SPIM_FLAG_TX_POSTINC
                          |NRFX_SPIM_FLAG_RX_POSTINC
                          |NRFX_SPIM_FLAG_NO_XFER_EVT_HANDLER
                          |NRFX_SPIM_FLAG_REPEATED_XFER);
                          
        err = nrfx_spim_xfer(&spim0_imu, &imu_xfer, flags);
        if (err != NRFX_SUCCESS) {
            LOG_INF("nrfx_spim_xfer error: %08x", err);
    		LOG_ERR("nrfx_spim_xfer error: %08x", err);
    		return;
    	}
    }
    
    void setup_ADL_mode_fram_ppi_spi_transfer(void)
    {
        nrfx_err_t err = NRFX_SUCCESS;
      
        uint32_t flags = (NRFX_SPIM_FLAG_HOLD_XFER
                          |NRFX_SPIM_FLAG_TX_POSTINC
                          |NRFX_SPIM_FLAG_RX_POSTINC
                          |NRFX_SPIM_FLAG_NO_XFER_EVT_HANDLER
                          |NRFX_SPIM_FLAG_REPEATED_XFER);
                          
        // FRAM SPI setup
        spim1_fram.p_reg->TXD.LIST = SPIM_TXD_LIST_LIST_ArrayList;
        spim1_fram.p_reg->RXD.LIST = SPIM_RXD_LIST_LIST_ArrayList;
        spim1_fram.p_reg->TXD.MAXCNT = 4;
        spim1_fram.p_reg->RXD.MAXCNT = 0; 
        nrfx_spim_xfer_desc_t fram_xfer = NRFX_SPIM_XFER_TRX((uint8_t*)FRAM_ADL_TX_ArrayList,
                                                                            4,
                                                                            NULL,
                                                                            0);                  
        err = nrfx_spim_xfer(&spim1_fram, &fram_xfer, flags);
        if (err != NRFX_SUCCESS) {
            LOG_INF("nrfx_spim_xfer error: %08x", err);
    		LOG_ERR("nrfx_spim_xfer error: %08x", err);
    		return;
    	}
    }

    void start_ADL_mode_acq()
    {
        //setup_imu_ppi_spi_transfer();
        setup_ADL_mode_imu_ppi_spi_transfer();
        setup_ADL_mode_fram_ppi_spi_transfer();
    	nrfx_ppi_group_enable(imu_trigger_group);
        
        // k_timer_stop(&m_start_imu_conv_timer_id);
        // k_timer_start(&m_start_imu_conv_timer_id, K_MSEC(1010), K_NO_WAIT);
        LOG_INF("started ADL Mode Acquisition...............");
    }
    
    void ADL_mode_ppi_init(void)
    {
        nrfx_err_t err = NRFX_SUCCESS;
    
        nrf_ppi_channel_t imu_int1_trigger_ppi_channel;
        nrf_ppi_channel_t imu_count_ppi_channel;
        nrf_ppi_channel_t imu_trigger_disable_channel;
        nrf_ppi_channel_t fram_spim_end_trigger_ppi_channel;
        nrf_ppi_channel_t fram_spim_start_trigger_ppi_channel;
        nrf_ppi_channel_t fram_hibernate_timer_ppi_channel;
        nrf_ppi_channel_t fram_spim_start_count_ppi_channel;
        nrf_ppi_channel_t fram_spim_end_count_ppi_channel;
    
        nrf_ppi_channel_t fram_1st_write_ppi_channel;
        nrf_ppi_channel_t fram_2nd_write_ppi_channel;
        nrf_ppi_channel_t fram_3rd_write_ppi_channel;
        nrf_ppi_channel_t fram_4th_write_ppi_channel;
    
        uint32_t imu_int1_trigger_pin_evt_addr;
        uint32_t imu_spim_start_task_addr;
        uint32_t imu_spim_end_evt_addr;
        uint32_t timer_count_task_addr;
        uint32_t timer_cc_event_addr;
        uint32_t group_imu_disable_task_addr;
        
        uint32_t imu_ss_pin_toggle_task_addr;
        uint32_t fram_timer_spim_start_count_task_addr;
        uint32_t fram_timer_spim_end_count_task_addr;
        uint32_t fram_timer_spim_start_cc1_event_addr;
        uint32_t fram_timer_spim_end_cc2_event_addr;
        uint32_t fram_timer_spim_end_cc3_event_addr;
       
        uint32_t fram_spim_start_task_addr;
        uint32_t fram_spim_end_evt_addr;
        uint32_t fram_spim_started_evt_addr;
        uint32_t fram_ss_pin_toggle_task_addr;
        // uint32_t group_fram_disable_task_addr;
    
        uint32_t fram_hibernate_timer_start_task_addr;
        uint32_t fram_hibernate_timer_cc_evt_addr;   
    
        err = nrfx_ppi_channel_alloc(&imu_int1_trigger_ppi_channel);
        if (err != NRFX_SUCCESS) {
    		LOG_ERR("nrfx_ppi_channel_alloc error: %08x", err);
    		return;
    	}
    
        // this ppi channel will toggle the fram spim cs at the end of the transaction to the fram
        err = nrfx_ppi_channel_alloc(&fram_spim_end_trigger_ppi_channel);
        if (err != NRFX_SUCCESS) {
    		LOG_ERR("nrfx_ppi_channel_alloc error: %08x", err);
    		return;
    	}
        
        err = nrfx_ppi_channel_alloc(&fram_spim_start_trigger_ppi_channel);
        if (err != NRFX_SUCCESS) {
    		LOG_ERR("nrfx_ppi_channel_alloc error: %08x", err);
    		return;
    	}
        
        err = nrfx_ppi_channel_alloc(&fram_hibernate_timer_ppi_channel);
        if (err != NRFX_SUCCESS) {
    		LOG_ERR("nrfx_ppi_channel_alloc error: %08x", err);
    		return;
    	}
        err = nrfx_ppi_channel_alloc(&imu_count_ppi_channel);
        if (err != NRFX_SUCCESS) {
    		LOG_ERR("nrfx_ppi_channel_alloc error: %08x", err);
    		return;
    	}  
        err = nrfx_ppi_channel_alloc(&fram_spim_start_count_ppi_channel);
        if (err != NRFX_SUCCESS) {
    		LOG_ERR("nrfx_ppi_channel_alloc error: %08x", err);
    		return;
    	}
        err = nrfx_ppi_channel_alloc(&fram_spim_end_count_ppi_channel);
        if (err != NRFX_SUCCESS) {
    		LOG_ERR("nrfx_ppi_channel_alloc error: %08x", err);
    		return;
    	}
        err = nrfx_ppi_channel_alloc(&fram_1st_write_ppi_channel);
        if (err != NRFX_SUCCESS) {
    		LOG_ERR("nrfx_ppi_channel_alloc error: %08x", err);
    		return;
    	}
        err = nrfx_ppi_channel_alloc(&fram_2nd_write_ppi_channel);
        if (err != NRFX_SUCCESS) {
    		LOG_ERR("nrfx_ppi_channel_alloc error: %08x", err);
    		return;
    	}
        err = nrfx_ppi_channel_alloc(&fram_3rd_write_ppi_channel);
        if (err != NRFX_SUCCESS) {
    		LOG_ERR("nrfx_ppi_channel_alloc error: %08x", err);
    		return;
    	}
        err = nrfx_ppi_channel_alloc(&fram_4th_write_ppi_channel);
        if (err != NRFX_SUCCESS) {
    		LOG_ERR("nrfx_ppi_channel_alloc error: %08x", err);
    		return;
    	}
        err = nrfx_ppi_channel_alloc(&imu_trigger_disable_channel);
        if (err != NRFX_SUCCESS) {
    		LOG_ERR("nrfx_ppi_channel_alloc error: %08x", err);
    		return;
    	}
    
        err = nrfx_ppi_group_alloc(&imu_trigger_group);
        if (err != NRFX_SUCCESS) {
    		LOG_ERR("nrfx_ppi_group_alloc error: %08x", err);
    		return;
    	}
    
        imu_int1_trigger_pin_evt_addr   = nrfx_gpiote_in_event_addr_get(IMU_INT1_PIN);
        imu_spim_start_task_addr        = nrf_spim_task_address_get(spim0_imu.p_reg, NRF_SPIM_TASK_START);
        imu_spim_end_evt_addr           = nrf_spim_event_address_get(spim0_imu.p_reg, NRF_SPIM_EVENT_END);
        timer_count_task_addr       = nrfx_timer_task_address_get(&m_imu_acq_cnt_timer, NRF_TIMER_TASK_COUNT);
        timer_cc_event_addr         = nrfx_timer_compare_event_address_get(&m_imu_acq_cnt_timer, NRF_TIMER_CC_CHANNEL0);
        // group_disable_task_addr = (uint32_t) nrf_ppi_task_group_disable_address_get(trigger_group);
        group_imu_disable_task_addr = (uint32_t) nrfx_ppi_task_addr_group_disable_get(imu_trigger_group);
        
        fram_spim_start_task_addr    = nrf_spim_task_address_get(spim1_fram.p_reg, NRF_SPIM_TASK_START); 
        fram_spim_end_evt_addr       = nrf_spim_event_address_get(spim1_fram.p_reg, NRF_SPIM_EVENT_END);
        fram_spim_started_evt_addr   = nrf_spim_event_address_get(spim1_fram.p_reg, NRF_SPIM_EVENT_STARTED);
     //   group_fram_disable_task_addr = (uint32_t) nrfx_ppi_task_addr_group_disable_get(fram_trigger_group);
        
        fram_hibernate_timer_start_task_addr = nrfx_timer_task_address_get(&m_fram_hibernate_delay_timer, NRF_TIMER_TASK_START);
        fram_hibernate_timer_cc_evt_addr     = nrfx_timer_compare_event_address_get(&m_fram_hibernate_delay_timer, NRF_TIMER_CC_CHANNEL2);
    
        fram_timer_spim_start_count_task_addr = nrfx_timer_task_address_get(&m_fram_spim_start_cnt_timer, NRF_TIMER_TASK_COUNT);
        fram_timer_spim_end_count_task_addr = nrfx_timer_task_address_get(&m_fram_spim_end_cnt_timer, NRF_TIMER_TASK_COUNT);
    
        //fram_timer_spim_start_cc1_event_addr         = nrfx_timer_compare_event_address_get(&m_fram_spim_start_cnt_timer, NRF_TIMER_CC_CHANNEL0);
        fram_timer_spim_end_cc2_event_addr         = nrfx_timer_compare_event_address_get(&m_fram_spim_end_cnt_timer, NRF_TIMER_CC_CHANNEL0);
        fram_timer_spim_end_cc3_event_addr         = nrfx_timer_compare_event_address_get(&m_fram_spim_end_cnt_timer, NRF_TIMER_CC_CHANNEL1);
    
        // IMU SS
        // The SS pin will be driven by a GPIOTE task.
        // have the ppi spim start/end event control the slave select       
        nrfx_gpiote_out_config_t imu_ss_pin_config = NRFX_GPIOTE_CONFIG_OUT_TASK_TOGGLE(true);
        err = nrfx_gpiote_out_init(IMU_CS_PIN, &imu_ss_pin_config);
        if (err != NRFX_SUCCESS) {
    		LOG_ERR("nrfx_gpiote_out_init error: %08x", err);
    		return;
    	}
        imu_ss_pin_toggle_task_addr = nrfx_gpiote_out_task_addr_get(IMU_CS_PIN);
    
        // FRAM SS
        // The SS pin will be driven by a GPIOTE task.
        // have the ppi spim start/end event control the slave select   
        nrfx_gpiote_out_config_t fram_ss_pin_config = NRFX_GPIOTE_CONFIG_OUT_TASK_TOGGLE(true);
        err = nrfx_gpiote_out_init(FRAM_CS_PIN, &fram_ss_pin_config);
        if (err != NRFX_SUCCESS) {
    		LOG_ERR("nrfx_gpiote_out_init error: %08x", err);
    		return;
    	}
        fram_ss_pin_toggle_task_addr = nrfx_gpiote_out_task_addr_get(FRAM_CS_PIN);
    
        // this channel will trigger the imu spim task off the imu int1 pin event 
        err = nrfx_ppi_channel_assign(imu_int1_trigger_ppi_channel,
                                              imu_int1_trigger_pin_evt_addr,
                                              imu_spim_start_task_addr);
        if (err != NRFX_SUCCESS) {
    		LOG_ERR("nrfx_ppi_channel_assign error: %08x", err);
    		return;
    	}
    
        // fork the imu ss pin off of the start(to assert) of imu spim channel
        err = nrfx_ppi_channel_fork_assign(imu_int1_trigger_ppi_channel, imu_ss_pin_toggle_task_addr);
        if (err != NRFX_SUCCESS) {
    		LOG_ERR("nrfx_ppi_channel_fork_assign error: %08x", err);
    		return;
    	}
    
        err = nrfx_ppi_channel_assign(imu_count_ppi_channel,
                                              imu_spim_end_evt_addr,
                                              timer_count_task_addr);
        if (err != NRFX_SUCCESS) {
    		LOG_ERR("nrfx_ppi_channel_assign error: %08x", err);
    		return;
    	}
        // fork the imu ss pin off of the end of imu spim channel(to de-assert))
        err = nrfx_ppi_channel_fork_assign(imu_count_ppi_channel, imu_ss_pin_toggle_task_addr);
        if (err != NRFX_SUCCESS) {
    		LOG_ERR("nrfx_ppi_channel_fork_assign error: %08x", err);
    		return;
    	}
     ////////   
        // first FRAM write. dummy read instruction. toggle ss pin, start spi, toggle ss pin  
        err = nrfx_ppi_channel_assign(fram_1st_write_ppi_channel,
                                              imu_spim_end_evt_addr,
                                              fram_spim_start_task_addr);
        if (err != NRFX_SUCCESS) {
    		LOG_ERR("nrfx_ppi_channel_assign error: %08x", err);
    		return;
    	}
        err = nrfx_ppi_channel_assign(fram_spim_start_trigger_ppi_channel,
                                              fram_spim_started_evt_addr,
                                              fram_ss_pin_toggle_task_addr);
        if (err != NRFX_SUCCESS) {
    		LOG_ERR("nrfx_ppi_channel_assign error: %08x", err);
    		return;
    	}
        err = nrfx_ppi_channel_assign(fram_spim_end_trigger_ppi_channel,
                                              fram_spim_end_evt_addr,
                                              fram_ss_pin_toggle_task_addr);
        if (err != NRFX_SUCCESS) {
    		LOG_ERR("nrfx_ppi_channel_assign error: %08x", err);
    		return;
    	}
        
        // count the FRAM SPI writes off of the SPI start
        err = nrfx_ppi_channel_assign(fram_spim_start_count_ppi_channel,
                                              fram_spim_started_evt_addr,
                                              fram_timer_spim_start_count_task_addr);
        if (err != NRFX_SUCCESS) {
    		LOG_ERR("nrfx_ppi_channel_assign error: %08x", err);
    		return;
    	} 
        err = nrfx_ppi_channel_assign(fram_spim_end_count_ppi_channel,
                                              fram_spim_end_evt_addr,
                                              fram_timer_spim_end_count_task_addr);
        if (err != NRFX_SUCCESS) {
    		LOG_ERR("nrfx_ppi_channel_assign error: %08x", err);
    		return;
    	}
       
        // start the FRAM hibernate timer off of the IMU SPI end Event
        err = nrfx_ppi_channel_assign(fram_hibernate_timer_ppi_channel,
                                              imu_spim_end_evt_addr,
                                              fram_hibernate_timer_start_task_addr);
        if (err != NRFX_SUCCESS) {
    		LOG_ERR("nrfx_ppi_channel_assign error: %08x", err);
    		return;
    	}
        // now we want to start the 2nd, 3rd and 4th FRAM SPI transactions
        // we start the 2nd off of the end of te hibernate timer
        err = nrfx_ppi_channel_assign(fram_2nd_write_ppi_channel,
                                              fram_hibernate_timer_cc_evt_addr,
                                              fram_spim_start_task_addr);
        if (err != NRFX_SUCCESS) {
    		LOG_ERR("nrfx_ppi_channel_assign error: %08x", err);
    		return;
    	}
        err = nrfx_ppi_channel_assign(fram_3rd_write_ppi_channel,
                                              fram_timer_spim_end_cc2_event_addr,
                                              fram_spim_start_task_addr);
        if (err != NRFX_SUCCESS) {
    		LOG_ERR("nrfx_ppi_channel_assign error: %08x", err);
    		return;
    	}
        err = nrfx_ppi_channel_assign(fram_4th_write_ppi_channel,
                                              fram_timer_spim_end_cc3_event_addr,
                                              fram_spim_start_task_addr);
        if (err != NRFX_SUCCESS) {
    		LOG_ERR("nrfx_ppi_channel_assign error: %08x", err);
    		return;
    	}
    
        err = nrfx_ppi_channel_enable(fram_spim_start_trigger_ppi_channel);
        if (err != NRFX_SUCCESS) {
    		LOG_ERR("nrfx_ppi_channel_enable error: %08x", err);
    		return;
    	}
        err = nrfx_ppi_channel_enable(fram_spim_end_trigger_ppi_channel);
        if (err != NRFX_SUCCESS) {
    		LOG_ERR("nrfx_ppi_channel_enable error: %08x", err);
    		return;
    	}
        err = nrfx_ppi_channel_enable(imu_count_ppi_channel);
        if (err != NRFX_SUCCESS) {
    		LOG_ERR("nrfx_ppi_channel_enable error: %08x", err);
    		return;
    	}
        err = nrfx_ppi_channel_enable(fram_spim_start_count_ppi_channel);
        if (err != NRFX_SUCCESS) {
    		LOG_ERR("nrfx_ppi_channel_enable error: %08x", err);
    		return;
    	}
        err = nrfx_ppi_channel_enable(fram_spim_end_count_ppi_channel);
        if (err != NRFX_SUCCESS) {
    		LOG_ERR("nrfx_ppi_channel_enable error: %08x", err);
    		return;
    	}
        err = nrfx_ppi_channel_enable(fram_1st_write_ppi_channel);
        if (err != NRFX_SUCCESS) {
    		LOG_ERR("nrfx_ppi_channel_enable error: %08x", err);
    		return;
    	}
        err = nrfx_ppi_channel_enable(fram_2nd_write_ppi_channel);
        if (err != NRFX_SUCCESS) {
    		LOG_ERR("nrfx_ppi_channel_enable error: %08x", err);
    		return;
    	}
        err = nrfx_ppi_channel_enable(fram_3rd_write_ppi_channel);
        if (err != NRFX_SUCCESS) {
    		LOG_ERR("nrfx_ppi_channel_enable error: %08x", err);
    		return;
    	}
         err = nrfx_ppi_channel_enable(fram_4th_write_ppi_channel);
        if (err != NRFX_SUCCESS) {
    		LOG_ERR("nrfx_ppi_channel_enable error: %08x", err);
    		return;
    	}
        
        err = nrfx_ppi_channel_enable(fram_hibernate_timer_ppi_channel);
        if (err != NRFX_SUCCESS) {
    		LOG_ERR("nrfx_ppi_channel_enable error: %08x", err);
    		return;
    	}
     
        err = nrfx_ppi_channel_assign(imu_trigger_disable_channel,
                                              timer_cc_event_addr,
                                              group_imu_disable_task_addr);
        if (err != NRFX_SUCCESS) {
    		LOG_ERR("nrfx_ppi_channel_assign error: %08x", err);
    		return;
    	}
        // err = nrfx_ppi_channel_assign(fram_trigger_disable_channel,
        //                                       timer_fram_cc_event_addr,
        //                                       group_fram_disable_task_addr);
        // if (err != NRFX_SUCCESS) {
    	// 	LOG_ERR("nrfx_ppi_channel_assign error: %08x", err);
    	// 	return;
    	// }
    
      
    //    err_code = nrfx_ppi_channel_enable(trigger_ppi_channel);
    //    APP_ERROR_CHECK(err_code);
     
    //     err = nrfx_ppi_channel_enable(imu_trigger_disable_channel);
    //     if (err != NRFX_SUCCESS) {
    // 		LOG_ERR("nrfx_ppi_channel_enable error: %08x", err);
    // 		return;
    // 	}
        
        // disable for testing
        // err = nrfx_ppi_channel_enable(fram_trigger_disable_channel);
        // if (err != NRFX_SUCCESS) {
    	// 	LOG_ERR("nrfx_ppi_channel_enable error: %08x", err);
    	// 	return;
    	// }
    
        nrfx_ppi_channel_include_in_group(imu_int1_trigger_ppi_channel, imu_trigger_group);
        // nrfx_ppi_channel_include_in_group(fram_spim_trigger_ppi_channel, fram_trigger_group);
        // nrfx_ppi_channel_include_in_group(fram_spim_end_trigger_ppi_channel, fram_trigger_group);
        
    //    nrf_ppi_group_enable(trigger_group);
    
        nrfx_gpiote_out_task_enable(IMU_CS_PIN);  
        nrfx_gpiote_out_task_enable(FRAM_CS_PIN); 
    }

  • Hi Wael,

    Sorry, I thought you were using the nRF5340 for some reason. A current draw in the 5-600 uA range on the nRF52 series usually indicates that a peripheral keep requesting the 16 MHz clock. For instance, a running TIMER instance. However, this should have led to a more constant draw, not like the waveform shown in your screenshot.

    The DMA current is closer to 2 mA with VDD @ 1.8 v. But as you said, this current should only be seen during transmissions when the CPU is idle.   

    Either way, to try narrow down the problem, could try to issue the TIMER SHUTDOWN tasks for your timers after the transaction is complete by calling nrfx_timer_disable(). Also, is it possible to power off the IMU and FRAM IC (make sure you do not have any floating inputs if you do this)?  

    Best regards,

    Vidar

Related