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

Page 90

Advertising
background image

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

Advertising