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

Does Counter Mode Timer really need TASKS_START ?

[References]

In page 234 of nRF52832_PS_v1.4 it says
    "In both modes, the TIMER is started by triggering the START task, and stopped by triggering the STOP task."

In this post  stated:
    "You must start the timer with TASKS_START also in counter mode.", 
while the statement from @Mik contradicts as:
    "the counter even counts the signals when not started. it would save mi 8uA when not using TASK_START with the same effect in getting the counting value."

In this post  stated:
    "The information given in the document is not adequate, the designer of the TIMER gave me proper information. In COUNTER mode of the TIMER, the HFCLK is not requested unless there is a COUNT task. When COUNT task is triggered, the TIMER peripheral will request the hfclk to get one clock cycle so that it will be able to do the COUNTER increment logic. And after that it stops requesting the HFCLK. This means that if nothing else is using HFCLK, and when COUNT task is triggered then HFCLK is requested and is turned on for 62ns (1 cycle) and then requested to turn off again."

By testing with the following code, I get the same results as @Mik.
4.8 / 8.7 uA saving is measured on PCA10040 / our PCB if TASKS_START is not set.
Both w/ or w/o TASKS_START will give expected results (1,2,3 are printed)

void main(void)
{
    NRF_LOG_INIT(NULL);
    NRF_LOG_DEFAULT_BACKENDS_INIT();
    
    NRF_TIMER4->TASKS_CLEAR  = 1;
    NRF_TIMER4->SHORTS       = 0;
    NRF_TIMER4->INTENCLR     = 0xffffffff;
    NRF_TIMER4->MODE         = TIMER_MODE_MODE_LowPowerCounter << TIMER_MODE_MODE_Pos;
    NRF_TIMER4->BITMODE      = TIMER_BITMODE_BITMODE_32Bit << TIMER_BITMODE_BITMODE_Pos;
    NRF_TIMER4->PRESCALER    = 0;
    NRF_TIMER4->CC[0]        = 0;
    NRF_TIMER4->CC[1]        = 0;
    NRF_TIMER4->CC[2]        = 0;
    NRF_TIMER4->CC[3]        = 0;
    NRF_TIMER4->CC[4]        = 0;
    NRF_TIMER4->CC[5]        = 0;
    NVIC_DisableIRQ(TIMER4_IRQn);

#ifdef DO_TIMER_TASKS_START
    NRF_TIMER4->TASKS_START  = 1;
#endif

    NRF_TIMER4->TASKS_COUNT = 1;
    NRF_TIMER4->TASKS_CAPTURE[0] = 1;
    NRF_LOG_DEBUG("Timer4->CC[0] = %d", NRF_TIMER4->CC[0]);

    NRF_TIMER4->TASKS_COUNT = 1;
    NRF_TIMER4->TASKS_CAPTURE[0] = 1;
    NRF_LOG_DEBUG("Timer4->CC[0] = %d", NRF_TIMER4->CC[0]);

    NRF_TIMER4->TASKS_COUNT = 1;
    NRF_TIMER4->TASKS_CAPTURE[0] = 1;
    NRF_LOG_DEBUG("Timer4->CC[0] = %d", NRF_TIMER4->CC[0]);

    nrf_pwr_mgmt_init();

    while (1)
    {
        if (NRF_LOG_PROCESS() == false)
        {
            nrf_pwr_mgmt_run();
        }
    }
}

Is it possible that Nordic confirms again in this post for the usage of counter mode timer?
4.8 / 8.7 uA is quite big compared with <2 uA current in "system on, sleep" state, and is critical for optimizing battery life.
Please help on this topic, thank you.

Parents
  • Xavier,

    The counter task might work correctly when you are doing this test after the first reset. I call this kind of result "getting lucky". This is because this was not designed this way, but the internal implementation of it makes it possible to use it. The designers of the hardware always use TASKS_START and TASKS_STOP to request the peripheral resources and release them. In this case, the clock and voltage regulators that are required by the TIMER4 is already running since the CPU is running. Imagine a situation where you have configured your device in a way, that releases all the clocks and voltage regulators are OFF. This is a very common situation on sleep mode. Then not doing a TASKS_START means missing the part where you properly register the module to resource manager. 

    I would recommend you one test.

    1) configure an RTC to generate a TICK every X seconds. (disable all interrupts on this RTC)

    2) use this tick event -> GPIOTE -> connect this task to the TASKS_COUNT

    3) Initialize your TIMER4 exactly like above except that TASKS_COUNT is coming from RTC.

    4) make the system to go to sleep __WFE()

    5) wakeup aftersometime and disable RTC ticks.

    6) check for the TIMER4 counter value

    Why are we doing this? Since we want to see that your "Lucky outcome" will survive the worst case scenario. This is not specified in spec, hence the TIMERS are not tested for this. But if you get a good result above, then you should be covered.

  • Thank you for prompt reply. Let me make sure if I understand correctly. (I'll do the test tomorrow anyway)

      1. After TASKS_START, resources for Timer peripheral are requested and this is the several uA we measured.
      2. TASKS_COUNT will only work while those resources are already requested (by TASKS_START or any other "Luck").
      3. Whenever there is no TASKS_COUNT, it is safe to use TASKS_STOP to release resources. If there are not other peripherals requesting resources, this will save those several uA in 1..
      4. By repeating all 3 on above, Counter Mode Timer can be incremented correctly.

    Am I taking anything wrong on above?

    Assuming TASKS_COUNT is triggered in a relatively long period, is the most energy optimized legal way to use Counter Mode Timer be "pre-triggering event (at least 0.25 us before?) -> PPI -> TASKS_START, riggering event -> PPI -> TASKS_COUNT, post-triggering event (how long after?) -> PPI -> TASKS_STOP" ?

    In this usage, what are the timing requirements between "TASKS_START <=> TASKS_COUNT" & "TASKS_COUNT <=> TASKS_STOP" ? Is there a definitive behavior we can take advantage by using PPI fork or something ?

Reply
  • Thank you for prompt reply. Let me make sure if I understand correctly. (I'll do the test tomorrow anyway)

      1. After TASKS_START, resources for Timer peripheral are requested and this is the several uA we measured.
      2. TASKS_COUNT will only work while those resources are already requested (by TASKS_START or any other "Luck").
      3. Whenever there is no TASKS_COUNT, it is safe to use TASKS_STOP to release resources. If there are not other peripherals requesting resources, this will save those several uA in 1..
      4. By repeating all 3 on above, Counter Mode Timer can be incremented correctly.

    Am I taking anything wrong on above?

    Assuming TASKS_COUNT is triggered in a relatively long period, is the most energy optimized legal way to use Counter Mode Timer be "pre-triggering event (at least 0.25 us before?) -> PPI -> TASKS_START, riggering event -> PPI -> TASKS_COUNT, post-triggering event (how long after?) -> PPI -> TASKS_STOP" ?

    In this usage, what are the timing requirements between "TASKS_START <=> TASKS_COUNT" & "TASKS_COUNT <=> TASKS_STOP" ? Is there a definitive behavior we can take advantage by using PPI fork or something ?

Children
No Data
Related