4

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?
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Mike Thielvoldt
  • 181
  • 1
  • 11
  • 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 Mar 28 '15 at 00:36
  • 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 Mar 28 '15 at 00:50
  • Well, you caught me. 7us is not strictly unacceptable yet. I'm building an [ECU for a van](https://hackaday.io/project/4622-ecuality1) 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 Mar 28 '15 at 00:57
  • 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 Mar 28 '15 at 01:20
  • Can you make your own interrupt a higher priority? http://courses.cs.washington.edu/courses/csep567/10wi/lectures/Lecture7.pdf – Weather Vane Mar 28 '15 at 11:19
  • I believe I can re-order the priority, but "priority" only controls which interrupt is serviced if more than one are pending when the global interrupt enable bit is reset. The issue is that the global interrupt enable bit is cleared on entry to any ISR by default. So without being able to change the actual ISR, I just have to wait for that other ISR to return before the global enable bit lets my ISR take over. – Mike Thielvoldt Mar 28 '15 at 20:46
  • You can [disable the Arduino Timer0 interrupt handler (and even replace it with your own) by unintrusively manipulating the file `wiring.c`](https://stackoverflow.com/questions/46573550/atmel-arduino-isrtimer0-ovf-vect-wont-compile-first-defined-in-vector/48779546#48779546) (folder `\hardware\arduino\avr\cores\arduino` in the installation). – Peter Mortensen Feb 15 '18 at 23:51

1 Answers1

2

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
}
TRiNE
  • 5,020
  • 1
  • 29
  • 42
  • Agreed. I had no trouble [replacing the Timer0 interrupt routine with my own](https://stackoverflow.com/questions/46573550/atmel-arduino-isrtimer0-ovf-vect-wont-compile-first-defined-in-vector/48779546#48779546) (because I needed to use Timer0 for my own purposes) - serial worked without any problems. – Peter Mortensen May 26 '19 at 13:26