SpenceKonde/ATTinyCore

Compilation failed with Timer0 Interrupt handler

DoubleCouponDay opened this issue · 5 comments

I am using the following sketch with the ATTinyCore Board Manager targeting an ATTiny84A. When I try to compile the sketch I get the following error. If I use the TIM1_OVF_vect to interrupt on timer 1 instead, it compiles.

In the tiny core in this repository, I found a second definition of TIM0_OVF_vect which conflicts with mine, preventing compilation. The tinymodern core does not seem to have this issue.

My question is how can I use the tinymodern core to compile so that I can use timer 0 with an interrupt routine?

#include <Arduino.h>
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#include <avr/interrupt.h>

void setup() {}
void loop() {}
ISR(TIM0_OVF_vect) {}
Linking everything together...
"/usr/bin/avr-gcc" -Wall -Wextra -Os -g -flto -fuse-linker-plugin -Wl,--gc-sections -mmcu=attiny84  -o "/tmp/arduino_build_300293/apd.ino.elf" "/tmp/arduino_build_300293/sketch/apd.ino.cpp.o" "/tmp/arduino_build_300293/core/core.a" "-L/tmp/arduino_build_300293" -lm
wiring.c.o (symbol from plugin): In function `__vector_11':
(.text+0x0): multiple definition of `__vector_11'
/tmp/arduino_build_300293/sketch/apd.ino.cpp.o (symbol from plugin):(.text+0x0): first defined here
collect2: error: ld returned 1 exit status
exit status 1
Error compiling for board ATtiny24/44/84(a) (No bootloader).

Try with Millis()/micros() disabled.

Thank you @hmeijdam , I can confirm that is working. Is there a dependency on timer 0 when using the millis() function?

You can read that here

Worth noting that

  • Both tiny and tinymodern both always use timer0 for millis. This is the same as basically every core for every classic AVR.
  • tinymodern is used in 1.x.x versions of ATTC for the 841, 441, 828, and 1634.
  • tiny is used in 1.x.x for all parts except those four, and for all parts in 2.x.x (and tinymodern is removed)
  • Although tinymodern is for a more "modern" set of parts, the core itself was always more hacky, crude, and buggy. The senseless bifurcation of the core was a consequence of limited knowledge at the time that decisions were being made - the parts contain no essential differences, and reflected the way I gathered support for various parts and combined them into one package. Version 2.0.0 of ATTC will eliminate the "tinymodern" core, bringing the 4 parts that used that (841, 441, 828, 1634) onto the same core that everything else uses, and the features and optimizations present on only one or the other were rolled into the one (which was essentially almost unchanged from "tiny", with the exception of trivialities like pinMode and digitalWrite having to treat the pins slightly differently.
  • The whole tinymodern naming was based on a series of premises dating to the time when those were the 4 most recently released tinyAVR products. At the time all of these premises looked sound
    • That future tinyAVR parts would be similar in behavior to currently available AVRs.
    • That the defining feature separating these newer more modernized AVRs would be that they have the separate PUEx register for the pullups.
    • That there were more differences than I had appreciated between those "final four" and the rest of the classic AVRs such that they required a separate core
  • All of those proved false:
    • Those parts were not the First Four of the new generation, they were the Final Four of the classic tinyAVR.
    • The new parts are most crisply separated from the old by which version of the AVR instruction set they implement - though their peripheral behavior (amongst eachother) is almost identical too, there are a lot of other simple definitions that sort the AVRs into the same groups, and significantly different from that of classic AVRs. This shakes out the AVR chips into these groups:
      • Oldass crap that implements vanilla AVR
      • tinyAVR and some older non-tinyAVR implement AVRe, a superset of AVR that enhances the efficiency of the instruction set dramatically (for any asm-person reading this, it's SBIW, ADIW and MOVW that are the "big deal" The tinyAVRs of this sort are covered by ATTC.
      • megaAVR, which implements AVRe+ - this is AVRe plus the hardware multiply instructions, which you can see as they go from mul to the wierder variants, they started to run out of opcodes to use, so the wierder multiplies only work if the operands are in certain subsets of registers. I think they got as desperate as to have to restrict some to just the SBIW/ADIW working registers (24-31) (Support for Arduino for these is covered almost entirely by the various mcudude cores)
      • xMega, which implements AVRxm - this is like AVRe+, but it also added 4 load-and-store single op commands. These didn't turn out to be a big success it looks like (that they only worked on SRAM, apparently excluding the extended I/O space, which is the place where I'd kill to have XCH work. None of the others were very useful. These were a commercial failure it would appear, and it also looks like Atmel bet heavily on their not being so. It certainly didn't help put Atmel up for sale, that's for sure.
      • The Final Four were clearly backed up against a hard deadline, because the last two of them were rushed out with bad bugs that they never fixed (828 was supposed to have a differential ADC for all those 28 analog inputs, but at the last minute, all reference to it was scrubbed (not very well) from the datasheet, and both of them have a "lame" pin that pulls down with a few mA of current if the WDT isn't enabled. I think there was a hard deadline after which all the engineers were pulled onto the project to make....
      • The actual modern AVRs are all AVRs released since 2016 or so - the tiny 0, 1, and 2 series (these are distinguished by the tens digit being a 0, 1 or 2, and the 1's digit being a 2 (8-pin) 4 (14 pin), 6 (20 pin) or 7 (24-pin), the mega0 (same deal, only prefixed by ATmega. In all cases the hundreds and thousands digit, if any indicated the size of the flash), and all the more recent parts named as AVRWWXYZZ, where WW is the flash size in kb, X is D or E indicating the base level of features, Y is another capital letter indicating which family of parts within that product line it is. These all implement AVRxt - which is a hybrid of AVRe+ and AVRxm, with improved instruction timing for many instructions as well.

So had my crystal ball been working, obviously I wouldn't have named the second subcore in this core tinymodern because the next part families released would instead herald the coming of what I now call modern AVRs, (Microchip who as you know bought Atmel in the mid 2010's, has not provided any such official term, nor a converse term to call non-modern AVRs; I call them Classic AVRs). And if I'd had more of a clue I'd have not needed a second core at all, but I didn't know what I was doing way back then, other than that I wanted to make an ATtiny841 work on arduino because I wanted 2 serial ports and Software Serial Sucks.

The big push in addition to consistency between parts (in the form of all pins_arduino.h files being completely overhauled) with 2.0.0 is eliminating the "tinymodern" core which was nothing but trouble - the two had to be kept in sync, that never happened, and problems resulted.

Thanks @SpenceKonde for the in-depth answer.