Controlling interrupts, Smp support, Interrupt routing – Comtrol eCos User Manual
Page 90

Interrupt Handling
The call to
cyg_interrupt_create
simply fills in a kernel data structure. A typical next step is to call
cyg_interrupt_attach
using the handle returned by the create operation. This makes it possible to have
several different interrupt handlers for a given vector, attaching whichever one is currently appropriate.
Replacing an interrupt handler requires a call to
cyg_interrupt_detach
, followed by another call to
cyg_interrupt_attach
for the replacement handler.
cyg_interrupt_delete
can be used if an interrupt
handler is no longer required.
Some hardware may allow for further control over specific interrupts, for example whether an interrupt is level or
edge triggered. Any such hardware functionality can be accessed using
cyg_interrupt_configure
: the
level
argument selects between level versus edge triggered; the
up
argument selects between high and low level, or
between rising and falling edges.
Usually interrupt handlers are created, attached and configured during system initialization, while global interrupts
are still disabled. On most hardware it will also be necessary to call
cyg_interrupt_unmask
, since the sensible
default for interrupt masking is to ignore any interrupts for which no handler is installed.
Controlling Interrupts
eCos provides two ways of controlling whether or not interrupts happen. It is possible to disable and reenable all
interrupts globally, using
cyg_interrupt_disable
and
cyg_interrupt_enable
. Typically this works by ma-
nipulating state inside the cpu itself, for example setting a flag in a status register or executing special instructions.
Alternatively it may be possible to mask a specific interrupt source by writing to one or to several interrupt mask
registers. Hardware-specific documentation should be consulted for the exact details of how interrupt masking
works, because a full implementation is not possible on all hardware.
The primary use for these functions is to allow data to be shared between ISRs and other code such as DSRs or
threads. If both a thread and an ISR need to manipulate either a data structure or the hardware itself, there is a
possible conflict if an interrupt happens just when the thread is doing such manipulation. Problems can be avoided
by the thread either disabling or masking interrupts during the critical region. If this critical region requires only
a few instructions then usually it is more efficient to disable interrupts. For larger critical regions it may be more
appropriate to use interrupt masking, allowing other interrupts to occur. There are other uses for interrupt masking.
For example if a device is not currently being used by the application then it may be desirable to mask all interrupts
generated by that device.
There
are
two
functions
for
masking
a
specific
interrupt
source,
cyg_interrupt_mask
and
cyg_interrupt_mask_intunsafe
. On typical hardware masking an interrupt is not an atomic operation,
so if two threads were to perform interrupt masking operations at the same time there could be problems.
cyg_interrupt_mask
disables all interrupts while it manipulates the interrupt mask. In situations where
interrupts are already know to be disabled,
cyg_interrupt_mask_intunsafe
can be used instead. There are
matching functions
cyg_interrupt_unmask
and
cyg_interrupt_unmask_intsafe
.
SMP Support
On SMP systems the kernel provides an additional two functions related to interrupt handling.
cyg_interrupt_set_cpu
specifies that a particular hardware interrupt should always be handled on one specific
processor in the system. In other words when the interrupt triggers it is only that processor which detects it, and it
is only on that processor that the VSR and ISR will run. If a DSR is requested then it will also run on the same
CPU. The function
cyg_interrupt_get_cpu
can be used to find out which interrupts are handled on which
processor.
90