Arduino, ATtiny85, and Timers

April 29, 2018 at 2:57 pm (computers) (, )

I’m still playing around with using the ATtiny85 as the basis for a synthesizer, using a range of code and circuits from the Internet, but had an irritating problem today with some open code.  The author describes complete build instructions for their code and circuit for v1.5.7 of the Arduino environment and the arduino-tiny library, which as far as I can see was last updated in 2013 from its google code repository.

But I have v1.8.5 and the now easy to use, built-in support for the ATtiny85 from David Mellis (https://github.com/damellis/attiny).

So when it comes to build it on my system I get the following error:

wiring.c.o (symbol from plugin): In function `delayMicroseconds':

(.text+0x0): multiple definition of `__vector_5'

Which is obviously a linker error, but it has proven quite difficult to find a detailed hint as to what the actual problem is.  It says that it has redefined in my .ino file, but wasn’t immediately obvious this related to interrupt routines (although the word vector should have been a clue I guess).

Well it turns out that this is a problem you get if you attempt to defined an interrupt service routine twice.  The code in question had defined

ISR(TIMER0_OVF_vect)

And in any modern Arduino core timer 0 is used for the millisecond timer, as defined in hardware/arduino/avr/cores/arduino/wiring.c.  This is indeed vector 5 (see http://ee-classes.usc.edu/ee459/library/documents/avr_intr_vectors/).  This is defined in wiring.c, but not directly related to the delayMicroseconds function (oh the joys of tracing C linker errors).

I’m skipping over the part where I was attempting to work out where the actual source code being built was stored – not in <program files>\Arduino; not in my own Arduino source area; no it was finding mention of <user>\AppData\Local\Arduino15 that found any ATtiny support in my installation at all.

There seems quite a lot of confusion online (at least from the searching I was doing) about timers on the ATtiny85 and the Arduino environment.  It looks like an earlier version of the Arduino core (although not obviously in the v1.5.7 suggested by the author of the code I was using, so that is still a puzzle) had a method for changing the timer usage for different microcontrollers.

The arduino-tiny library uses a core_build_options.h options file and uses it to set the following:

#if defined( __AVR_ATtiny25__ ) || defined( __AVR_ATtiny45__ ) || defined( __AVR_ATtiny85__ )
#define __AVR_ATtinyX5__
#endif

#if defined( __AVR_ATtinyX5__ )

/*
 For various reasons, Timer 1 is a better choice for the millis timer on the
 '85 processor.
*/
#define TIMER_TO_USE_FOR_MILLIS 1

However, this isn’t in the latest builds of the core or in the version of the ATtiny core support I’m using, which doesn’t seem to have the option to change which timer is used for the delay functions.  In fact, I couldn’t quite pin down when the use of this header file disappeared from the Arduino builds, but to be honest I didn’t spend ages looking.

The code I’m trying to use needs the use of both timers, and as there are only two timers on the attiny85, hence the clash.  I’m not totally clear why it builds when the delay timer is swapped to use timer1 (as in the older arduino-tiny core), but I guess the code isn’t hanging an ISR of the other timer.

Interestingly in other code by the same author, does build ok, but in that case, even though it is installing an ISR for timer0, it is using a different vector, so it doesn’t seem to clash:

ISR(TIMER0_COMPA_vect)

So whilst you can completely mess up the functioning of the timers in your own sketch, by changing the control registers and so on directly, I haven’t found a way to clear and attach a new ISR to the interrupt.

I need to dig around a bit more now into the internals of the ATtiny timers to see how the code might be modified to support timer 1 instead of timer 0, but that will have to be a job for another day now.

Some possible options might include forgoing the use of ‘setup’ and ‘loop’ in the sketch; integrating it better alongside its use with delay; attempting to port over from triggering on overflow to triggering on compare; or I may end up trying to reverse the timer usage in the sketch (but I read somewhere that the two ATtiny85 timers are quite different, so that might not be possible).   I may end up with a special ‘hacked’ core board definition to re-specify the use of timer1 rather than 0 as per the older library, but that would be a bit of a mess…

Anyway, the upshot of all this is that this took quite a lot of untangling and googling and following dead-ends, so if you know of a definitive resource or document that details the history of ATtiny85 support within Arduino and when this changed, I’d like to hear about it!

Update: In my case it turned out that I was pretty much able to replace the use of the Timer 0 overflow interrupt with the Timer 0 compare A interrupt and get largely the same thing.  I don’t know if the two use of the different timers needs to be swapped though, but as far as I can tell right now, changing interrupt does remove the clash.

So in my case, I did this:

#ifdef ORIGINAL_CODE_
 TIMSK = (1 << TOIE0); // Interrupt on overflow
#else
 // Set compare value to same that would trigger overflow
 // of the 8-bit counter (pretty much)
 OCR0A = 0xff;
 TIMSK = (1 << OCIE0A); // Interrupt on compare with OCR0A
#endif

and then later on, when defining the ISR:

#ifdef ORIGINAL_CODE_
ISR(TIMER0_OVF_vect) {
#else
ISR(TIMER0_COMPA_vect) {
#endif

Of course there may still be other side effects, but I need to dig into the details to see.

Kevin

Advertisements

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: