![]() |
DEFINE_INT_HANDLER | Language Extension |
intr.h |
Defines an interrupt handler function.
DEFINE_INT_HANDLER is a language extension macro which is used for defining interrupt handlers. The syntax is similar to function definition:
DEFINE_INT_HANDLER (HandlerName) { // The body of the handler... }Note, however, that DEFINE_INT_HANDLER does not define a standard function: it constructs an object named HandlerName of INT_HANDLER type, which is initialized to point to the handler body (implemented internally as a function, but unaccessable directly to the rest of the program). So, you can not call the interrupt handler using a standard call construction like
HandlerName ();Such behaviour is implemented due to safety reasons: interrupt handlers are not supposed to be executed directly. If you need to call the interrupt handler anyway, you can use ExecuteHandler function. Here is an example of the program which installs the new (user-defined) interrupt handler for auto interrupt 5 (the programable timer interrupt), in which the old (default) handler is called as well (called "Interrupt Handler"):
// Interrupt handler incrementing a counter #define USE_TI89 // Compile for TI-89 #define USE_TI92PLUS // Compile for TI-92 Plus #define USE_V200 // Compile for V200 #define OPTIMIZE_ROM_CALLS // Use ROM Call Optimization #define MIN_AMS 100 // Compile for AMS 1.00 or higher #define SAVE_SCREEN // Save/Restore LCD Contents #include <tigcclib.h> // Include All Header Files INT_HANDLER OldInt5 = NULL; volatile int Counter = 0; DEFINE_INT_HANDLER(MyInt5) { Counter++; ExecuteHandler (OldInt5); } void _main(void) { OldInt5 = GetIntVec (AUTO_INT_5); SetIntVec (AUTO_INT_5, MyInt5); while (!kbhit()) printf_xy (50, 50, "Counter = %d ", Counter); SetIntVec (AUTO_INT_5, OldInt5); GKeyFlush (); }The only legal usage of INT_HANDLER objects is to be passed as arguments to the functions SetIntVec or ExecuteHandler.
volatile
.
In fact, any global variable which may be changed by the
interrupt handler should be declared as volatile
, especially if it is accessed
from the other parts of the program (i.e. out of the interrupt handler). This is necessary
to prevent various optimizations which may be fooled by the fact
that the variable may be changed in a way which is completely unpredictable from the aspect
of the normal program flow. For example, various optimizations may force keeping the variable
content in a register, so if the variable is changed asynchronously, the compiler will not
know anything about it. volatile
will prevent keeping the variable in a
register, so it will be reloaded from the memory on each access. The example given above
will still work if you omit the volatile
keyword, but more complicated programs
will probably not work correctly without it.