SAMD21 TC sync fixes short sleep?

Go To Last Post
6 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I am using SAMD21g18a with FreeRTOS in tickless mode.  After much assistance (https://community.atmel.com/forum/samd21-timercounter-callback-jitter-when-reading-multiple-tc-values), I have a tickless implementation (a modified version of the ASF tickless.c) that is working.  The issue is that I have to do a sync of TC4 before I sleep or I occasionally see an 8 ms sleep cycle instead of something on the order of 1000 ms.

 

			while (tc_is_syncing(&tc45)) {
				/* Wait for sync */
			}
			system_sleep();

 

Any insight on why this might be?

 

I have attached the full tickless.c implementation.

Attachment(s): 

Last Edited: Fri. Jan 6, 2017 - 03:15 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi,

 

I could image that this happens: Have a look into the implementation of tc_set_top_value()

 

enum status_code tc_set_top_value (
        const struct tc_module *const module_inst,
        const uint32_t top_value)
{
    Assert(module_inst);
    Assert(module_inst->hw);
    Assert(top_value);

    Tc *const tc_module = module_inst->hw;

    while (tc_is_syncing(module_inst)) {
        /* Wait for sync */
    }

    switch (module_inst->counter_size) {

        ...
        tc_module->COUNT = top_value; // pseudo line

        ...
    }
}

 

You see that there is not explicit sync after writing the tc_module->COUNT. Upon the write the synchronisation automatically starts which take many cycles since the TC runs at a different clock domain (32kHz, 30us period) while the ARM core runs on PLL with many MHz. Usually 2-3 slow clock cylces are needed for the sync, which results in upto ~100us. When the processor executes the WFI instruction (inside system_sleep() ) the low power mode is enterred and the PLL stops. I image this stops the synchronisation, too. Finally the new TOP value is not yet available in the TC and the current (yet old) value is still used.
Your addition of while (tc_is_syncing(&tc45))... make sure that the new top value arrives in time.

 

spachner

Last Edited: Wed. May 16, 2018 - 03:02 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi,

 

I do not understand the reason for this explicit READREQ the line TC4->COUNT32.READREQ.reg = TC_READREQ_RREQ | TC_READREQ_ADDR(0x10); in vPortSetupTimerInterrupt() . It is only executed once and therefore only triggers a single syncronisation, so does not really help. At least so far I understand the datasheet. Simple reading from register 0x10 (COUNT) does an automatic sync (in hardware) and should be safe. Of course you should expect some delay due to the synchronisation (slow clock to fast clock) done in hardware.

 

regards

 

spachner

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Greetings,  since I posted this we have switched from FreeRTOS to a TNEO derivative that allows for a better tickless implementation.  What we have discovered is that the switch from a 32 bit counter to a 32kHz oscillator for sleep just takes too much time as a result of the synchronization, as you point out.  Thus we just use RTC running off the 32 bit external oscillator so there isn't any switching at sleep and this has worked well.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi photonthunder,

 

thanks for your reply. Sorry, I cannot follow. With SAMD21 you do not have many choices. In order to maintain low power during sleep the clock which drives a timer peripheral (either TC, RTC or whatever) must be a 32kHz crystal. As a consequence your fast running mcu core has to synchronize registers read/writes which takes time. This burden does not vanish when using a different RTOS.

 

You are also talking about your final solution: "Thus we just use RTC running off the 32 bit external oscillator so there isn't any switching at sleep and this has worked well." Well, I consider the FreeRTOS tickless implementation does exactly this. What du you mean with "switching".

 

Do you mind to reveal the source of mentioned TNEO derivative, I am curious.

 

regards

 

spachner

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

So the way FreeRTOS implemented tickless last year (hopefully they have updated since then) was to use a 32 bit Timer/Counter (like TC4/5) running of your 48 MHz clock to control your tick (say you have it set for 1 ms).  Then before sleeping you would switch to your 32 kHz clock, I attempted this setup but the extreme delay in syncing made it non-functional for applications that sleep and awake often.  Anytime you sync off a 32 kHz clock be prepared for a long wait...

 

Here is the TNEO link:

https://github.com/dimonomid/tneo