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

extra current in idle ~450 uA NRF52832

Hi all

I'm trying to build a generator based on NRF52832. Outpit signals are: 8MHz clock and two latches signals highly sinchronized with clock - RGB_LAT and TXT_LAT. For this task I used TIMER1, PPI and GPIOTE. Actually my approach is working as expected. But the problem is high current consumption - additional 450 uA in CPU idle mode. I simplified my code for PCA10040 and checked the current to elliminate my PCB from posible reasons for extra power consumption. Also I found ERRATA # 98 "Static 400 μA while while using GPIOTE" seems to be very close to my case. In my code below you can see the setting of the named peripherals. DspPowerOn () - enables the signals output and DspPowerOff () disables it. You can sence extra current 450 uA still present on measurment port of PCA10040 after DspPowerOff () executed. In my code NRF_GPIOTE-> TASKS_OUT [2] is triggered by two PPI channels but not simultaneously and both directions is low-to-high. Also I noticed that extra current apears only if NRF_GPIOTE-> TASKS_CLR [2] executed at any time after DspPowerOn (). #define EXPOSE_BUG can reveal that. So my question is it realy chip bug or I missed something?

#include <stdbool.h>
#include <stdint.h>
#include "nrf.h"
#include "nrf_timer.h"
#include "nrf_drv_common.h"
#include "app_util_platform.h"
#include "nrf_delay.h"

#define RGB_LAT_LOCK()				NRF_GPIOTE->TASKS_SET[1] = 1
#define TXT_LAT_LOCK()				NRF_GPIOTE->TASKS_SET[2] = 1

#define EXPOSE_BUG	// define this one to see extra 430 uA

#ifdef EXPOSE_BUG
	#define RGB_LAT_RELEASE()			NRF_GPIOTE->TASKS_CLR[1] = 1
	#define TXT_LAT_RELEASE()			NRF_GPIOTE->TASKS_CLR[2] = 1
#else
	#define RGB_LAT_RELEASE()
	#define TXT_LAT_RELEASE()
#endif

#define Board_TXT_LAT		                14
#define Board_RGB_GCK                       23
#define Board_RGB_LAT   	                20

void TIMER2_IRQHandler(void)
{
	if (nrf_timer_event_check(NRF_TIMER2, NRF_TIMER_EVENT_COMPARE0))
	{	// RGB_LAT has been rised just now
		nrf_timer_event_clear(NRF_TIMER2, NRF_TIMER_EVENT_COMPARE0);
		RGB_LAT_RELEASE();
		TXT_LAT_RELEASE();
	}
	if (nrf_timer_event_check(NRF_TIMER2, NRF_TIMER_EVENT_COMPARE1))
	{	// TXT_LAT has been rised just now
		nrf_timer_event_clear(NRF_TIMER2, NRF_TIMER_EVENT_COMPARE1);
		TXT_LAT_RELEASE();
	}
}

void DspPowerOn(void)
{
	// Configure timer1
	NRF_TIMER1->PRESCALER = 0;
	NRF_TIMER1->CC[0] = 1;  // 8 MHz.
	NRF_TIMER1->SHORTS = (TIMER_SHORTS_COMPARE0_CLEAR_Enabled << TIMER_SHORTS_COMPARE0_CLEAR_Pos); 
	NRF_TIMER1->TASKS_START = 1;	// start GCK
	// timer2 is engaged with timer1(GCK) through the PPI
	NRF_TIMER2->PRESCALER = 0;
	NRF_TIMER2->CC[0] = 2*4096; // RGB_LAT timing
	NRF_TIMER2->CC[1] = 4096;  // TXT_LAT timing
	NRF_TIMER2->MODE = TIMER_MODE_MODE_Counter << TIMER_MODE_MODE_Pos;
	NRF_TIMER2->BITMODE = TIMER_BITMODE_BITMODE_24Bit << TIMER_BITMODE_BITMODE_Pos;
	NRF_TIMER2->SHORTS = (TIMER_SHORTS_COMPARE0_CLEAR_Enabled << TIMER_SHORTS_COMPARE0_CLEAR_Pos);
	nrf_timer_event_clear(NRF_TIMER2, NRF_TIMER_EVENT_COMPARE0);
	nrf_timer_event_clear(NRF_TIMER2, NRF_TIMER_EVENT_COMPARE1);
	nrf_timer_int_enable(NRF_TIMER2, nrf_timer_compare_int_get(0)|nrf_timer_compare_int_get(1));
	NRF_TIMER2->TASKS_START = 1;	// start LAT
}

