7
\$\begingroup\$

I am following a programming build in Arduino and I came across this code here:

ISR(PCINT2_vect) {
 hall3state = digitalRead(hall3);
 NextStep();
}

ISR(ADC_vect) {
 int x = ADCH;  // read 8 bit value from ADC
 OCR1B = map(x,0,255,1,799);
}

I don't understand how the functionality of this code works. Are these 2 ISR() code snippets functions? If so how does this function get called because there is nowhere else in the code that calls ISR(). Also how is there 2 different functions with the exact same name? If you call ISR() how do you know which one will get called?

I don't need you to explain what the code is doing, I just don't understand how the computer knows when to run these functions because we never call it anywhere else in the code.

If you need to download the entire code you can get it here

\$\endgroup\$
5
  • 1
    \$\begingroup\$ This may also be interesting to you if you want to know how those macros are expanded: stackoverflow.com/questions/3742822/preprocessor-output \$\endgroup\$ Jun 15 at 0:13
  • 2
    \$\begingroup\$ The key here is that those aren't functions. They're actually preprocessor macros. \$\endgroup\$ Jun 15 at 9:03
  • 3
    \$\begingroup\$ Ignoring this particular case (where what you are looking at are macros), should you ever see a function with no return type in really archaic C (not C++) code, the default return type may be int (stackoverflow.com/questions/18421735/…). Ah, those were the days \$\endgroup\$
    – Flydog57
    Jun 15 at 20:29
  • \$\begingroup\$ @Flydog57: If you're feeling nostalgic for how much you can leave out and still have your program work (on at least some implementations), see Tips for golfing in C - e.g. main(a){for(;++a<28;)putchar(95+a);} is an entire program that prints the lower-case alphabet. (Assuming it runs with argc=1) \$\endgroup\$ Jun 16 at 5:07
  • \$\begingroup\$ Nope, no nostalgia for those days. 1/2 the code in Z80 assembly, half in K&R (pre-ANSI) C. Burning EPROMS, debugging with an in-circuit emulator and a printed MAP to get symbols. Nope, those were horse and buggy days. Give me my BMW (or Visual Studio) \$\endgroup\$
    – Flydog57
    Jun 16 at 5:12

2 Answers 2

20
\$\begingroup\$

The functions are interrupt handlers, defined using the ISR(vector, attributes) macro. The macro generates a proper platform-specific function signature, including the return type (usually void).

This macro automatically "wires" the function body to the given interrupt vector. Note that the vector must be spelled correctly: if there's a typo or a wrong name is used, the function will have no effect.

The first and only required argument of the macro is the name of the interrupt vector.

  • PCINT2_vect is the Pin Change Interrupt Request 2 vector.

  • ADC_vect is the ADC Conversion Complete vector.

Those two functions are thus assigned as interrupt handlers for a given interrupt vector. As soon as you enable the interrupt from a given source, those functions will get called when the respective interrupt is asserted.

For a list of interrupt vectors and further details, see the documentation of the <avr/interrupt.h> header.

\$\endgroup\$
3
  • 8
    \$\begingroup\$ Also note that the macro does populate the missing return type information at the front: # define ISR(vector, ...) \ void vector (void) __attribute__ ((__signal__,__INTR_ATTRS)) __VA_ARGS__; nongnu.org/avr-libc/user-manual/interrupt_8h_source.html starting line 125 \$\endgroup\$
    – Bryan
    Jun 14 at 23:39
  • 6
    \$\begingroup\$ Excellent answer! I'll only point out for the OP that the use of ALL CAPS in the source code is a clue: it's a convention for macros, and shouldn't be used for ordinary function names. \$\endgroup\$ Jun 15 at 0:09
  • 1
    \$\begingroup\$ @Trev347 - 2 tricks that might have helped you here - 1: Its a standard idiom in C coding that an all caps identifier is a macro. 2: "ISR" is a very common acronym for interrupt (service) routines. Those have to interface with the OS directly, and every platform has its own trick for doing so. One common use of C macros is of course to hide commonly required tricky code. \$\endgroup\$
    – T.E.D.
    Jun 15 at 20:12
1
\$\begingroup\$

Those are Interrupt Service Routines - they run in response to an input on an I/O pin, or when the ADC has a reading ready. They are not called from your main program.

Look in the Arduino reference material for information on Interrupts to see how they work.

\$\endgroup\$

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.