Very Fast Interval Timer

Status
Not open for further replies.

DavidTroendle

New member
Experts,

I saw Nefarious' post on sub-microsecond timers, but did not see an answer. I have a similar question.

Is it possible to create an interval timer that interrupts every μs on a Teensy 3.6? (I am using DWT_CYCCNT to measure jitter and processing times.)

I tried the sketch below under Windows 10 on a Teensy 3.6. It works as long as the indicated line below "MyTimer.begin(Sample,3000);" is 3000 or more. (Sample output is after code.)

Many thanks for helping a newbie.

David

===================================Sketch===================================

class cCycleCount
{
volatile uint32_t *DWT_CYCCNT;
volatile uint32_t *DWT_CONTROL;
volatile uint32_t *SCB_DEMCR; // debug exception and monitor control
volatile uint32_t *LAR;
public:

cCycleCount(void)
{
DWT_CYCCNT = (volatile uint32_t *) 0xE0001004;
DWT_CONTROL = (volatile uint32_t *) 0xE0001000;
SCB_DEMCR = (volatile uint32_t *) 0xE000EDFC;
LAR = (uint32_t *) 0xE0001FB0;

return;
}

void init(void)
{
*SCB_DEMCR |= 0x01000000;
*LAR = 0xC5ACCE55;
*DWT_CYCCNT = 0; // reset the counter
*DWT_CONTROL |= 1; // enable the counter
}

inline uint32_t ticks(void)
{
return *DWT_CYCCNT;
}

inline uint32_t micros(void)
{
static const uint16_t DIV = F_CPU / 1000 / 1000;
return *DWT_CYCCNT / DIV; // TODO: will skip when wrapping, only use to check drift!
}

inline void reset(void)
{
*DWT_CYCCNT = 0;
return;
}
};

cCycleCount CycleCount;
IntervalTimer MyTimer;

#define nSamples 16u
volatile uint32_t SampleTimes[nSamples];
volatile uint32_t ProcessingTimes[nSamples];
volatile uint32_t SampleIndex = 0u;

void setup(void)
{
CycleCount.init();
SampleIndex = 0u;
Serial.begin(9600);
Serial.println("Setup complete.");
MyTimer.begin(Sample,3000); // <<<<================== Lowest number that works.
}

FASTRUN void Sample(void)
{
uint32_t Count = CycleCount.ticks();
CycleCount.reset();

if (SampleIndex < nSamples)
{
SampleTimes[SampleIndex] = Count;
ProcessingTimes[SampleIndex] = CycleCount.ticks();
++SampleIndex;
}

return;
}

void loop(void)
{
uint32_t Index;

noInterrupts();
Index = SampleIndex;
interrupts();

if (Index == nSamples)
{
for (uint32_t i = 0u; i < nSamples; ++i)
{
Serial.print("Sample: ");
Serial.print(i);
Serial.print(" Count: ");
Serial.print(SampleTimes);
Serial.print(" Processing Time: ");
Serial.println(ProcessingTimes);
}
++SampleIndex;
}
}

===================================Sample Output===================================

Sample: 0 Count: 540492 Processing Time: 16
Sample: 1 Count: 539983 Processing Time: 16
Sample: 2 Count: 540004 Processing Time: 16
Sample: 3 Count: 539992 Processing Time: 16
Sample: 4 Count: 539998 Processing Time: 16
Sample: 5 Count: 539998 Processing Time: 16
Sample: 6 Count: 540004 Processing Time: 16
Sample: 7 Count: 539992 Processing Time: 16
Sample: 8 Count: 539998 Processing Time: 16
Sample: 9 Count: 539998 Processing Time: 16
Sample: 10 Count: 539998 Processing Time: 16
Sample: 11 Count: 539998 Processing Time: 16
Sample: 12 Count: 540013 Processing Time: 16
Sample: 13 Count: 539983 Processing Time: 16
Sample: 14 Count: 539998 Processing Time: 16
Sample: 15 Count: 539998 Processing Time: 16
 
