Working With Interrupts
Thanks to the Plus1 SoC's PinMux capability, nearly any line of the Size 3 Linux Tibbo Project PCB (LTPP3), Gen. 2 can work as an interrupt. To enable a particular interrupt line, select it using the io.intnum property, disable the line with the io.enabled property, designate it as an interrupt via io.intnum, optionally set the edge with the io.intedge property, and then enable the interrupt with io.intenabled:
io.num = PL_IO_NUM_11; // Set the I/O line to 11
io.enabled = NO; // Set the I/O line as an input
io.intnum = PL_INT_NUM_7; // Set the interrupt number to 7
io.intedge = INT_EDGE_BOTH; // Set the interrupt edge to BOTH
io.intenabled = YES; // Enable the interrupt
Event Handlers
Once the line has been enabled, a change in this line's state will generate the on_io_int and on_io_int_line events. You do not need to use both event handlers — in fact, it's preferable that you pick just one. Declaring both event handlers will result in multiple events being added to the event queue when an interrupt is generated and there are no previous interrupt events in the queue.
The on_io_int Event
The linestate argument of the on_io_int event is bit-encoded: Each bit of the value represents one interrupt line. For PL_INT_NUM_0, the corresponding bit is bit 0, for PL_INT_NUM_1 it is bit 1, and so on. A particular bit of the linestate argument is set when a state change (from LOW to HIGH or from HIGH to LOW) has been detected on the related interrupt line. The event handler for the on_io_int event can then determine what triggered the interrupt (see the example below).
To ensure compatibility with applications developed for TiOS-based platforms, only one on_io_int event can be added to the event queue at a time.
The on_io_int_line Event
The on_io_int_line event has three arguments:
- ionum — The I/O line number on which the interrupt was generated (see the pl_io_num enum)
- intnum — The interrupt line number on which the interrupt was generated (see the pl_int_num enum)
- edge — The edge on which the interrupt was generated (see the pl_int_edge enum)
Providing both the I/O and interrupt line numbers facilitates interrupt identification and handling. The event handler for the on_io_int_line event can then determine what triggered the interrupt (see the example below).
An on_io_int_line event will be added to the event queue sequentially for every interrupt generated.
Example
// Declare the on_io_int event handler
void on_io_int(byte linestate) {
// Print the value of the linestate argument
sys.debugprintline("on_io_int linestate: " + str(linestate));
}
// Declare the on_io_int_line event handler
void on_io_int_line(pl_io_num ionum, pl_int_num intnum, pl_int_edge edge) {
// Print the value of the ionum, intnum, and edge arguments
sys.debugprintline("on_io_int_line ionum: %d intnum: %d edge: %d", ionum, intnum, edge;
}
Which would give you this output:
on_io_int linestate: 128
on_io_int_line ionum: 11 intnum: 7 edge: 1
Please note that the word "interrupt" is used here in a somewhat loose sense. On traditional microcontrollers, an interrupt line status change causes a near-instantaneous pause to the execution of the main code and a jump to an "interrupt routine." Hence, the term "interrupt" — the execution of the main code gets interrupted.
With the io. object, the interrupt line state change does not disrupt the execution of any event handler or trigger the reordering of pending events in the event queue. The on_io_int and on_io_int_line events are added to the end of the event queue and are not handled until all earlier events are processed. Therefore, nothing is actually interrupted. Note that there is also no guaranteed interrupt response speed here — the time between line state change detection and the execution of the on_io_int and on_io_int_line event handlers depends on the number of prior events waiting in the queue and, hence, cannot be predetermined with any certainty.
Bottom line: The "interrupts" of the io. object should be viewed as a more convenient alternative to the programmatic polling of I/O lines.
Interrupt line names, such as PL_INT_NUM_0, are defined by the pl_int_num enum.