Author Topic: Overclocked tinyAVR timer  (Read 2623 times)

0 Members and 1 Guest are viewing this topic.

Offline T3sl4co1lTopic starter

  • Super Contributor
  • ***
  • Posts: 22435
  • Country: us
  • Expert, Analog Electronics, PCB Layout, EMC
    • Seven Transistor Labs
Overclocked tinyAVR timer
« on: October 15, 2022, 05:30:01 pm »
https://sm6vfz.wordpress.com/2022/10/10/150-mhz-frequency-counter-with-attiny817/

Neat.

I recall XMEGA PLL and some timers can run at 128MHz or thereabouts, could very well be the core logic on those is similar in some respect.  Not that that actually means anything, they're very different processes AFAIK (flat 3.3V logic vs. 5V IOs + low voltage (1.2V?) core).  Though I suppose the truth of it is, they just don't want to rate it running faster than the CPU, and the CPU constitutes the bulk of the complexity (read: propagation delays).  If not for that, everything else can run faster.

Tim
Seven Transistor Labs, LLC
Electronic design, from concept to prototype.
Bringing a project to life?  Send me a message!
 
The following users thanked this post: edavid, ledtester, magic

Offline iMo

  • Super Contributor
  • ***
  • Posts: 5669
  • Country: nu
Re: Overclocked tinyAVR timer
« Reply #1 on: October 15, 2022, 06:31:34 pm »
That reminds me on the vintage 16F84 in a similar config ran freq counter up to 50MHz..
Readers discretion is advised..
 

Offline PCB.Wiz

  • Super Contributor
  • ***
  • Posts: 2288
  • Country: au
Re: Overclocked tinyAVR timer
« Reply #2 on: October 16, 2022, 05:46:58 am »
https://sm6vfz.wordpress.com/2022/10/10/150-mhz-frequency-counter-with-attiny817/

Neat.

I recall XMEGA PLL and some timers can run at 128MHz or thereabouts, could very well be the core logic on those is similar in some respect.  Not that that actually means anything, they're very different processes AFAIK (flat 3.3V logic vs. 5V IOs + low voltage (1.2V?) core).  Though I suppose the truth of it is, they just don't want to rate it running faster than the CPU, and the CPU constitutes the bulk of the complexity (read: propagation delays).  If not for that, everything else can run faster.
The FLASH is often the limit.

The Tiny817 examples is interesting in claiming 10MHz on EXTCLK.32k, and it seems that MCU has a specific bit-setting, so must avoid the usual crystal buffer and enable a separate CMOS buffer

I've tested EFM8 parts external clocking to 200Mhz (the limit of the Si5351a generator) and at room temp that was fine.
Note that's just a small amount of logic in the prescaler counting at 200Mhz, the core itself cannot run above 25Mhz or 50Mhz
Some parts do specify an external clock maximum, FWIR I've seen 125MHz on some xmegas (but the core must be < 32Mhz)

If doing a Freq Counter I have thought about using two MCUs - one dedicated purely to a prescaler, or using a 74AHC1G4208 as a prescaler. (that has a preamplifier included )
« Last Edit: October 16, 2022, 07:17:01 am by PCB.Wiz »
 

Offline magic

  • Super Contributor
  • ***
  • Posts: 7568
  • Country: pl
Re: Overclocked tinyAVR timer
« Reply #3 on: October 16, 2022, 07:25:36 am »
I wonder if resolution could be improved with this statistical technology:
https://www.eevblog.com/forum/projects/8-11-digits-reciprocal-frequency-counter-0-1-hz-150-mhz/

That being said, I look at that thread and see that I raised some objections with regard to possible race conditions.
I'm not sure if they could be solved, but maybe the errors would be too rare or drowned and averaged in the noise.
It seemed to work for the OP.
 

Offline cv007

  • Frequent Contributor
  • **
  • Posts: 879
Re: Overclocked tinyAVR timer
« Reply #4 on: October 16, 2022, 07:35:23 am »
Nothing is really being 'overclocked' as tcd and rtc are both async counters. The datasheet is not very clear on what the limits are (or silent), but in the case of the rtc they just say it can be clocked with an external clock (no limit said or implied). The rtc in these newer avr's seem to be neglected for some reason, but is a handy timer to have.

For a freq counter, there are plenty of options for events to capture the tcd counter (clocked externally) so the rtc is not the only way to get this done (rtc also can use ovf/cmp to generate events, and if a 32k xtal is used the rtc can be set to generate an event at 1Hz without outside help).

This is one way- let the tcd overflow irq advance a counter by its width along with the tcd capture to finalize each 1Hz event. The tcd irq ovf will get more frequent as the measured clock speed increases, so at some point the isr duration comes into play. Its probably about 100 cpu clocks to get in/out of the isr, so assuming double that it will still allow reading in the 400MHz range (20MHz/200*4096) but very little time to do much else. So the limit will most likely not be from the software side. One could lessen the ovf isr frequency if needed by prescaling the tcd counter, but if you get to that point you may be up against hardware limitations anyway.

If I had a 10MHz ref that could not be reduced, I think I would do the same as above, just using the rtc to divide the 10MHz via the PER register- set to 49999, on the ovf irq #199 enable the rtc ovf event so the next ovf gets a tcd capture.

The following is using an external 1Hz 'gate' generated from a 32k xtal on an efr32 board via its letimer output, measuring the efr32 38.4MHz clockout. I am measuring 38400563Hz +/-1 count, and I assume since it is quite stable its probably ok but I have no good way to verify either clock.

Quote
#include "MyAvr.hpp"
//attiny3217 curiosity nano
//led0 = PA3, same as EXTCLK input (any ext clock use will override pin)
//debug = (uart0, 230400)
//PC3 will be 1Hz 'gate' input

                volatile u32 tcd_count_1s;
                volatile u32 tcd_count;
                volatile bool tcd_count_1s_rdy;

                extern "C" __attribute__ (( signal, used )) void
TCD0_OVF_vect   ()
                { //higher priority than trig
                TCD0.INTFLAGS = 1;
                tcd_count += 4096;
                }

                extern "C" __attribute__ (( signal, used )) void
TCD0_TRIG_vect  ()
                {
                TCD0.INTFLAGS = 4;
                auto capt = TCD0.CAPTUREA; //16bit register, 12bit value
                tcd_count_1s = tcd_count + capt;
                tcd_count = -(uint32_t)capt; //setup for first ovf irq count adjust
                tcd_count_1s_rdy = true;
                }


                int
main         ()
                {
                _PROTECTED_WRITE(CLKCTRL.MCLKCTRLB, 0);     //20MHz
                EVSYS.ASYNCCH2 = 0xd;   //PC3 - 1Hz 'gate' input
                EVSYS.ASYNCUSER6 = 5;   //TCD0_EV0, ASYNCHCH2

                TCD0.EVCTRLA = 0x85;    //ASYNCON, CAPTURE, TRIGEI
                TCD0.INTCTRL = 5;       //TRIGA, OVF
                TCD0.CMPBCLR = 0xFFF;   //full period
                TCD0.CTRLA = 0x41;      //extclk, enable

                asm("sei");
                while(1){
                    while( not tcd_count_1s_rdy ){}
                    tcd_count_1s_rdy = false;
                    debug << tcd_count_1s << " Hz" << endl;
                    }

                }
 

Offline magic

  • Super Contributor
  • ***
  • Posts: 7568
  • Country: pl
Re: Overclocked tinyAVR timer
« Reply #5 on: October 16, 2022, 07:48:07 am »
Isn't it possible to overflow TCD into another 16 bit counter with events?
Then the software would only need to deal with reading captured samples and doing the maths.
 

Offline cv007

  • Frequent Contributor
  • **
  • Posts: 879
