'Arduino - need reassign Timer 0 overflow (TIMER0_OVF_vect) to different ISR - how?
On a generic Arduino (ATMEGA386P) -based application, I need Timer 0's overflow interrupt (normally goes to TIMER0_OVF_vect) to point to my own code, not the existing Arduino code. I realize this will cause the Arduino runtime functions dependent on the normally-functioning 1 kHz interval to be unusable. I am working within an existing Arduino-based application and cannot readily move out of the Arduino environment (example, to AVR-GCC) as there are some other Arduino dependencies I need to retain. I cannot harness the other timers (Timer 1 or Timer 2) as they are in use for other purposes.
My question is this - how do I (or can I) reconfigure Timer 0 so that it's Overflow interrupt vector points to my own code's ISR entry point?
Thank you.
ADDING INFORMATION 13 DEC 2021 per amike comment 10 Dec 2021
I created ISR(TIMER0_OVF_vect) (that I would use as a substitute for the one present in wiring.c)
ISR(TIMER0_OVF_vect)
{
// MY SUBSTITUTE CODE WILL GO HERE
}
While the code appears to get through the compiler, it fails during linking with the following error message (from the Arduino IDE
wiring.c.o (symbol from plugin): In function __vector_16': (.text+0x0): multiple definition of
__vector_16'
sketch\MYTESTPROGRAM.ino.cpp.o (symbol from plugin):(.text+0x0): first defined here
collect2.exe: error: ld returned 1 exit status
exit status 1
Error compiling for board Arduino Uno
This problem is a show-stopper for a larger project I'm working on, so I'd be very grateful for any further advice on whether I can replace the interrupt service routine (without altering or recompiling the Arduino libraries.)
Thanks again
Solution 1:[1]
This topic is treated in arduino.cc.
Nevertheless, I am using a workaround to obtain the same result. This was tested on an Arduino Micro with ATmega32U4 but should be straight-forward to translate to your chip.
Instead of using the timer0 overflow whose ISR routine is already defined by Arduino, I am using the output compare register B and set it to OCR0B = 0xFF
. This will make the Output Compare Match B Interrupt to fire on overflow of timer0.
To avoid any interference, you should disable the TOIE0 bit in TIMSK0 so Arduino's ISR(TIMER0_OVF_vect) is never executed. Instead you set the OCIE0B bit:
TIMSK0 = (1 << OCIE0B); // Disables TOIE0 and enables OCIE0B
Your code can then be exectued within the interrupt
ISR(TIMER0_COMPB_vect)
{
// Your code
}
To give the whole operation some meaning, you'd also want to change the clocking in TCCR0B
register by setting the CS02:0 bits as required.
Obviously, you wont be able to use the arduino-native millis()
/ micros()
/ delay()
functionality. You could also use the output compare register A instead, but I like to keep the option of defining OCR0A
as TOP for the counter, thus using B.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | AVRepublic |