Symbian3/PDK/Source/GUID-76A30EC4-4B99-5471-9E80-F853C91485BC.dita
author Dominic Pinkman <dominic.pinkman@nokia.com>
Fri, 13 Aug 2010 16:47:46 +0100
changeset 14 578be2adaf3e
parent 12 80ef3a206772
permissions -rw-r--r--
Week 32 contribution of PDK documentation content. See release notes for details. Fixes bug Bug 3582

<?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>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 suspend normal execution, enter interrupt handling
state and jump to a section of code called an interrupt handler. </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">
<title>Chained interrupts</title>
<image href="GUID-0DB79535-E4E6-50BD-852D-B2F177202C9C_d0e379292_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">
<title>Multiple interrupt sources</title>
<image href="GUID-DCBBDFA7-1E6C-5B00-A13E-A25794668E12_d0e379317_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">
<title>Interrupt binding</title>
<image href="GUID-B7E7E6D6-7824-505C-BA0B-B7861897E78F_d0e379414_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">
<title>ISR table</title>
<image href="GUID-60949ACD-AAA9-540E-85AE-BB173382D548_d0e379533_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 <b>Symbian OS
Internals Book, Chapter 6  - Interrupts and Exceptions</b></p> </section>
</conbody></concept>