SAMD21 Timer/Counter Callback jitter when reading multiple TC values

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

I am using a samd21g18a and I am seeing incorrect callback times for TC4/5 (32 bit counter) when I setup another timer (say TC3) and I read the value from that timer before reading the value from TC4.  I have tried to recreate the problem outside of my project using the samd21j18a XPLAINED board.

 

What I see is if I setup TC3 as a 16 bit counter with no callback and I setup TC4 as a 32 bit counter with a callback running off the external 32 kHz crystal and I read both of them (tc_get_count_value) in a loop I will see noise on the TC4 callback.

 

Hopefully, to make this easy to reproduce I am using the standalone ASF download (xdk-asf-3.32.0) and I modified the quick_start_callback example as show in the attached file (xdk-asf-3.32.0/sam0/drivers/tc/quick_start_callback/qs_tc_callback.c).  I also modified the conf_clocks.h (xdk-asf-3.32.0/sam0/drivers/tc/quick_start_callback/samd21_xplained_pro/conf_clocks.h) to use the 32kHz external oscillator and DFLL to produce the 48MHz clock.  I then ran the make file (xdk-asf-3.32.0/sam0/drivers/tc/quick_start_callback/samd21_xplained_pro/gcc/Makefile) and use openocd to write the hex file to the xplained board using the USB debug.

 

If you put a scope on the LED you will see jitter on the ~1ms signal.  If you comment out either of the tc_get_count_value functions:

 

Line 190: tc_get_count_value(&tc_instance2);

 

Line 192: tc_get_count_value(&tc_instance);

 

then the jitter goes away.

 

Another interesting note is if you increase the for loop value from 70 to say 1000 the jitter goes away as well.

 

My actually problem shows up when I use tickless mode of freeRTOS running off TC4/5 and it will occasionally fire the freeRTOS at very short intervals if I am using another timer/counter in my code.

 

I asked Atmel support if this could be related to Errata 13268 but was told that is only if I use the event system.  I sent this information to them as well so hopefully I will get a response that I can share.

 

Any help is appreciated...

 

Attachment(s): 

This topic has a solution.
Last Edited: Wed. Jan 4, 2017 - 07:19 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Possibly it's the slow clock on tc_instance causing syncing to to take a lot of time. You can test that by clocking that timer from GCLK_GENERATOR_0 also (top value 48000 to get 1ms).

/Lars

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

Thank for the response,

 

The sync does take a long time and it is a concern, yet in my application I am using freeRTOS in tickless mode so that I can achieve low sleep currents by just keeping the external oscillator running.  Any insight on why the problem appears to go away if I only read tc_instance?  Am I just getting lucky?

 

 

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

Deleted.

Last Edited: Thu. Dec 15, 2016 - 08:19 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I did some more playing and I noticed that even if I don't do a sync as part of the read I still see the problem.  It turns out if you replace

 

tc_get_count_value(&tc_instance2);

 

with a read of the count register

 

tc_instance2.hw->COUNT32.COUNT.reg;

 

then the jitter still shows up.  That surprised me cause I thought it was the slow sync (tc_is_syncing) that was causing the jitter in the interrupt handler.  I did get a short reply from Atmel, but it was one of those that makes you wonder if they even read your email.  If I get any real responses from them I will be sure to share.

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

If you "don't do a sync" yourself, then "the bus will be stalled" for the duration you would otherwise be sitting in the while(ts_is_syncing) loop. No surprise there.

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

Thank you, that does make sense.  So why is it that I only see the jitter with multiple timer/counters?

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

Can you say something about the jitter timing (or show us)? Does it look like it is related to the timer clock period?

/Lars

 

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

So in the test case I presented on the XPLAINED board I toggle the LED pin every ~1ms and the values are very consistent.  With the read of the second timer counter the time between toggle will vary 100-200 uS, which is on order of the 6 counts it takes to sync when running at 32kHz.  Thus I would expect to see the variation when I am just reading TC4, but it only shows up when I do a second read (say of TC3).  I will try to come up with some output I can post on Monday.

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

So here are some scope pictures.  First one is with just a read of TC4 and no read of TC3.  The second includes a read of TC3.  I should note that if I read TC3 once and then read TC4 once I see no jitter.  The jitter just occurs when I do a loop with about 70 TC3 reads and then read TC4.

 

The 184 uS difference between pos and negative width is expected since that is almost exactly the amount of time it takes to make a TC4 read (~182 us).  What I don't understand is why the reads of TC3 increase that time.  Do I need to increase the interrupt priority some how?

 

 

 

Attachment(s): 

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

I also don't get why TC3 reading should affect the timing like that. I hope you get some answer from Atmel. Meanwhile, maybe it would it be possible to work around this using RTC or TCC. The reason I can think that can make a difference is that they both have a read request function for the counter value. TCC also has a different synchronization scheme (distributed synchronizer vs common synchronizer).
BTW, is there any real need to read the counter value of TC4 if you just use it to get the ~1ms callback?
/Lars

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

I just ran the test using SysTick instead of TC3 and I did not see the issue, I had previously seen some problems with my board.  I will have to try TCC as well...

 

My actual application uses freeRTOS in Tickless mode with the idea being that you don't wake up every 1mS but sleep until something needs to happen.  Then when you wake up, read the timer/counter and adjust the tick counts accordingly.  I added a delay using systick, and then TC3, so that it wouldn't enter tickless mode until it was done printing and that is when I would notice some strange results.  If I took out the delay then the strange timing would disappear.  My troubleshooting lead me to this example because I didn't want to convolute things with having freeRTOS in the mix.

 

I did get another response from Atmel and it was disheartening.  I am sure the engineer is just overworked and is required to answer with something so they just throw out whatever might make sense but it is as if they don't even read the question.  That being said I will keep the dialogue moving forward.  Sometimes good things can come from the most unsuspecting source.  Used to have a great regional sales rep for the area that would help get my questions answered but sadly no longer with Atmel and they haven't hired anyone new.

 

Last Edited: Tue. Dec 20, 2016 - 11:30 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

This is why it is good to run things on an independent set up cause what you think is not always what you find.  I had thought that I saw jitter with SysTick and TCC with my actual design but when I run this test case on the xplained board then I see no jitter.  It actually evens up the positive and negative slope as you would expect cause the interrupt can fire when other things are being read.  I will try and use TC4 with TCC1 in my actual design and see if things clear up.  My question still remains why the extra jitter with read of TC3.  Maybe there is a shared synchronizer related issue.

This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Lajon wrote:

I also don't get why TC3 reading should affect the timing like that. I hope you get some answer from Atmel. Meanwhile, maybe it would it be possible to work around this using RTC or TCC. The reason I can think that can make a difference is that they both have a read request function for the counter value. TCC also has a different synchronization scheme (distributed synchronizer vs common synchronizer).
BTW, is there any real need to read the counter value of TC4 if you just use it to get the ~1ms callback?
/Lars

Looks like I overlooked that TC also has a read request register, i.e., possibly it will make a difference if 

		TC4->COUNT32.READREQ.reg = TC_READREQ_RREQ | TC_READREQ_ADDR(0x10);

is added before 

		tc_get_count_value(&tc_instance);

/Lars

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

Happy New Year,

 

I did get a response from Atmel that went as follows:

 

"When both GCLKS are sourced by the same clock, (32khz, internal 8Mhz, internal 32khz) the delta between the readings remains consistent.

When both GCLKS are sourced by different clocks, (32khz, internal 8Mhz, internal 32khz) the delta between the readings will vary with in a small window (up to 16 count by observation)."

 

I also got this response:

 

"All of these issues are most likely related to synchronization. Even just reading the register directly, the D21 will still synchronize the clock domains and stall the bus while waiting...Remember, synchronization takes 2-3 clock cycles. Using a 32kHz clock for TC (GCLK 1) while cause a considerable delay during this synchronization. Better to use on demand clocking with the 8MHz internal RC or GCLK 0. This will still yield low power, but demand the clock when it is needed."

 

The question I ask in response (and hoping I get one) is how then do I implement a sleep in tickless mode of freeRTOS.  My thought was that I would use the external 32kHz oscillator because it was the lowest power but these responses tell me that there is a better way to have a fast clock and low power?

 

Lars, thanks for the information, I will try and implement it and see if it makes a difference.  The reason I have to read TC4 is after a sleep the exact sleep time is not known, if you woke from some non-count related interrupt.  So a read of TC4 is performed to calculate how many ticks occurred during sleep.

 

As always, insight is appreciated...

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

Lars, that read request was the key.  Adding that to my TC4 configuration fixed the jitter issue.  The answer was also just given to me by atmel support:

 

"Essentially the READREQ register of the TC module will allow the user to assign an address to the register to update a value as needed or continuously internal to the module and eliminate the sync delay."

 

That is very informative and very helpful.  Hopefully this will help eliminate the tick issues I am seeing in my tickless freeRTOS.

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

With the help above I was able to get my tickless implementation working but I had to add a sync of TC4 right before sleep.  I have posted it as a new question since this question has been well answered.

 

https://community.atmel.com/forum/samd21-tc-sync-fixes-short-sleep

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

Hi,

 

according to Atmel's (Microchip's) Datasheet TC3/4 are combined and not TC4/5 as in this thread is written for 32 bit mode. Could this probably case the issues your are talking about.

 

From datasheet:

 

This mode is achieved by pairing two 16-bit TC peripherals. TC3 is paired with TC4, and TC5 is paired with TC6. TC7 does not support 32-bit resolution.When paired, the TC peripherals are configured using the registers of the even-numbered TC (TC4 orTC6 respectively). The odd-numbered partner (TC3 or TC5 respectively) will act as slave, and theSlave bit in the Status register (STATUS.SLAVE) will be set. The register values of a slave willnot reflect the registers of the 32-bit counter. Writing to any of the slave registers will not affect the 32-bit counter. Normal access to the slave COUNT and CCx registers is not allowed.

 

spachner

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

"TC3 is paired with TC4, and TC5 is paired with TC6. TC7 does not support 32-bit resolution" - that doesn't seem right as far as I remember; need to dig through older datasheets and maybe contact Microchip.

 

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

This is one of those cases where you can't completely believe the datasheet. If you look in gclk.h for samd21 you will see the pairings.

 

#define   GCLK_CLKCTRL_ID_TCC0_TCC1_Val   0x1Aul  /**< \brief (GCLK_CLKCTRL) TCC0_TCC1 */
#define   GCLK_CLKCTRL_ID_TCC2_TC3_Val    0x1Bul  /**< \brief (GCLK_CLKCTRL) TCC2_TC3 */
#define   GCLK_CLKCTRL_ID_TC4_TC5_Val     0x1Cul  /**< \brief (GCLK_CLKCTRL) TC4_TC5 */
#define   GCLK_CLKCTRL_ID_TC6_TC7_Val     0x1Dul  /**< \brief (GCLK_CLKCTRL) TC6_TC7 */

And I can confirm that TC4/TC5 do work as a 32 bit pair.

 

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

Hi,

 

many thanks. This is interesting. I filed a report to Microchip.

 

regards

 

spachner

 

 

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

Hi,

 

I got an official statement from Microchip that the datasheet is wrong and indead TC4/TC5 do work as a 32 bit pair.

 

spachner