void DspPowerOff(void)
{
	//TIMER_TASKS_SHUTDOWN triggered to reduce power consumption in sleep while DSP is off
	NRF_TIMER2->TASKS_SHUTDOWN = 1;		// stop synchronous LAT
	NRF_TIMER1->TASKS_SHUTDOWN = 1;		// stop GCK
}

int main(void)
{
	// configure GPIOTE to get GCK (8 MHz) out of chip
	NRF_GPIOTE->CONFIG[0] = 
		GPIOTE_CONFIG_POLARITY_Toggle << GPIOTE_CONFIG_POLARITY_Pos |
		Board_RGB_GCK << GPIOTE_CONFIG_PSEL_Pos |
		GPIOTE_CONFIG_OUTINIT_Low << GPIOTE_CONFIG_OUTINIT_Pos |
		GPIOTE_CONFIG_MODE_Task << GPIOTE_CONFIG_MODE_Pos;

	// configure GPIOTE to get RGB_LAT to be synchronous with GCK 
	NRF_GPIOTE->CONFIG[1] = 
		GPIOTE_CONFIG_POLARITY_LoToHi << GPIOTE_CONFIG_POLARITY_Pos |
		Board_RGB_LAT << GPIOTE_CONFIG_PSEL_Pos |
		GPIOTE_CONFIG_OUTINIT_Low << GPIOTE_CONFIG_OUTINIT_Pos |
		GPIOTE_CONFIG_MODE_Task << GPIOTE_CONFIG_MODE_Pos;
	
	// configure GPIOTE to get TXT_LAT to be synchronous with GCK 
	NRF_GPIOTE->CONFIG[2] = 
		GPIOTE_CONFIG_POLARITY_LoToHi << GPIOTE_CONFIG_POLARITY_Pos |
		Board_TXT_LAT << GPIOTE_CONFIG_PSEL_Pos |
		GPIOTE_CONFIG_OUTINIT_Low << GPIOTE_CONFIG_OUTINIT_Pos |
		GPIOTE_CONFIG_MODE_Task << GPIOTE_CONFIG_MODE_Pos;
	
	//Configure PPI
	NRF_PPI->CH[0].EEP = (uint32_t) &NRF_TIMER1->EVENTS_COMPARE[0];
	NRF_PPI->CH[0].TEP = (uint32_t) &NRF_GPIOTE->TASKS_OUT[0];	// GCK pin out
	NRF_PPI->FORK[0].TEP = (uint32_t) &NRF_TIMER2->TASKS_COUNT;	// synchronous timer2 count
	
	NRF_PPI->CH[1].EEP = (uint32_t) &NRF_TIMER2->EVENTS_COMPARE[0];	// T2.CC0 - RGB_LAT timing
	NRF_PPI->CH[1].TEP = (uint32_t) &NRF_GPIOTE->TASKS_OUT[1];	// RGB_LAT pin out
	NRF_PPI->FORK[1].TEP = (uint32_t) &NRF_GPIOTE->TASKS_OUT[2]; // TXT_LAT pin out
	
	NRF_PPI->CH[2].EEP = (uint32_t) &NRF_TIMER2->EVENTS_COMPARE[1]; // T2.CC1 - RGB_TXT timing
	NRF_PPI->CH[2].TEP = (uint32_t) &NRF_GPIOTE->TASKS_OUT[2];	// TXT_LAT pin out
	
	NRF_PPI->CHENSET = 	(PPI_CHENSET_CH0_Enabled << PPI_CHENSET_CH0_Pos) + 
						(PPI_CHENSET_CH1_Enabled << PPI_CHENSET_CH1_Pos) +
						(PPI_CHENSET_CH2_Enabled << PPI_CHENSET_CH2_Pos);
	// enable timer irq	
	nrf_timer_event_clear(NRF_TIMER2, nrf_timer_compare_event_get(0));
	nrf_timer_event_clear(NRF_TIMER2, nrf_timer_compare_event_get(1));
	nrf_drv_common_irq_enable(TIMER2_IRQn, APP_IRQ_PRIORITY_LOW);

	DspPowerOn();
	
	nrf_delay_ms(10);
	
	DspPowerOff();
	
    while (1) __WFI();
}

/** @} */
Related