1

I know that I can handle a single rollover with subtraction:

if (micros() - lastTime > period) {
  lastTime = micros();
  ...
}

But how it can be handled if this is not true or it is not checked for more than 70 minutes (without using uint64_t)?

Vasil Kalchev
  • 285
  • 1
  • 2
  • 12
  • What is the objection to using `millis()` if you are timing rather long periods? – Nick Gammon Apr 03 '18 at 04:12
  • I'm using my implementation of micros() and I don't want to implement millis() because it makes the ISR bigger. Also the precision. – Vasil Kalchev Apr 03 '18 at 04:28
  • So just to be clear, this is **your** version of micros you are asking us about? How about posting the code to it? – Nick Gammon Apr 03 '18 at 04:58
  • It's the same as Arduino's version except that in `ISR(TIMER0_OVF_vect)` there is a single variable increment. The code needs to run with as little interruptions as possible and I want to be able to run something with irregular long intervals. – Vasil Kalchev Apr 03 '18 at 05:27
  • It's the same as the Arduino version, except it's completely different, is that it? I gather this is top-secret code. – Nick Gammon Apr 03 '18 at 06:46
  • It is the same, and it has nothing to do with the question: ` #define clockCyclesPerMicrosecond() ( F_CPU / 1000000L ) volatile uint32_t timer0OverflowCount = 0; ISR(TIMER0_OVF_vect) { ++timer0OverflowCount; } uint32_t us() { uint32_t m; uint8_t t; uint8_t oldSREG = SREG; cli(); m = timer0OverflowCount; t = TCNT0; if (((TIFR0 & (1 << TOV0)) && (t < 255))) ++m; SREG = oldSREG; return ((m << 8) + t) * (64 / clockCyclesPerMicrosecond()); } ` – Vasil Kalchev Apr 03 '18 at 07:06
  • What exactly is the problem? Do you want `period` to be more than 70 minutes? – Gerben Apr 03 '18 at 09:30

1 Answers1

1

If you want to measure times longer than 70 minutes with micros(), you will have to use uint64_t, and there is nothing wrong with that.

The code needs to run with as little interruptions as possible [...]

You don't need to do the 64-bit arithmetic within the ISR. You could very well implement an interrupt-driven 32-bit version, and then extend it to 64 bits in non-interrupt context. Example:

// Your ISR-based implementation.
uint32_t micros32();

// Extend to 64 bits.
uint64_t micros64() {
    static uint32_t low32, high32;
    uint32_t new_low32 = micros32();
    if (new_low32 < low32) high32++;
    low32 = new_low32;
    return (uint64_t) high32 << 32 | low32;
}

This should work as long as you call micros64() often enough. Presumably, you will have something like if (micros64() - lastTime > period) { ... } within your loop, so this should be no issue as long as you never block your loop.

Actually, you can push this idea even further. If you can guarantee that micros64() will be called at least once every 65.5 ms, then you could have your ISR increment only a 16-bit counter.

Edgar Bonet
  • 39,449
  • 4
  • 36
  • 72