0

First time arduino programmer here...however I have programmed the TI MSP430 in the past...

I am trying to figure out how to configure internal Interrupt Vectors on this Arduino Uno.

In the Arduino IDE, I am skeptical about writing lines of code like

ISR(TIMER1_CAPT_vect) {
    Serial.Print("Entered Capture Vector");
}

Because it doesn't appear to matter what I type inside ISR(), for instance I can write ISR(GibERisH) { }

And it still compiles and uploads to the arduino. What?! Also how could Arduino IDE know what the heck TIMER1_CAPT_vect is without having the library?

I found a list of interrupt vector names here: http://www.nongnu.org/avr-libc/user-manual/group__avr__interrupts.html

But I can not find documentation ANYWHERE ELSE on what to call these interrupt vectors.

Should I abandon the Arduino IDE and go with the Atmel Studio 6.2 (There is a juicy looking arduino plug-in...)? I need advanced control of the guts of this processor, and there is zero documentation about how to do this anywhere on the internet.


EDIT: I realized my problem was I was looking for documentation for the atmega16U2 (that does something else on the board), not the atmega328P.

migrated from electronics.stackexchange.com Jun 4 '15 at 22:27

This question came from our site for electronics and electrical engineering professionals, students, and enthusiasts.

3

The vector names are all defined within the header files for the main chip in the compiler. The IDE doesn't need to know anything about that kind of thing - that's all up to the compiler.

Look for the files "lib/avr/include/avr/io*.h within the compiler in your chosen IDE. In there are all the chips and all their definitions.

For instance, the ATMega328P definition (iom328p.h) has this list:

#define INT0_vect         _VECTOR(1)   /* External Interrupt Request 0 */
#define INT1_vect         _VECTOR(2)   /* External Interrupt Request 1 */
#define PCINT0_vect       _VECTOR(3)   /* Pin Change Interrupt Request 0 */
#define PCINT1_vect       _VECTOR(4)   /* Pin Change Interrupt Request 0 */
#define PCINT2_vect       _VECTOR(5)   /* Pin Change Interrupt Request 1 */
#define WDT_vect          _VECTOR(6)   /* Watchdog Time-out Interrupt */
#define TIMER2_COMPA_vect _VECTOR(7)   /* Timer/Counter2 Compare Match A */
#define TIMER2_COMPB_vect _VECTOR(8)   /* Timer/Counter2 Compare Match A */
#define TIMER2_OVF_vect   _VECTOR(9)   /* Timer/Counter2 Overflow */
#define TIMER1_CAPT_vect  _VECTOR(10)  /* Timer/Counter1 Capture Event */
#define TIMER1_COMPA_vect _VECTOR(11)  /* Timer/Counter1 Compare Match A */
#define TIMER1_COMPB_vect _VECTOR(12)  /* Timer/Counter1 Compare Match B */
#define TIMER1_OVF_vect   _VECTOR(13)  /* Timer/Counter1 Overflow */
#define TIMER0_COMPA_vect _VECTOR(14)  /* TimerCounter0 Compare Match A */
#define TIMER0_COMPB_vect _VECTOR(15)  /* TimerCounter0 Compare Match B */
#define TIMER0_OVF_vect   _VECTOR(16)  /* Timer/Couner0 Overflow */
#define SPI_STC_vect      _VECTOR(17)  /* SPI Serial Transfer Complete */
#define USART_RX_vect     _VECTOR(18)  /* USART Rx Complete */
#define USART_UDRE_vect   _VECTOR(19)  /* USART, Data Register Empty */
#define USART_TX_vect     _VECTOR(20)  /* USART Tx Complete */
#define ADC_vect          _VECTOR(21)  /* ADC Conversion Complete */
#define EE_READY_vect     _VECTOR(22)  /* EEPROM Ready */
#define ANALOG_COMP_vect  _VECTOR(23)  /* Analog Comparator */
#define TWI_vect          _VECTOR(24)  /* Two-wire Serial Interface */
#define SPM_READY_vect    _VECTOR(25)  /* Store Program Memory Read */

Further, _ISR() is just a macro. It creates a suitable function prototype for your function, and if that happens to include a valid vector then it becomes an ISR.

#  define ISR(vector, ...)            \
    extern "C" void vector (void) __attribute__ ((signal,__INTR_ATTRS)) __VA_ARGS__; \
    void vector (void)

That is defined in "avr/interrupt.h" in the compiler's include files. With your gibberish you'd end up with:

extern "C" void GibERisH (void) __attribute__ ((signal,__INTR_ATTRS));
void GibERisH (void) {
    // something here
}

With a real vector you'd get the more meaningful:

extern "C" void _VECTOR(7) (void) __attribute__ ((signal,__INTR_ATTRS));
void _VECTOR(7) (void) {
    // something here
}

Of course, _VECTOR() itself is a macro:

lib/avr/include/avr/sfr_defs.h:#define _VECTOR(N) __vector_ ## N

So that further expands out to:

extern "C" void __vector_7 (void) __attribute__ ((signal,__INTR_ATTRS));
void __vector_7 (void) {
    // something here
}

And magically, that new function name of __vector_7 is directly referenced from the standard vector handling code in the startup library crt of the AVR compiler.

  • Thank Majenko. Also the documentation actually does have the names of the interrupts, but looking at the header makes it crystal clear. Thanks for answering. – OrangeSherbet Jun 4 '15 at 23:49
0
ISR(TIMER1_CAPT_vect) {
    Serial.Print("Entered Capture Vector");
}

Rule #1. Don't do serial prints inside an ISR. Doing that will likely hang the sketch.

Because it doesn't appear to matter what I type inside ISR(), for instance I can write ISR(GibERisH) { }

Yes you can do that. It just degrades into some function that is never called. The way it is organized with all the defines, any non-valid ISR name effectively creates a non-ISR function, which is therefore ignored. Even getting the capitalization wrong can cause this.

I need advanced control of the guts of this processor, and there is zero documentation about how to do this anywhere on the internet.

There is a considerable amount of detail on my site: http://www.gammon.com.au/interrupts

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.