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

Clock control in RTC interrupt

Hi all!

I am developing an nRF52 application that uses RTC interrupt to measure an ADC value every 100 ms. Depending on the measured value the chip shall either go back to sleep or execute an algorithm. We are in the beginning of the project and one of the first tasks is to evaluate if we can get the power consumption low enough. Currently I am just running the RTC interrupt every 100 ms and then go back to sleep. The current is measured with a Keysight power analyzer and the execution time for the interrupt is measured by toggling a GPIO connected to an oscilloscope. My intention was to just use the internal 32 kHz RC oscillator during the interrupt. The RTC timing measurement however indicates that the interrupt is executed in 2.9 us which makes me suspect that it runs on 64 MHz. Calling nrf_drv_clock_hfclk_is_running() however return false. During this there is a max peak current of 7.2 mA. Just to execute the interrupt without even starting the SAADC uses around 170 nC which is too much for our needs. Calling nrf_drv_clock_hfclk_is_running() however return false. Anyone that can explain what is happening? Also see code pasted below.

static void rtc_handler(nrf_drv_rtc_int_type_t int_type) { uint32_t err_code;

if (nrf_drv_clock_hfclk_is_running())
{
    nrf_gpio_pin_set(ARDUINO_0_PIN);
}
else
{
    nrf_gpio_pin_set(ARDUINO_1_PIN);
}

if (int_type == NRF_DRV_RTC_INT_COMPARE0)
{
    err_code = nrf_drv_rtc_cc_set(&rtc,0,RTC_CC_VALUE,true);
    APP_ERROR_CHECK(err_code);
    nrf_drv_rtc_counter_clear(&rtc);
}
nrf_gpio_pin_clear(ARDUINO_0_PIN);
nrf_gpio_pin_clear(ARDUINO_1_PIN);

}

static void rtc_config(void) { uint32_t err_code;

//Initialize RTC instance
nrf_drv_rtc_config_t rtc_config;
rtc_config.prescaler = RTC_FREQ_TO_PRESCALER(10);
err_code = nrf_drv_rtc_init(&rtc, &rtc_config, rtc_handler);
APP_ERROR_CHECK(err_code);

err_code = nrf_drv_rtc_cc_set(&rtc,0,1,true);
APP_ERROR_CHECK(err_code);

//Power on RTC instance
nrf_drv_rtc_enable(&rtc);

}

int main(void) { lfclk_config();

nrf_gpio_cfg_output(ARDUINO_0_PIN);
nrf_gpio_cfg_output(ARDUINO_1_PIN);

rtc_config();

while (true)
{
    __WFE();
    __SEV();
    __WFE();

}

}

Thanks in advance, Mattias

  • Hi Mattias

    The CPU in the nRF52 can only run from the 64MHz clock source, it is not possible to run code at any lower speeds. The reason for this is that the overall efficiency is usually improved by simply running the code quickly and going back to sleep.

    The call to nrf_drv_clock_hfclk_is_running() will simply check if the external 32MHz clock is running. If this returns false it means the CPU is running off of the internal 64MHz RC oscillator.

    One tip to reduce the active current is to enable the DCDC regulator, assuming you have the necessary components in place (if you are using a DK then the DCDC is available).

    Best regards
    Torbjørn

  • Thanks Torbjørn,

    your answer together with some more reading made things much clearer for me. I tried switching on DCDC regulator and peak current decreased from 7.2 mA to 4.5 mA which maps better to the figures in "7.2.1 CPU performance in product specification". I am using the PCA10040 DK board so DCDC regulator is available. From there it is also very clear that CPU clock speed always is 64 MHz.

    Do you see any other approach to decrease power consumption in our application?

    What we want to do is:

    1. wake up every 10 ms
    2. measure a voltage level 3a go back to sleep if voltage is above limit value 3b execute an algorithm if level is below limit value

    3a is the normal case and the major part of power consumption. Could I for example use RTC to start AD conversion via PPI and only start CPU if measured value is above the limit? Or use COMP/LPCOMP?

    BR Mattias

  • Hi Mattias

    Yes, you should be able to trigger the ADC directly from the RTC by using a PPI connection. The SAADC module can be configured to generate an interrupt when the input is either higher or lower than a certain value, and this interrupt can be used as a wakeup source.

    Best regards
    Torbjørn

Related