Electronic – Non-reentrant Functions as Macros for utilities used in both Main and Interrupts

interruptsmacropic

When compiling software with xc8 for a PIC which has functions which are called in both interrupts and in the main function the compiler gives an advisory:

non-reentrant function "foo" appears in multiple call graphs and has been duplicated by the compiler

Although this is not necessarily an issue, I understand from some reading that it is bad practice to call functions from both an interrupt and main.

Does this extend to pre-processor macros?

Most of the functions that I implement and are used in both are simple aliases for some simple maths, for example:

uint16_t timer3_get_value(void)
{
    return (uint16_t) (TMR3H << 8) | TMR3L;
}

Would making this function inline or changing it to a macro make a difference and/or be better practice?

#define TIMER3_GET_VALUE() (uint16_t) (TMR3H << 8) | TMR3L

Best Answer

Like the compiler message tells you, the code is duplicated. This has the very same effect as being inlined, put aside the overhead for call and return. Both versions are independent and can't influence each other.

So it's up to you to choose.

  • Relying on the compiler's capability makes your code less portable. And you get the compiler message which might be disturbing.
  • AFAIK inline just gives the compiler a hint. It does not have to obey it.
  • You best bet would be to use your last idea of making it a macro expression / statement.

    For the latter this is common style:

    #define function_name() do { /* anything it should do */ } while (0)

    so you could use it like a void expression. If you accidentally try to assign it you'll get an error message. Please note the missing semicolon at the end. This will be provided at the place of the usage:

    function_name();