diff -r 578be2adaf3e -r 307f4279f433 Adaptation/GUID-76A30EC4-4B99-5471-9E80-F853C91485BC.dita --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Adaptation/GUID-76A30EC4-4B99-5471-9E80-F853C91485BC.dita Fri Oct 15 14:32:18 2010 +0100 @@ -0,0 +1,198 @@ + + + + + +Interrupt DispatcherThe ASSP/Variant part of the base port must implement an +interrupt dispatcher to manage interrupts. +

An interrupt source is a hardware device or software action that +can force the CPU to suspend normal execution, enter interrupt handling +state and jump to a section of code called an interrupt handler.

+

Typically, a number of interrupt sources are monitored by an interrupt +controller. This is hardware that generates a single interrupt notification +to the CPU, and provides information about which interrupts are pending, +i.e. which interrupts require action to be taken.

+
ISR

An interrupt service routine, or ISR, is code that deals with +a pending interrupt. The Symbian platform kernel responds to an interrupt +notification by calling an ISR for each pending interrupt. The process +of calling ISRs is called interrupt dispatch.

The ISR is a +single bare function. It is not a class member.

Each ISR takes +a single 32-bit parameter that is, typically, a pointer to an owning +class, although it can be any value that is appropriate. The parameter +is defined as a TAny * type, so a cast is almost +always necessary.

ISRs are usually kept in an ISR table.

+
Interrupt +ID

An interrupt source is identified by number, defined +as a TInt type. Typically, the ASSP layer defines +this number for each interrupt in a header file and exports it so +that it can be included and used by device drivers.

Where +the ASSP layer is split into a common layer and a variant (device +specific) layer, then the variant layer may also define its own set +of interrupt IDs.

This number is usually referred to as the +interrupt ID.

+
Binding +and unbinding

Only one ISR can be associated with each +possible interrupt source. Making this association is known as binding. +ISRs can be bound and unbound during normal operation, but only one +ISR can be bound to an interrupt source at any one time.

A +device driver binds an ISR by calling Interrupt::Bind(), passing the interrupt source ID; similarly, the device driver can +unbind the ISR by calling Interrupt::Unbind(), +also passing the interrupt ID.

+
Dispatching +interrupts

At its simplest, this is the process of deciding +which interrupts are pending and calling the ISR for each.

The following pseudo code shows the general principle:

+ { + FOREVER + { + Get next pending interrupt; + if None + { + return; + } + call ISR for the pending interrupt; + } + } +

In practice the dispatcher may have to do some more +work to communicate with the interrupt controller hardware.

+
Chained +interrupts

A system may have multiple interrupt controllers +to handle a large number of interrupt sources. These are usually prioritised +by connecting the interrupt output of a lower-priority controller +to an interrupt input of a higher-priority controller. This is called +chaining.

+Chained interrupts + +

An interrupt from a lower priority controller will appear +as an interrupt on the highest-priority controller.

When the +interrupt dispatcher of the higher-priority controller detects that +it is the chained interrupt that is pending, the usual way of dealing +with this is to run a secondary dispatcher to determine which interrupt +on the chained controller is pending.

There may be further +levels of chaining before the true source of the interrupt has been +identified.

+
Multiple +interrupt sources and pseudo interrupt sources

It is possible +that a single input to an interrupt controller is shared by several +interrupt sources.

+Multiple interrupt sources + +

It appears necessary to bind multiple ISRs to the same interrupt. +However, this is not possible. There are two ways of dealing with +this:

    +
  • Maintain a list +of all ISRs that are bound to this single interrupt source, and call +all the ISRs in the list when the interrupt is dispatched. This is +most conveniently implemented by binding a single ISR to the interrupt, +which then calls all the real ISRs bound to this interrupt

  • +
  • Create pseudo +interrupts. These are extra interrupt IDs that do not exist in the +interrupt controller, but represent each of the interrupt sources +connected to the single shared interrupt source. An ISR can then be +bound to each pseudo interrupt. The interrupt dispatcher can then +determine which of the sources are actually signalling and call the +appropriate ISR via that pseudo interrupt ID. This is effectively +an implementation of a chained interrupt, and assumes that the interrupt dispatcher +can identify which of the sources is signalling.

  • +
+
Interrupts +in the split ASSP/Variant Configuration

When a common ASSP +extension is used, a device may have additional peripherals external +to the ASSP, and there needs to be a way of allowing extra interrupt +binding and dispatch functions to be added later by the variant layer. +This must be handled by the port as Symbian platform does not provide +any additional API to support this.

Device drivers should +be able to use the Interrupt class functions without +having to know where the interrupt is actually implemented. This implies +that all requests should go to the core implementation of functions +like Interrupt::Bind(), Interrupt::Enable() etc.

