Anyone Play with the CYCLE count? (CYCCNT)

As I mentioned on the thread:

I know there are several places in Teensy code where when people need accurate timings
and/or delays, they use the ARM cycle count register.
Some of the Teensy code looks like:

    ARM_DEMCR |= ARM_DEMCR_TRCENA;
    ARM_DWT_CTRL |= ARM_DWT_CTRL_CYCCNTENA;
...
    if (target - (ARM_DWT_CYCCNT - begin) > WORST_INTERRUPT_CYCLES+20) {

searching around the GIGA sources and experimenting have dirty sketch which
I believe is enabling it and getting the general speed of it...

void setup() {
    // put your setup code here, to run once:
    while (!Serial && millis() < 4000) {}
    Serial.begin(115200);

    Serial.println(DWT->CTRL);
    Serial.println(DWT->CYCCNT);
    pinMode(LED_BUILTIN, OUTPUT);
    uint32_t core_debug = CoreDebug->DEMCR;
    CoreDebug->DEMCR = core_debug | CoreDebug_DEMCR_TRCENA_Msk;

    uint32_t dwt_ctrl = DWT->CTRL;
    DWT->CTRL = dwt_ctrl | DWT_CTRL_CYCCNTENA_Msk;
    Serial.println(DWT->CTRL);
}

uint8_t loop_count = 0;
uint32_t prev_micros = 0;
uint32_t prev_cycles = 0;

void loop() {
    prev_micros = micros();
    prev_cycles = DWT->CYCCNT;
    delay(250);
    uint32_t cur_micros = micros();
    uint32_t cur_cycles = DWT->CYCCNT;
    uint32_t delta_micros = cur_micros - prev_micros;
    uint32_t delta_cycles = cur_cycles - prev_cycles;
    digitalWrite(LED_BUILTIN, (++loop_count & 1) ? HIGH : LOW);
    Serial.print(cur_micros);
    Serial.print("(");
    Serial.print(delta_micros);
    Serial.print(")");
    Serial.print(cur_cycles);
    Serial.print("(");
    Serial.print(delta_cycles);
    Serial.print(")");
    Serial.print(" : ");
    Serial.println((float)delta_cycles * (1000000.9 / float(delta_micros)), 2);
}

SO far I have only tried this on the M7
Some example output:

6716050(249217)1910070955(467433) : 1875608.09
6966015(249139)1910719345(463386) : 1859951.34
7215979(249167)1911373781(470465) : 1888153.02
7465944(249018)1912030493(470301) : 1888624.21
7715909(249013)1912679795(462187) : 1856077.46
7965874(249083)1913332440(467631) : 1877412.03
8215839(249260)1913985522(470730) : 1888511.69

I will rerun it some at different delay times to make sure I am not getting rollover issues
on the counts...

As anyone played with this stuff? If it works, who knows maybe I will play with SoftwareSerial code. Although will need to bypass things like digitalWrite and the like.

CYCCNT is part of the "Debug, Watchdog, and Trace" (DWT) unit that is part of the Arduino core. I've written a microsecond delay routine using DWT->CYCCNT that I've used on SAMD51 boards (120MHz; which means that the 32bit counter overflows in about 37s.) It should work on other ARMs with the DWT option as well.

I did also write a "dumb, tx-only, SoftwareSerial" that should work on any system that is both fast and implements an accurate delayMicroseconds() function:

1 Like

Thanks, for the fun of it I have hacked up version of Paul's version of SoftwareSerial that I am debugging.

The TX is working, the RX is faulting... Just pulled out hardware debugger.
The code is sort of interesting that Paul did for RX.
He setup a Pin Change interrupt to catch the start bit, at which time on the Teensy,
he started up an IntervalTimer to read in each of the bits, that part appears to be sort of working, but then after receiving all of the bits, it detaches that interrupt and tries to reattach the pinInterrupt, which is faulting...

Instead of IntervalTimer (which is specific to the Teensy code base), I am using a
mbed::Ticker ticker; // calls a callback repeatedly with a timeout

I am also using sort of a variation of my digitalWriteFast code, where at begin time, I convert the pin number into a pointer to the Port and the bitmask, and Set the clear the bits only...

Will post more tomorrow (or so)...