Re: Overclocked tinyAVR timer
« Reply #6 on: October 16, 2022, 08:30:57 am »
Could possibly be some way, but I don't see it at the moment. The tcd is an async generator so have to have an async user, and tca which can count events is a sync user so cannot use tcd events.

Maybe the tcd could use an output to drive the rtc (tosc1) via external connection, so rtc would then be counting tcd overflows. I think I was going to try it, but my curiosity board tosc1 pin is a uart pin that is being used.

My example probably needs some more thought about the irq's as you may need to sort out the order of occurrence in some cases. There is also a high priority interrupt option that could probably be put to use also.

I think adding this in the middle of the ovf isr would take care of the situation where a third isr is blocking these isr's when both ovf/capture have taken place-
Code: [Select]
if( (TCD0.INTFLAGS bitand 4) and (TCD0.CAPTUREA > 4096/2) ) return;if the capt irq occurred and the capt value is high then skip adding the 4096 as the capture was probably before the overflow. I think all other combos work out ok (the first to fire runs first), and if these irq's fire at the same time then the ovf has priority and ends up correct also.
« Last Edit: October 16, 2022, 09:05:31 am by cv007 »
 

Offline magic

  • Super Contributor
  • ***
  • Posts: 7568
  • Country: pl
Re: Overclocked tinyAVR timer
« Reply #7 on: October 16, 2022, 10:27:25 am »
IIRC most GPIOs can generate sync events and a few can output async events, maybe there is some overlap, maybe even one that isn't used by UART on your board? It's stupid to push this signal through a pin, but the list of sync generators is short and it doesn't look like there are other peripherals capable of synchronizing an async event.

(Of course the point of this trick is that a sync event can subsequently be counted by a sync timer, so no need to abuse RTC).

And TCD must be configured to output 50% duty cycle waveform for the synchronizers to reliably pick it up at high speeds. I don't know if that's possible; I see that there are "compare match" outputs, which sounds like single-cycle strobe.

edit
Screw TCD events, use its PWM outputs. Set up WOA/WOB pin as a sync event source. AVR can generally read its own output on GPIOs, this is likely to work.
« Last Edit: October 16, 2022, 11:53:51 am by magic »
 

Offline T3sl4co1lTopic starter

  • Super Contributor
  • ***
  • Posts: 22435
  • Country: us
  • Expert, Analog Electronics, PCB Layout, EMC
    • Seven Transistor Labs
Re: Overclocked tinyAVR timer
« Reply #8 on: October 16, 2022, 01:54:21 pm »
The FLASH is often the limit.

Right---and that's usually no more than 60MHz or something like that, even on ARMs made to run much faster; and at that, is that usually with 2-cycle latency, I forget?  The "accelerator" (cache) on those is very much mandatory for [average] performance.