Minor changes - there was no wait for Serial USB to connect in setup(), so print of test results ended up in the bit bucket.

Compiled Fastest + PureCode w/LTO at 256 MHZ and I see it working at 1.
T:\tCode\FORUM\FastIntervTimer\FastIntervTimer.ino Dec 14 2018 16:05:00
Setup complete. At Sample Timer =1
Sample: 0 Count: 434 Processing Time: 13
Sample: 1 Count: 231 Processing Time: 13
Sample: 2 Count: 254 Processing Time: 13
Sample: 3 Count: 254 Processing Time: 13
Sample: 4 Count: 254 Processing Time: 13
Sample: 5 Count: 262 Processing Time: 13
Sample: 6 Count: 246 Processing Time: 13
...

Here is the code - using the # 'CODE' blocking:
Code:
class cCycleCount
{
    volatile uint32_t *DWT_CYCCNT;
    volatile uint32_t *DWT_CONTROL;
    volatile uint32_t *SCB_DEMCR; // debug exception and monitor control
    volatile uint32_t *LAR;
  public:

    cCycleCount(void)
    {
      DWT_CYCCNT = (volatile uint32_t *) 0xE0001004;
      DWT_CONTROL = (volatile uint32_t *) 0xE0001000;
      SCB_DEMCR = (volatile uint32_t *) 0xE000EDFC;
      LAR = (uint32_t *) 0xE0001FB0;

      return;
    }

    void init(void)
    {
      *SCB_DEMCR |= 0x01000000;
      *LAR = 0xC5ACCE55;
      *DWT_CYCCNT = 0; // reset the counter
      *DWT_CONTROL |= 1; // enable the counter
    }

    inline uint32_t ticks(void)
    {
      return *DWT_CYCCNT;
    }

    inline uint32_t micros(void)
    {
      static const uint16_t DIV = F_CPU / 1000 / 1000;
      return *DWT_CYCCNT / DIV; // TODO: will skip when wrapping, only use to check drift!
    }

    inline void reset(void)
    {
      *DWT_CYCCNT = 0;
      return;
    }
};

cCycleCount CycleCount;
IntervalTimer MyTimer;

#define nSamples 16u
[B][U]#define SampleRate 1[/U][/B]
volatile uint32_t SampleTimes[nSamples];
volatile uint32_t ProcessingTimes[nSamples];
volatile uint32_t SampleIndex = 0u;

void setup(void)
{
  CycleCount.init();
  SampleIndex = 0u;
  Serial.begin(9600);
  [B][U]while (!Serial && millis() < 5000 );[/U][/B]
  Serial.println("\n" __FILE__ " " __DATE__ " " __TIME__);
  Serial.print("Setup complete. At Sample Timer =");
  Serial.println( SampleRate );

  CycleCount.reset();
  [B]MyTimer.begin(Sample, SampleRate );[/B] // <<<<================== Lowest number that works.
}

FASTRUN void Sample(void)
{
  uint32_t Count = CycleCount.ticks();
  CycleCount.reset();

  if (SampleIndex < nSamples)
  {
    SampleTimes[SampleIndex] = Count;
    ProcessingTimes[SampleIndex] = CycleCount.ticks();
    ++SampleIndex;
  }

  return;
}

void loop(void)
{
  uint32_t Index;

  noInterrupts();
  Index = SampleIndex;
  interrupts();

  if (Index == nSamples)
  {
    for (uint32_t i = 0u; i < nSamples; ++i)
    {
      Serial.print("Sample: ");
      Serial.print(i);
      Serial.print(" Count: ");
      Serial.print(SampleTimes[i]);
      Serial.print(" Processing Time: ");
      Serial.println(ProcessingTimes[i]);
    }
    ++SampleIndex;
  }
}
 
Status
Not open for further replies.
Back
Top