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

nrf52840 RTC vs app_timer plus timestamping

hello Nordic

i am working with nrf52840, sdk16, over the peripheral app_ble_blinky example

my system will go to sleep mode for 10 minutes each time, i wonder if there is any advantage to use RTC directly instead of app_timer in meters of power consumption, is there less cpu interventions or over head when using RTC directly ?

also if i have some gpio interrupt during the 10 min sleep then i want to be able to read the current clock at resolution of 100ms. 

first thought was to use an app_timer that counts in 100ms intervals but that seems wasteful, i think i should seek for a way to have one timer interrupt every 10 minutes but ne able to get the current time stamp from the clock maybe.

1. is there a way to read a clock value while in sleep mode, that has some meaning, does it start from '0' every time we put the power on so we can try to calculate the delta each time ? 

2. is there a way to have an app_timer running on REPEATED mode that wakes up every 10 minutes ? does it really save something or it ticks every 32khz anyway? and is it better to do it directly with RTC ?

not so relevant but what's the difference between WFI and WFE beside the Event/Interrupt, does it refer to the type of sleep mode - system ON sleep(for WFE) vs system OFF sleep (for WFI)?

hope to read from you soon

best regards

Ziv

  • Hi,

    my system will go to sleep mode for 10 minutes each time, i wonder if there is any advantage to use RTC directly instead of app_timer in meters of power consumption, is there less cpu interventions or over head when using RTC directly ?

    App_timer has a few additional interrupts that trigger on at specific events (overflow, compare1 at half of max count), to handle internal flow. When using RTC directly, you can configure it for your exact needs, to avoid these interrupts. Depending on the configuration, these events should not have a very big impact on the average current consumption.

    1. is there a way to read a clock value while in sleep mode, that has some meaning, does it start from '0' every time we put the power on so we can try to calculate the delta each time ? 

    Not sure exactly how you intend to read the clock value while you are in sleep mode, but if you mean before and after sleep, you can use the app_timer_cnt_get() and app_timer_cnt_diff_compute() functions. These functions will simply get the count register from the RTC and compute the difference between them, but if you configure APP_TIMER_CONFIG_RTC_FREQUENCY to allow the RTC to not overflow more than once during the longest expected sleep cycle, this should work. If you want to translate this to actual time in your application, you need to store the counts, or use a similar approach to the nRF5 Calendar Example.

    2. is there a way to have an app_timer running on REPEATED mode that wakes up every 10 minutes ? does it really save something or it ticks every 32khz anyway? and is it better to do it directly with RTC ?

    App_timer uses compare events to wakeup when the next timer expires, it does not wake every 32 kHz to "tick". The frequency is also configurable, allowing for longer timers, as described above.

    not so relevant but what's the difference between WFI and WFE beside the Event/Interrupt, does it refer to the type of sleep mode - system ON sleep(for WFE) vs system OFF sleep (for WFI)?

    Both uses System On idle mode. The chip can only wake from System OFF from a limited set of peripheral signals (see System OFF mode), and wakeup will cause a chip reset. See this post for more details on WFE/WFI.

    Best regards,
    Jørgen

  • hi Jorgen

    thanks for your reply

    Not sure exactly how you intend to read the clock value while you are in sleep mode

    i mean that while i am in sleep mode there can be an event that wakes up the system, not by the timer, and i may want to know how much time has passed in the 0-2 last hours (i wake up every 10 min for small sampling and every 2 hours 10*12 for bigger operation)  

    just few more clarifications on that matter: 

    1. if i use the APP_TIMER_CONFIG_RTC_FREQUENCY, to change pre scaling if i understand correct, would it affect other app_timer instances that i have in my program ? 

    2. the APP_TIMER_CONFIG_RTC_FREQUENCY to 1024 (minimum) but, with RTC, if i get this right,

    in the "sdk_config.h": "NRFX_RTC_DEFAULT_CONFIG_FREQUENCY - Frequency  <16-32768> "

    i can get down to 16 tick per second, am i right ?

    3. if i want to use the RTC directly, is there an example in the sdk for using the RTC directly, and if i have softdevice, timer (HFCLK), SPI(at 8MHz), TWI (not sure if the serials clock matter) and one instance of app_timer in my program, can i use only the RTC2 for this 10min sleep ?

    hope to read from you soon

    best regards

    Ziv

  • ziv123 said:
    1. if i use the APP_TIMER_CONFIG_RTC_FREQUENCY, to change pre scaling if i understand correct, would it affect other app_timer instances that i have in my program ? 

    Yes, this will change the PRESCALER configuration of the RTC used by app_timer, and will affect all created timers.

    ziv123 said:

    2. the APP_TIMER_CONFIG_RTC_FREQUENCY to 1024 (minimum) but, with RTC, if i get this right,

    in the "sdk_config.h": "NRFX_RTC_DEFAULT_CONFIG_FREQUENCY - Frequency  <16-32768> "

    i can get down to 16 tick per second, am i right ?

    Theoretically, you should be able to set the config lower for app_timer as well, but it may affect other uses of app_timer, and may not be testet properly. I just tested by setting it to 4095 in the ble_app_hrs application, and the only issue I saw so far was that the default detection delay for buttons used by the BSP library is too low. After increasing this 100 times, the ble_app_hrs runs as normal.

    ziv123 said:
    3. if i want to use the RTC directly, is there an example in the sdk for using the RTC directly, and if i have softdevice, timer (HFCLK), SPI(at 8MHz), TWI (not sure if the serials clock matter) and one instance of app_timer in my program, can i use only the RTC2 for this 10min sleep ?

     See the Real Time Counter Example. Softdevice uses RTC0 and app_timer uses RTC1 by default, so RTC2 should be fine to use for this purpose.

  • 3. if i want to use the RTC directly, is there an example in the sdk for using the RTC directly, and if i have softdevice, timer (HFCLK), SPI(at 8MHz), TWI (not sure if the serials clock matter) and one instance of app_timer in my program, can i use only the RTC2 for this 10min sleep ?

    Here is a more advanced direct implementation of the RTC which allow you to do what you need. https://github.com/IOsonata/IOsonata/blob/master/ARM/Nordic/src/timer_lf_nrfx.cpp

    usage example : github.com/.../TimerDemo.cpp

    RTC0 & RTC1 are used by Softdevice & SDK. Only RTC2 is available for custom App.

  • hi Jorgen

    i looked at the rtc example, stange thing though

    when running the rtc example (SDK 16) for nrf542840, when changing the 

     config.prescaler = 32767; //15; //8191; // 32767; //4095;

    from 4095 to 32767, i was expecting that blinking will slow down to 1 sec blink but it seems the blinking stays the same.. how come ? 

    another strange thing for me is that the compare event happens only once at start, is it not supposed to happen every 3 sec and not only after the first 3 sec, is there no zeroing of the counter after each compare event ? 

    one more thing which is critical for me is that i get the event handler to be called on each tick event, i don't want this in my program, i want the event to be called only when compare event has accurse, can you explain what changes i need to make to get that ? 

    hope to read you soon 

    p.s. in my code 

    static void timers_init(void)
    {
        ret_code_t err_code = NRF_LOG_INIT(NULL);
        sd_clock_hfclk_request();  // this is for the audio sempling rate
    
        err_code = nrf_drv_clock_init();
        APP_ERROR_CHECK(err_code);
        nrf_drv_clock_lfclk_request(NULL);
    
        //Initialize RTC instance
        nrf_drv_rtc_config_t config = NRF_DRV_RTC_DEFAULT_CONFIG;
        config.prescaler = 32767; //8191; // 32767; // 4095; // with 32768 it should tick every one second
        err_code = nrf_drv_rtc_init(&rtc_10_min, &config, rtc_10_min_handler);
        APP_ERROR_CHECK(err_code);
    
        //Enable tick event & interrupt
        nrf_drv_rtc_tick_enable(&rtc_10_min,true);
    
        //Set compare channel to trigger interrupt after COMPARE_COUNTERTIME seconds
        err_code = nrf_drv_rtc_cc_set(&rtc_10_min,0,COMPARE_COUNTER_10_MIN, true);
        APP_ERROR_CHECK(err_code);
    
        //Power on RTC instance
        nrf_drv_rtc_enable(&rtc_10_min);
    
        // app_timer used by other modules
        err_code = app_timer_init();
        APP_ERROR_CHECK(err_code);
    }

    where this is the handler:

    volatile uint32_t count = 0;
    
    static void rtc_10_min_handler(nrf_drv_rtc_int_type_t int_type)
    {
        if (int_type == NRF_DRV_RTC_INT_COMPARE0)
        {
            main_state = MAIN_STATE_EVERY_10_MIN_SAMPELING;
            physic_sample_done_flag = false;
            accelo_sample_done_flag = false;     
    //nrf_gpio_pin_toggle(COMPARE_EVENT_OUTPUT);
        }
        count++;
    //    else if (int_type == NRF_DRV_RTC_INT_TICK)
    //    {
    //    calculaTE delta    
    //nrf_gpio_pin_toggle(TICK_EVENT_OUTPUT);
    //    }
    }

    and this is the instance:

    const nrf_drv_rtc_t rtc_10_min = NRF_DRV_RTC_INSTANCE(2);

    it seems that if i put the count variable in the handler in a watch i see that every 1 second (which is the set refresh time in SEGGER debugging) it adds 8 to its value, even if the pre scaling is 32676, or 8191 it still the same .. why does the pre scaling does not change the tick count ?

    BEST REGARDS

    Ziv

Related