Symbian3/PDK/Source/GUID-76A30EC4-4B99-5471-9E80-F853C91485BC.dita
author Dominic Pinkman <dominic.pinkman@nokia.com>
Fri, 16 Jul 2010 17:23:46 +0100
changeset 12 80ef3a206772
parent 9 59758314f811
child 14 578be2adaf3e
permissions -rw-r--r--
Week 28 contribution of PDK documentation content. See release notes for details. Fixes bugs Bug 1897, Bug 344, Bug 2681, Bug 463, Bug 1522.

<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies) All rights reserved. -->
<!-- This component and the accompanying materials are made available under the terms of the License 
"Eclipse Public License v1.0" which accompanies this distribution, 
and is available at the URL "http://www.eclipse.org/legal/epl-v10.html". -->
<!-- Initial Contributors:
    Nokia Corporation - initial contribution.
Contributors: 
-->
<!DOCTYPE concept
  PUBLIC "-//OASIS//DTD DITA Concept//EN" "concept.dtd">
<concept id="GUID-76A30EC4-4B99-5471-9E80-F853C91485BC" xml:lang="en"><title>Interrupt
Dispatcher</title><shortdesc>An interrupt is a condition that causes the CPU to suspend normal
execution, enter interrupt handling state and jump to a section of code called
an interrupt handler. The ASSP/variant part of the base port must implement
an interrupt dispatcher to manage interrupts. </shortdesc><prolog><metadata><keywords/></metadata></prolog><conbody>
<p>An interrupt source is a hardware device or software action that can force
the CPU to enter interrupt handling state. </p>
<p>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. </p>
<section id="GUID-1FAA26F5-BFB2-55A0-977C-1538EBF3C82A"><title>ISR</title> <p>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. </p> <p>The ISR is a single bare function. It is not a class member. </p> <p>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 <xref href="GUID-6D079976-9119-31FA-8E21-C3B815F94648.dita"><apiname>TAny</apiname></xref> * type, so a cast is almost always necessary. </p> <p>ISRs
are usually kept in an ISR table. </p> </section>
<section id="GUID-8E58F4C9-0290-55E0-A4FD-B6C2361BE205"><title>Interrupt ID</title> <p>An
interrupt source is identified by number, defined as a <xref href="GUID-7A2A43EC-6125-3BFE-834B-23C37F7B40D5.dita"><apiname>TInt</apiname></xref> 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. </p> <p>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. </p> <p>This
number is usually referred to as the interrupt ID. </p> </section>
<section id="GUID-A8C9C079-D043-5A5F-9F08-CD8656F6702A"><title>Binding and
unbinding</title> <p>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. </p> <p>A device driver binds an ISR by calling <xref href="GUID-E7A7083C-97B9-39B9-A147-4A6E314EE3A3.dita#GUID-E7A7083C-97B9-39B9-A147-4A6E314EE3A3/GUID-4E3CB472-3525-32F8-9BC4-8ECFEE931E7B"><apiname>Interrupt::Bind()</apiname></xref>,
passing the interrupt source ID; similarly, the device driver can unbind the
ISR by calling <xref href="GUID-E7A7083C-97B9-39B9-A147-4A6E314EE3A3.dita#GUID-E7A7083C-97B9-39B9-A147-4A6E314EE3A3/GUID-CCC9A397-608C-3EAF-830F-A59800C2E8E5"><apiname>Interrupt::Unbind()</apiname></xref>, also passing the <xref href="GUID-76A30EC4-4B99-5471-9E80-F853C91485BC.dita#GUID-76A30EC4-4B99-5471-9E80-F853C91485BC/GUID-8E58F4C9-0290-55E0-A4FD-B6C2361BE205">interrupt
ID</xref>. </p> </section>
<section id="GUID-DDA62ABB-9CC6-44DC-B08D-FEE5AC505858"><title>Dispatching
interrupts</title> <p>At its simplest, this is the process of deciding which
interrupts are pending and calling the ISR for each. </p> <p>The following
pseudo code shows the general principle: </p> <codeblock id="GUID-9C971C66-BB26-5A07-9373-3542B95A16FD" xml:space="preserve">
    {
       FOREVER
              {
        Get next pending interrupt;
        if None
            {
               return;
            }
        call ISR for the pending interrupt;
        }
    }
</codeblock> <p>In practice the dispatcher may have to do some more work to
communicate with the interrupt controller hardware. </p> </section>
<section id="GUID-9026A4AC-57AF-545D-887C-AF43E0B37EDC"><title>Chained interrupts</title> <p>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. </p> <fig id="GUID-49264B94-DF6D-5F11-8815-D42CDBF94E39">
<image href="GUID-0DB79535-E4E6-50BD-852D-B2F177202C9C_d0e381454_href.png" placement="inline"/>
</fig> <p>An interrupt from a lower priority controller will appear as an
interrupt on the highest-priority controller. </p> <p>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. </p> <p>There
may be further levels of chaining before the true source of the interrupt
has been identified. </p> </section>
<section id="GUID-ED6F2F47-7A16-5AE6-8E5B-B2475F6EDEAA"><title>Multiple interrupt
sources and pseudo interrupt sources</title> <p>It is possible that a single
input to an interrupt controller is shared by several interrupt sources. </p> <fig id="GUID-DC96E3A8-9820-5CD4-8020-3B55398388D9">
<image href="GUID-DCBBDFA7-1E6C-5B00-A13E-A25794668E12_d0e381476_href.png" placement="inline"/>
</fig> <p>It appears necessary to bind multiple ISRs to the same interrupt.
However, this is not possible. There are two ways of dealing with this: </p> <ul>
<li id="GUID-0D954444-C2C3-51CC-8E1D-7EB063CDACAA"><p>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 </p> </li>
<li id="GUID-C5EFE907-26A5-568D-8CF0-DE5E89ED5CBB"><p>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 <xref href="GUID-76A30EC4-4B99-5471-9E80-F853C91485BC.dita#GUID-76A30EC4-4B99-5471-9E80-F853C91485BC/GUID-9026A4AC-57AF-545D-887C-AF43E0B37EDC">chained
interrupt</xref>, and assumes that the interrupt dispatcher can identify which
of the sources is signalling. </p> </li>
</ul> </section>
<section id="GUID-A87DE0F9-2095-5CA6-BE88-3A2EAABB0D33"><title>Interrupts
in the split ASSP/Variant Configuration</title> <p>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. </p> <p>Device
drivers should be able to use the <xref href="GUID-E7A7083C-97B9-39B9-A147-4A6E314EE3A3.dita"><apiname>Interrupt</apiname></xref> 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 <xref href="GUID-E7A7083C-97B9-39B9-A147-4A6E314EE3A3.dita#GUID-E7A7083C-97B9-39B9-A147-4A6E314EE3A3/GUID-4E3CB472-3525-32F8-9BC4-8ECFEE931E7B"><apiname>Interrupt::Bind()</apiname></xref>, <xref href="GUID-E7A7083C-97B9-39B9-A147-4A6E314EE3A3.dita#GUID-E7A7083C-97B9-39B9-A147-4A6E314EE3A3/GUID-BB169E6E-D8F9-3762-899D-6DBA4B29CF87"><apiname>Interrupt::Enable()</apiname></xref> etc. </p> <p>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. </p> <p>The general pattern for creating the core-device specific
split is that the core derives an implementation from class <xref href="GUID-A83A7C3C-7DC0-3B9C-842F-70FCC751365D.dita"><apiname>Asic</apiname></xref>,
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 <xref href="GUID-0BEA3647-7888-3612-A2D3-7E27AC405E29.dita"><apiname>KErrArgument</apiname></xref> to
trap illegal ID numbers. This API would need functions equivalent to each
of the functions defined by the <xref href="GUID-E7A7083C-97B9-39B9-A147-4A6E314EE3A3.dita"><apiname>Interrupt</apiname></xref> class. </p> <p>As
an example, the core layer for the template reference board defines a class <codeph>TemplateAssp</codeph> that
is derived from <xref href="GUID-A83A7C3C-7DC0-3B9C-842F-70FCC751365D.dita"><apiname>Asic</apiname></xref>. <codeph>TemplateAssp</codeph> defines
the pure virtual functions: <codeph>InterruptBind()</codeph>, <codeph>InterruptUnbind()</codeph>, <codeph>InterruptEnable()</codeph> etc,
all with signatures that are the same for the comparable functions defined
by <xref href="GUID-E7A7083C-97B9-39B9-A147-4A6E314EE3A3.dita"><apiname>Interrupt</apiname></xref>, and which are implemented by the <codeph>Template</codeph> class. </p> <fig id="GUID-458C7825-5B35-583C-BDF6-7DCD21DAE670">
<image href="GUID-B7E7E6D6-7824-505C-BA0B-B7861897E78F_d0e381570_href.png" placement="inline"/>
</fig> </section>
<section id="GUID-9D98586F-AD1D-5C50-9AD8-F81D72135382"><title>Spurious interrupts</title> <p>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. </p> </section>
<section id="GUID-109C6250-DC5B-48EC-B1A0-24E2E9731B38"><title>Interrupt priority</title> <p>The
interrupt architecture supports the concept of adjustable interrupt priorities.
Symbian platform defines the <xref href="GUID-E7A7083C-97B9-39B9-A147-4A6E314EE3A3.dita#GUID-E7A7083C-97B9-39B9-A147-4A6E314EE3A3/GUID-FA4CFED7-D694-399C-8F84-FA9FE3C3A171"><apiname>Interrupt::SetPriority()</apiname></xref> 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. </p> </section>
<section id="GUID-77E83634-BBF6-5190-9434-9FB700547CD0"><title>The ISR table</title> <p>The
Variant must provide a table where each entry defines which <xref href="GUID-76A30EC4-4B99-5471-9E80-F853C91485BC.dita#GUID-76A30EC4-4B99-5471-9E80-F853C91485BC/GUID-1FAA26F5-BFB2-55A0-977C-1538EBF3C82A">ISR</xref> is bound to which interrupt source. The table must have enough
space for entries for each interrupt source that is known to the Variant. </p> <p>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. </p> <p>Symbian platform provides the <xref href="GUID-2C9B6510-D045-3FA1-AD65-B544E30D34C7.dita"><apiname>SInterruptHandler</apiname></xref> structure,
defined in the header file <filepath>...\e32\include\kernel\arm\assp.h</filepath> to
encapsulate the entry for an ISR. The ISR table is, therefore, just an array
of <xref href="GUID-2C9B6510-D045-3FA1-AD65-B544E30D34C7.dita"><apiname>SInterruptHandler</apiname></xref> items. For example, if a system has
32 possible interrupt sources, then the ISR table would be defined as: </p> <codeblock id="GUID-6C95C2EF-A882-565A-8718-07BF7E4A7AC5" xml:space="preserve">...
const TInt KInterruptSourceCount = 32;
SInterruptHandler IsrHandlers[KInterruptSourceCount];
...</codeblock> <p>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. </p> <p>On the template
reference board, for example, the ISR table is defined as a static data member
of the <codeph>VariantASSPInterrupt</codeph> class, which is derived from <xref href="GUID-5E593C59-BA22-3B70-AAFB-BFE19E22538A.dita"><apiname>TemplateInterrupt</apiname></xref>.
The class is defined in <filepath>...\template_assp\template_assp_priv.h</filepath>. </p> <codeblock id="GUID-59D7A629-353C-5117-84B7-15CD425481C6" xml:space="preserve">class TemplateInterrupt : public Interrupt
    {
    ... // functions
public:
    static SInterruptHandler Handlers[KNumTemplateInts];
    ...
    };</codeblock> <p>where KNumTemplateInts is defined in the same header
file. </p> <p><b>Factors
that decide the size of the ISR table</b> </p> <p>The number of entries to
be reserved in the ISR table depends on the following factors: </p> <ul>
<li id="GUID-05AE4B19-AA29-56E4-842A-CC65546EFB54"><p>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. </p> </li>
<li id="GUID-C62B31BD-FAD7-5A76-9E43-2387FD8AFCC8"><p>If any <xref href="GUID-76A30EC4-4B99-5471-9E80-F853C91485BC.dita#GUID-76A30EC4-4B99-5471-9E80-F853C91485BC/GUID-ED6F2F47-7A16-5AE6-8E5B-B2475F6EDEAA">pseudo sources</xref> exist, they should be included in the main table for
efficiency, but note that this is not strictly necessary. </p> </li>
</ul> <p><b>Other
factors affecting the ISR table</b> </p> <p>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 <xref href="GUID-76A30EC4-4B99-5471-9E80-F853C91485BC.dita#GUID-76A30EC4-4B99-5471-9E80-F853C91485BC/GUID-8E58F4C9-0290-55E0-A4FD-B6C2361BE205">interrupt
ID</xref> whether the interrupt is an IRQ or FIQ. </p> <p>For example: </p> <fig id="GUID-9DD2CC92-A5DB-5C78-A9A6-64402FF04FE2">
<image href="GUID-60949ACD-AAA9-540E-85AE-BB173382D548_d0e381686_href.png" placement="inline"/>
</fig> </section>
<section id="GUID-EACCBDFD-46CD-4D67-B60C-D705867C9116"><title>Location of
interrupt handling code</title> <p>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. </p> <p>The kernel
defines, but does not implement, a class called <xref href="GUID-E7A7083C-97B9-39B9-A147-4A6E314EE3A3.dita"><apiname>Interrupt</apiname></xref> 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. </p> <p>The class is defined in the header files <filepath>...\e32\include\kernel\arm\assp.h</filepath>,
which is exported to <filepath>...\epoc32\include\kernel\arm</filepath>. </p><p>See
Symbian OS Internals Book, Chapter 6  - Interrupts and Exceptions</p> </section>
</conbody></concept>