To enable the core implementation of these functions +to decide whether an interrupt ID refers to a core interrupt or device +specific interrupt, a common technique is to "tag" the interrupt ID. +A simple way is to use positive numbers to identify core interrupts +and negative numbers to identify device specific interrupts. The ISRs +for device specific interrupts are not stored in the core ISR table, +instead the device specific layer provides its own ISR table.

The general pattern for creating the core-device specific split +is that the core derives an implementation from class Asic, and the device specific part further derives from this core implementation. +The usual technique is to add a set of virtual functions to the core +class that can be derived by the device specific part. The core can +provide default implementations for these functions that would just +return KErrArgument to trap illegal ID numbers. +This API would need functions equivalent to each of the functions +defined by the Interrupt class.

As an example, +the core layer for the template reference board defines a class TemplateAssp that is derived from Asic. TemplateAssp defines the pure virtual functions: InterruptBind(), InterruptUnbind(), InterruptEnable() etc, all with signatures that are the +same for the comparable functions defined by Interrupt, and which are implemented by the Template class.

+Interrupt binding + +
+
Spurious +interrupts

In the Kernel Architecture 2, it is a convention +that unbound interrupts should be bound to a "spurious" interrupt +handler, i.e. an interrupt handler that faults the system indicating +the number of the interrupt. This aids debugging by identifying interrupts +that are enabled without corresponding ISRs.

+
Interrupt +priority

The interrupt architecture supports the concept +of adjustable interrupt priorities. Symbian platform defines the Interrupt::SetPriority() function that can implement this. +The function is passed the ID of the interrupt source to be adjusted +together with a priority value. The meaning of the priority value +is hardware and implementation dependent, and is defined by the port.

+
The +ISR table

The Variant must provide a table where each entry +defines which ISR is bound to which interrupt source. The table must have +enough space for entries for each interrupt source that is known to +the Variant.

When the Variant is split into an ASSP layer +and a Variant layer, the ISR table is put in the ASSP layer and will +not normally include ISRs for the Variant interrupt sources - these +will be handled by separate chained dispatchers in the Variant layer.

Symbian platform provides the SInterruptHandler structure, defined in the header file ...\e32\include\kernel\arm\assp.h to encapsulate the entry for an ISR. The ISR table is, therefore, +just an array of SInterruptHandler items. For example, +if a system has 32 possible interrupt sources, then the ISR table +would be defined as:

... +const TInt KInterruptSourceCount = 32; +SInterruptHandler IsrHandlers[KInterruptSourceCount]; +...

Interrupts are identified in the system by their +interrupt ID number, which is used to index into the ISR table. You +are free to allocate these numbers any way that is convenient for +you.

On the template reference board, for example, the ISR +table is defined as a static data member of the VariantASSPInterrupt class, which is derived from TemplateInterrupt. The class is defined in ...\template_assp\template_assp_priv.h.

class TemplateInterrupt : public Interrupt + { + ... // functions +public: + static SInterruptHandler Handlers[KNumTemplateInts]; + ... + };

where KNumTemplateInts is defined in the same +header file.

Factors that decide the size of the ISR table

The number of entries to be reserved in the ISR table depends +on the following factors:

    +
  • Where the ASSP +is targeted at only a single device, the number of possible interrupts +is usually known, and the table can include an entry for each one.

  • +
  • If any pseudo sources exist, they should be included in the main +table for efficiency, but note that this is not strictly necessary.

  • +

Other factors affecting the ISR table

IRQs +and FIQs may need to be distinguished, although the exact requirement +is hardware dependent. Although the table has one entry for each possible +interrupt source, a possible scheme may be to group IRQs at the start +of the table, and FIQs at the end of the table. If the hardware has +separate interrupt controller hardware for IRQs and FIQs (or at least, +different registers) then you will need to arrange the table so that +you can determine from the interrupt ID whether the interrupt is an IRQ or FIQ.

For example:

+ISR table + +
+
Location +of interrupt handling code

Most of the interrupt dispatching +code is implemented in the ASSP layer. This includes a list of ISRs, +code for adding and removing ISRs, enabling and disabling interrupt +sources, and dispatching ISRs. The kernel only provides a pre-amble +and post-amble.

The kernel defines, but does not implement, +a class called Interrupt that exports interrupt +functionality to device drivers and other kernel code. The class provides +the public API for using interrupts (but not for dispatching them). +The port must provide an implementation for each function defined +by the class.

The class is defined in the header files ...\e32\include\kernel\arm\assp.h, which is exported to ...\epoc32\include\kernel\arm.

See Symbian OS +Internals Book, Chapter 6 - Interrupts and Exceptions

+
\ No newline at end of file