3
votes

Background:

I need very repeatable interrupt execution timing for my own ISR in the Arduino environment. The Timer0 overflow interrupt is used by the Arduino core library to provide millis(). Occasionally, the condition that triggers my interrupt is met while the Timer0 overflow interrupt is being executed. By default, the AVR does not allow one interrupt to "interrupt" another. See this Nested interrupts question.

The Timer0 ISR blocks my ISR from executing until it completes. This delay can take up to 7 µs, which is unacceptable in my application. (I know!)

I do not require millis() in my application, so I tried disabling the Timer0 overflow interrupt like so inside void setup():

TIMSK0 = 0;

Gotcha: Unfortunately, that breaks the hardware serial functions. I have looked through the core library source, but I don't understand how the hardware serial methods depend on Timer 0.

Constraints: I want my sketch to compile and work with a standard Arduino distribution, so I only have control of what's in my sketch directory (not the Arduino directory) and Arduino sketches hide "includes" from you, so I'm not sure I can avoid the "HardwareSerial.h" inclusion.

Exact Question:

  1. How does the Serial class depend on Timer0?
  2. Is there a way to make calls to the "Serial" class work again without modifying the core libraries?
  3. In general, can I re-define methods of (or the whole of) a class that's defined elsewhere?
1
I'm not sure what the answer is, but I'm interested to know what the application is where a 7us delay causes problems???DigitalNinja
I'm thinking you could probably poll for bytes on the USART instead of relying on an interrupt if you still need the serial communication. That way you could do it when your critical ISR isn't running, but I've never worked with Arduino before so I'm not sure what you're limited to in a sketch.DigitalNinja
Well, you caught me. 7us is not strictly unacceptable yet. I'm building an ECU for a van This problem is currently only adding about .3% error to the system, but indicates that I am at the mercy of someone else's code run-time being tight. I'd rather have control of that than hope it stays good enough.Mike Thielvoldt
I'm familiar with how to implement serial functions using polling, but can I write my own routines that share the same names as what's already included in the core? I want another developer to be able to use Serial.println("hey"); verbatim.Mike Thielvoldt
Can you make your own interrupt a higher priority? courses.cs.washington.edu/courses/csep567/10wi/lectures/…Weather Vane

1 Answers

1
votes

Serial works though you disabled Timer 0. This simple experiment concludes that.

#include "avr/pgmspace.h"
#include "avr/io.h"

#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))


void setup() {
  Serial.begin(9600);
  cbi (TIMSK0, TOIE0); // disable Timer0 !!! delay() is now not available
}

void loop() {
  if (Serial.available()){
    Serial.write(Serial.read());
  }
  delay(1000);              // this is not working since Timer 0 disabled
}