Heh, interesting I suppose, tinyAVR / AVR-Dx shouldn't overclock with supply voltage to any significant extent, on account of the internal core supply; that should only affect port IO (so, only to the extent that's limiting performance).  XMEGA ought to go a bit higher then, and I know ATMEGA have been demonstrated a bit higher (30-some MHz, maybe with cooling and elevated supply; ex: https://hackaday.com/2015/08/04/clocking-or-overclocking-an-avr/ ) so that makes sense.

Tim
Seven Transistor Labs, LLC
Electronic design, from concept to prototype.
Bringing a project to life?  Send me a message!
 

Offline T3sl4co1lTopic starter

  • Super Contributor
  • ***
  • Posts: 22435
  • Country: us
  • Expert, Analog Electronics, PCB Layout, EMC
    • Seven Transistor Labs
Re: Overclocked tinyAVR timer
« Reply #9 on: October 16, 2022, 02:04:52 pm »
I wonder if resolution could be improved with this statistical technology:
https://www.eevblog.com/forum/projects/8-11-digits-reciprocal-frequency-counter-0-1-hz-150-mhz/

That being said, I look at that thread and see that I raised some objections with regard to possible race conditions.
I'm not sure if they could be solved, but maybe the errors would be too rare or drowned and averaged in the noise.
It seemed to work for the OP.

Also lots of possibilities with the configurable logic, for example using TCA0 to gate another clock.  I recently did something similar to that on a project, doing equivalent time sampling by triggering the ADC at a fixed offset from a main timer.  Took a bit of work to solve the race conditions; several things are not as they seem, and I ended up having to reset the logic in software (in the ISR, after saving the ADC result) to get the hold-off correct.  Partly exacerbated by using multiple interrupts, so the CPU might not respond promptly all the time.

The CCL is asynchronous as well, so likely can run quite fast too.  Oh hm, I forget offhand if TCD can be clocked from CCL, or if you'll need to hack in a jumper wire (LUT output --> CLK in).  In which case, going through the pin will significantly limit speed.

Tim
Seven Transistor Labs, LLC
Electronic design, from concept to prototype.
Bringing a project to life?  Send me a message!
 

Offline MikeK

  • Super Contributor
  • ***
  • Posts: 1316
  • Country: us
Re: Overclocked tinyAVR timer
« Reply #10 on: October 16, 2022, 02:21:23 pm »
I'm skeptical of the accuracy, even near 100MHz.  Yeah, the original PIC16F84 frequency counter could go up to 50MHz.  And that limit was based on the rise/fall time of the T0CKI pin.  Which is STILL the limit on modern PIC's.  So Atmel had some magic sauce that drastically beat PIC's toggle speed and PIC's still can't go any faster than 50MHz?
 

Offline magic

  • Super Contributor
  • ***
  • Posts: 7568
  • Country: pl
Re: Overclocked tinyAVR timer
« Reply #11 on: October 16, 2022, 03:19:02 pm »
Yes, this should be validated by showing an exact count down to the last digit while running on the same reference clock as the generator. The screenshot posted by the author isn't perfect ::)

The CCL is asynchronous as well, so likely can run quite fast too.  Oh hm, I forget offhand if TCD can be clocked from CCL, or if you'll need to hack in a jumper wire (LUT output --> CLK in).  In which case, going through the pin will significantly limit speed.
The datasheet seems to suggest its either one of the internal clocks or the EXTCLK pin.

It's interesting if reciprocal counting and the linear regression trick could be made to work. Perhaps TCD's PWM capability could be used as a prescaler to derive sampling triggers synchronized to signal edges at some rate the CPU can deal with (tens of kHz) and feed this as an event to TCD and TCA/TCB (counting wall time) to be captured simultaneously. Then atomicity is ensured by reading out the capture registers promptly enough. I think...
« Last Edit: October 16, 2022, 03:23:03 pm by magic »
 

Offline MikeK

  • Super Contributor
  • ***
  • Posts: 1316
  • Country: us
Re: Overclocked tinyAVR timer
« Reply #12 on: October 16, 2022, 04:22:28 pm »
I'm skeptical of the accuracy, even near 100MHz.  Yeah, the original PIC16F84 frequency counter could go up to 50MHz.  And that limit was based on the rise/fall time of the T0CKI pin.  Which is STILL the limit on modern PIC's.  So Atmel had some magic sauce that drastically beat PIC's toggle speed and PIC's still can't go any faster than 50MHz?

Okay, I'm impressed.

For PIC's, the rise and fall times have always been 10ns each.  So 1/20ns = 50MHz.  The datasheet for the ATtiny817 says that the rise and fall times are 1.5ns and 1.3ns (quoted as typical, and at 5V).  So 1/2.8ns = 357MHz.  Damn!

I'm going to have to buy one of these and see for myself.  I have a PIC-based frequency counter and didn't like the limit of 50MHz.
 

Offline ledtester

  • Super Contributor
  • ***
  • Posts: 3453
  • Country: us
Re: Overclocked tinyAVR timer
« Reply #13 on: October 16, 2022, 04:35:25 pm »
I'm going to have to buy one of these and see for myself.  I have a PIC-based frequency counter and didn't like the limit of 50MHz.

If you don't know about it already you might be interested in this alternate firmware for the PIC:

PIC Frequency Counter: Fixing the pulse-width problem (and getting beyond 100 MHz)
https://youtu.be/HVVcTv75RFs
 

Offline MikeK

  • Super Contributor
  • ***
  • Posts: 1316
  • Country: us
Re: Overclocked tinyAVR timer
« Reply #14 on: October 16, 2022, 05:44:42 pm »
I'm going to have to buy one of these and see for myself.  I have a PIC-based frequency counter and didn't like the limit of 50MHz.

If you don't know about it already you might be interested in this alternate firmware for the PIC:

PIC Frequency Counter: Fixing the pulse-width problem (and getting beyond 100 MHz)
https://youtu.be/HVVcTv75RFs

Yep, I have that, thanks.  The problem is that the 100MHz is not guaranteed; the spec of the PIC T0CKI pin is still only 50MHz.  To be honest I haven't seen how far mine can be pushed.
 

Offline PCB.Wiz

  • Super Contributor
  • ***
  • Posts: 2288
  • Country: au
Re: Overclocked tinyAVR timer
« Reply #15 on: October 16, 2022, 09:41:05 pm »
For PIC's, the rise and fall times have always been 10ns each.  So 1/20ns = 50MHz.  The datasheet for the ATtiny817 says that the rise and fall times are 1.5ns and 1.3ns (quoted as typical, and at 5V).  So 1/2.8ns = 357MHz.  Damn!
I'm going to have to buy one of these and see for myself.  I have a PIC-based frequency counter and didn't like the limit of 50MHz.

You cannot make the leap between rise/fall times and counting ability.

The counting limit is set by the pin buffer plus internal flip flop logic, and smaller dividers will be faster than larger ones.
Most vendors these days have something like a 100MHz pin limit, on CMOS MCU parts, but typically they can go much higher (see above my room temp tests to 200MHz on EFM8 MCU EXTCLK)
ESD structures tend to lower the upper pin limit.

You can also get an idea on CMOS logic speeds, from new tiny gate parts like 74LVC1G80 - that shows 200MHz min and 400MHz typ toggle rates
The 74AHC1G42xx counters spec 165MHz min so should be ~ 300MHz typically, so are a compact option to extend counters.
« Last Edit: October 17, 2022, 03:04:12 am by PCB.Wiz »
 

Offline MikeK

  • Super Contributor
  • ***
  • Posts: 1316
  • Country: us
Re: Overclocked tinyAVR timer
« Reply #16 on: October 16, 2022, 10:49:08 pm »
For PIC's, the rise and fall times have always been 10ns each.  So 1/20ns = 50MHz.  The datasheet for the ATtiny817 says that the rise and fall times are 1.5ns and 1.3ns (quoted as typical, and at 5V).  So 1/2.8ns = 357MHz.  Damn!
I'm going to have to buy one of these and see for myself.  I have a PIC-based frequency counter and didn't like the limit of 50MHz.

You cannot make the leap between rise/fall times and counting ability.

I shouldn't have said rise/fall times.  Should have been high/low times, or period.  That directly determines the max operating frequency.  Signals that are too fast will simply fail to trigger the input circuitry properly.
 

Offline cv007

  • Frequent Contributor
  • **
  • Posts: 879
Re: Overclocked tinyAVR timer
« Reply #17 on: October 20, 2022, 10:33:24 am »
Since I had a samd10 xplained mini 2 feet away from my tiny3217 curiosity nano, it was begging for a chance to show up its cousin. It is showing 38400551 +/-2 also clocked via an efr32 (38.4MHz clkout, and its 32k xtal providing the 1Hz via timer output). The advantage here of course is no interrupts needed (I'm running the samd at its reset clock speed of 1MHz).

It took me about 5 times longer to get it to work as I have a hard time making sense of the samd sometimes. Not sure if I have it correct, but it is working. Probably a dozen better ways to do this, but I focused on the first one I thought of using TC1/2 as a 32bit timer.

The avr is easy to use, but is working harder as it only can capture via the 12bit timer. The samd is harder to use, but it exerts little effort in doing the same job. Same as always with 8bit vs 32bit. The price difference is minimal, so if I wanted to create a simple freq counter I would go with the samd. In either case its probably not going to replace a bench instrument but will be good enough for many uses (and better than many handheld multimeters). Hanging a 32k xtal on to either will get you to a pretty stable 1Hz gate so about the only remaining questions would be is how to display the info and how to buffer the input signal.

Code: [Select]
#include "MySam.hpp" //samd10 xplained mini
//led = PA09, debug = uart0, tx PA10, 9600baud
//to make changing pins easier, store pin info here and change as needed
static const struct { PIN pin; Eic::EXTINTn extintN; Evsys::SOURCE evsrc; }
    Gate1Hz { PA16, Eic.EXTINT0, Evsys::EXTINT0 };
static const struct { Gclk::GENERATOR genN; PIN pin; }
    ExtFreq { Gclk::GEN5, PA15 };

int main(){
    Gclk.generatorSource( ExtFreq.genN, Gclk.GCLKIN ); //use GCLK_IO[n] as clock source
    Pin( ExtFreq.pin, INPUT ).altFunction( ALTFUNC_GCLK ); //pin = GCLK_IO[n] input

    Eic //setup gate event, will be 1Hz gate (capture) event for Tc132
        .gclk( ExtFreq.genN ) //same async clock as tc1 counter
        .config( Gate1Hz.extintN, Eic.RISE )
        .eventOn( Gate1Hz.extintN )
        .on();
    Pin( Gate1Hz.pin, INPUT ).altFunction( ALTFUNC_EIC );

    Evsys //setup async event on CH0, EXTINT0 -> TC1EVU
        .userChannel( Evsys.TC1EVU, Evsys.CH0 )
        .sourceChannel( Gate1Hz.evsrc, Evsys.CH0, Evsys.ASYNC );

    Tc132 //Tc1+Tc2 32bit counter, capture on event to CC0
        .gclk( ExtFreq.genN )
        .eventCapture( Tc132.CAPT0, Tc132.PPW )
        .readContinuous( Tc132.CC0 )
        .on();

    for(;;){
        led.toggle();
        while( not Tc132.isFlag(Tc132.CAPT0) ){} //1Hz
        auto period = Tc132.capturePeriod();
        debug << FG CYAN << period/1000000 /*MHz*/ << '.' << setwf(6,'0') << period%1000000 << FG ORANGE " MHz"
              << endl;
        }
}
or, putting the power of C++ to work by making the freq counter a class where you can just specify the pins you want (templates allow easy compile time checking for validity of glk_io and extint pins, along with sorting out the appropriate genN, extintN, and evsys source from the pins provided, but templates are not a necessity to make this class work).
Code: [Select]
#include "MySam.hpp" //samd10 xplained mini
//led = PA09, debug = uart0, tx PA10, 9600baud

FreqCounter<PA15, PA16> freq; //<pin count (gclk_io), pin 1hz (extint) [, evsys channel]>
int main(){
    for(;;){
        led.toggle();
        u32 period;
        while( not freq.read(period) ){}
        debug << FG CYAN << period/1000000 /*MHz*/ << '.' << setwf(6,'0') << period%1000000 << FG ORANGE " MHz" << endl;
        }
}
edit- I added duty cycle by capturing both 1Hz edges.
edit- I subtracted duty cycle as it was of the 1Hz gate clock, which is of no value (my thinking cap was not on). I don't think there is a way to measure duty cycle internally as there is no other clock to use as a measuring stick (at least for the higher frequencies).
« Last Edit: October 23, 2022, 07:53:06 am by cv007 »
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf