Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 2 of 2

Thread: Very Fast Interval Timer

  1. #1
    Junior Member
    Join Date
    Dec 2017
    Location
    Olive Branch, MS
    Posts
    3

    Very Fast Interval Timer

    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[i]);
    Serial.print(" Processing Time: ");
    Serial.println(ProcessingTimes[i]);
    }
    ++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

  2. #2
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    7,817
    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
    #define SampleRate 1
    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);
      while (!Serial && millis() < 5000 );
      Serial.println("\n" __FILE__ " " __DATE__ " " __TIME__);
      Serial.print("Setup complete. At Sample Timer =");
      Serial.println( SampleRate );
    
      CycleCount.reset();
      MyTimer.begin(Sample, SampleRate ); // <<<<================== 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;
      }
    }

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •