Adaptation/GUID-76A30EC4-4B99-5471-9E80-F853C91485BC.dita
changeset 15 307f4279f433
equal deleted inserted replaced
14:578be2adaf3e 15:307f4279f433
       
     1 <?xml version="1.0" encoding="utf-8"?>
       
     2 <!-- Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies) All rights reserved. -->
       
     3 <!-- This component and the accompanying materials are made available under the terms of the License 
       
     4 "Eclipse Public License v1.0" which accompanies this distribution, 
       
     5 and is available at the URL "http://www.eclipse.org/legal/epl-v10.html". -->
       
     6 <!-- Initial Contributors:
       
     7     Nokia Corporation - initial contribution.
       
     8 Contributors: 
       
     9 -->
       
    10 <!DOCTYPE concept
       
    11   PUBLIC "-//OASIS//DTD DITA Concept//EN" "concept.dtd">
       
    12 <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
       
    13 interrupt dispatcher to manage interrupts. </shortdesc><prolog><metadata><keywords/></metadata></prolog><conbody>
       
    14 <p>An interrupt source is a hardware device or software action that
       
    15 can force the CPU to suspend normal execution, enter interrupt handling
       
    16 state and jump to a section of code called an interrupt handler. </p>
       
    17 <p>Typically, a number of interrupt sources are monitored by an interrupt
       
    18 controller. This is hardware that generates a single interrupt notification
       
    19 to the CPU, and provides information about which interrupts are pending,
       
    20 i.e. which interrupts require action to be taken. </p>
       
    21 <section id="GUID-1FAA26F5-BFB2-55A0-977C-1538EBF3C82A"><title>ISR</title> <p>An interrupt service routine, or ISR, is code that deals with
       
    22 a pending interrupt. The Symbian platform kernel responds to an interrupt
       
    23 notification by calling an ISR for each pending interrupt. The process
       
    24 of calling ISRs is called interrupt dispatch. </p> <p>The ISR is a
       
    25 single bare function. It is not a class member. </p> <p>Each ISR takes
       
    26 a single 32-bit parameter that is, typically, a pointer to an owning
       
    27 class, although it can be any value that is appropriate. The parameter
       
    28 is defined as a <xref href="GUID-6D079976-9119-31FA-8E21-C3B815F94648.dita"><apiname>TAny</apiname></xref> * type, so a cast is almost
       
    29 always necessary. </p> <p>ISRs are usually kept in an ISR table. </p> </section>
       
    30 <section id="GUID-8E58F4C9-0290-55E0-A4FD-B6C2361BE205"><title>Interrupt
       
    31 ID</title> <p>An interrupt source is identified by number, defined
       
    32 as a <xref href="GUID-7A2A43EC-6125-3BFE-834B-23C37F7B40D5.dita"><apiname>TInt</apiname></xref> type. Typically, the ASSP layer defines
       
    33 this number for each interrupt in a header file and exports it so
       
    34 that it can be included and used by device drivers. </p> <p>Where
       
    35 the ASSP layer is split into a common layer and a variant (device
       
    36 specific) layer, then the variant layer may also define its own set
       
    37 of interrupt IDs. </p> <p>This number is usually referred to as the
       
    38 interrupt ID. </p> </section>
       
    39 <section id="GUID-A8C9C079-D043-5A5F-9F08-CD8656F6702A"><title>Binding
       
    40 and unbinding</title> <p>Only one ISR can be associated with each
       
    41 possible interrupt source. Making this association is known as binding.
       
    42 ISRs can be bound and unbound during normal operation, but only one
       
    43 ISR can be bound to an interrupt source at any one time. </p> <p>A
       
    44 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
       
    45 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>,
       
    46 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>
       
    47 <section id="GUID-DDA62ABB-9CC6-44DC-B08D-FEE5AC505858"><title>Dispatching
       
    48 interrupts</title> <p>At its simplest, this is the process of deciding
       
    49 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">
       
    50     {
       
    51        FOREVER
       
    52               {
       
    53         Get next pending interrupt;
       
    54         if None
       
    55             {
       
    56                return;
       
    57             }
       
    58         call ISR for the pending interrupt;
       
    59         }
       
    60     }
       
    61 </codeblock> <p>In practice the dispatcher may have to do some more
       
    62 work to communicate with the interrupt controller hardware. </p> </section>
       
    63 <section id="GUID-9026A4AC-57AF-545D-887C-AF43E0B37EDC"><title>Chained
       
    64 interrupts</title> <p>A system may have multiple interrupt controllers
       
    65 to handle a large number of interrupt sources. These are usually prioritised
       
    66 by connecting the interrupt output of a lower-priority controller
       
    67 to an interrupt input of a higher-priority controller. This is called
       
    68 chaining. </p> <fig id="GUID-49264B94-DF6D-5F11-8815-D42CDBF94E39">
       
    69 <title>Chained interrupts</title>
       
    70 <image href="GUID-0DB79535-E4E6-50BD-852D-B2F177202C9C_d0e13227_href.png" placement="inline"/>
       
    71 </fig> <p>An interrupt from a lower priority controller will appear
       
    72 as an interrupt on the highest-priority controller. </p> <p>When the
       
    73 interrupt dispatcher of the higher-priority controller detects that
       
    74 it is the chained interrupt that is pending, the usual way of dealing
       
    75 with this is to run a secondary dispatcher to determine which interrupt
       
    76 on the chained controller is pending. </p> <p>There may be further
       
    77 levels of chaining before the true source of the interrupt has been
       
    78 identified. </p> </section>
       
    79 <section id="GUID-ED6F2F47-7A16-5AE6-8E5B-B2475F6EDEAA"><title>Multiple
       
    80 interrupt sources and pseudo interrupt sources</title> <p>It is possible
       
    81 that a single input to an interrupt controller is shared by several
       
    82 interrupt sources. </p> <fig id="GUID-DC96E3A8-9820-5CD4-8020-3B55398388D9">
       
    83 <title>Multiple interrupt sources</title>
       
    84 <image href="GUID-DCBBDFA7-1E6C-5B00-A13E-A25794668E12_d0e13252_href.png" placement="inline"/>
       
    85 </fig> <p>It appears necessary to bind multiple ISRs to the same interrupt.
       
    86 However, this is not possible. There are two ways of dealing with
       
    87 this: </p> <ul>
       
    88 <li id="GUID-0D954444-C2C3-51CC-8E1D-7EB063CDACAA"><p>Maintain a list
       
    89 of all ISRs that are bound to this single interrupt source, and call
       
    90 all the ISRs in the list when the interrupt is dispatched. This is
       
    91 most conveniently implemented by binding a single ISR to the interrupt,
       
    92 which then calls all the real ISRs bound to this interrupt </p> </li>
       
    93 <li id="GUID-C5EFE907-26A5-568D-8CF0-DE5E89ED5CBB"><p>Create pseudo
       
    94 interrupts. These are extra interrupt IDs that do not exist in the
       
    95 interrupt controller, but represent each of the interrupt sources
       
    96 connected to the single shared interrupt source. An ISR can then be
       
    97 bound to each pseudo interrupt. The interrupt dispatcher can then
       
    98 determine which of the sources are actually signalling and call the
       
    99 appropriate ISR via that pseudo interrupt ID. This is effectively
       
   100 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
       
   101 can identify which of the sources is signalling. </p> </li>
       
   102 </ul> </section>
       
   103 <section id="GUID-A87DE0F9-2095-5CA6-BE88-3A2EAABB0D33"><title>Interrupts
       
   104 in the split ASSP/Variant Configuration</title> <p>When a common ASSP
       
   105 extension is used, a device may have additional peripherals external
       
   106 to the ASSP, and there needs to be a way of allowing extra interrupt
       
   107 binding and dispatch functions to be added later by the variant layer.
       
   108 This must be handled by the port as Symbian platform does not provide
       
   109 any additional API to support this. </p> <p>Device drivers should
       
   110 be able to use the <xref href="GUID-E7A7083C-97B9-39B9-A147-4A6E314EE3A3.dita"><apiname>Interrupt</apiname></xref> class functions without
       
   111 having to know where the interrupt is actually implemented. This implies
       
   112 that all requests should go to the core implementation of functions
       
   113 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
       
   114 to decide whether an interrupt ID refers to a core interrupt or device
       
   115 specific interrupt, a common technique is to "tag" the interrupt ID.
       
   116 A simple way is to use positive numbers to identify core interrupts
       
   117 and negative numbers to identify device specific interrupts. The ISRs
       
   118 for device specific interrupts are not stored in the core ISR table,
       
   119 instead the device specific layer provides its own ISR table. </p> <p>The general pattern for creating the core-device specific split
       
   120 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.
       
   121 The usual technique is to add a set of virtual functions to the core
       
   122 class that can be derived by the device specific part. The core can
       
   123 provide default implementations for these functions that would just
       
   124 return <xref href="GUID-0BEA3647-7888-3612-A2D3-7E27AC405E29.dita"><apiname>KErrArgument</apiname></xref> to trap illegal ID numbers.
       
   125 This API would need functions equivalent to each of the functions
       
   126 defined by the <xref href="GUID-E7A7083C-97B9-39B9-A147-4A6E314EE3A3.dita"><apiname>Interrupt</apiname></xref> class. </p> <p>As an example,
       
   127 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
       
   128 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">
       
   129 <title>Interrupt binding</title>
       
   130 <image href="GUID-B7E7E6D6-7824-505C-BA0B-B7861897E78F_d0e13349_href.png" placement="inline"/>
       
   131 </fig> </section>
       
   132 <section id="GUID-9D98586F-AD1D-5C50-9AD8-F81D72135382"><title>Spurious
       
   133 interrupts</title> <p>In the Kernel Architecture 2, it is a convention
       
   134 that unbound interrupts should be bound to a "spurious" interrupt
       
   135 handler, i.e. an interrupt handler that faults the system indicating
       
   136 the number of the interrupt. This aids debugging by identifying interrupts
       
   137 that are enabled without corresponding ISRs. </p> </section>
       
   138 <section id="GUID-109C6250-DC5B-48EC-B1A0-24E2E9731B38"><title>Interrupt
       
   139 priority</title> <p>The interrupt architecture supports the concept
       
   140 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.
       
   141 The function is passed the ID of the interrupt source to be adjusted
       
   142 together with a priority value. The meaning of the priority value
       
   143 is hardware and implementation dependent, and is defined by the port. </p> </section>
       
   144 <section id="GUID-77E83634-BBF6-5190-9434-9FB700547CD0"><title>The
       
   145 ISR table</title> <p>The Variant must provide a table where each entry
       
   146 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
       
   147 enough space for entries for each interrupt source that is known to
       
   148 the Variant. </p> <p>When the Variant is split into an ASSP layer
       
   149 and a Variant layer, the ISR table is put in the ASSP layer and will
       
   150 not normally include ISRs for the Variant interrupt sources - these
       
   151 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,
       
   152 just an array of <xref href="GUID-2C9B6510-D045-3FA1-AD65-B544E30D34C7.dita"><apiname>SInterruptHandler</apiname></xref> items. For example,
       
   153 if a system has 32 possible interrupt sources, then the ISR table
       
   154 would be defined as: </p> <codeblock id="GUID-6C95C2EF-A882-565A-8718-07BF7E4A7AC5" xml:space="preserve">...
       
   155 const TInt KInterruptSourceCount = 32;
       
   156 SInterruptHandler IsrHandlers[KInterruptSourceCount];
       
   157 ...</codeblock> <p>Interrupts are identified in the system by their
       
   158 interrupt ID number, which is used to index into the ISR table. You
       
   159 are free to allocate these numbers any way that is convenient for
       
   160 you. </p> <p>On the template reference board, for example, the ISR
       
   161 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
       
   162     {
       
   163     ... // functions
       
   164 public:
       
   165     static SInterruptHandler Handlers[KNumTemplateInts];
       
   166     ...
       
   167     };</codeblock> <p>where KNumTemplateInts is defined in the same
       
   168 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
       
   169 on the following factors: </p> <ul>
       
   170 <li id="GUID-05AE4B19-AA29-56E4-842A-CC65546EFB54"><p>Where the ASSP
       
   171 is targeted at only a single device, the number of possible interrupts
       
   172 is usually known, and the table can include an entry for each one. </p> </li>
       
   173 <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
       
   174 table for efficiency, but note that this is not strictly necessary. </p> </li>
       
   175 </ul> <p><b>Other factors affecting the ISR table</b> </p> <p>IRQs
       
   176 and FIQs may need to be distinguished, although the exact requirement
       
   177 is hardware dependent. Although the table has one entry for each possible
       
   178 interrupt source, a possible scheme may be to group IRQs at the start
       
   179 of the table, and FIQs at the end of the table. If the hardware has
       
   180 separate interrupt controller hardware for IRQs and FIQs (or at least,
       
   181 different registers) then you will need to arrange the table so that
       
   182 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">
       
   183 <title>ISR table</title>
       
   184 <image href="GUID-60949ACD-AAA9-540E-85AE-BB173382D548_d0e13468_href.png" placement="inline"/>
       
   185 </fig> </section>
       
   186 <section id="GUID-EACCBDFD-46CD-4D67-B60C-D705867C9116"><title>Location
       
   187 of interrupt handling code</title> <p>Most of the interrupt dispatching
       
   188 code is implemented in the ASSP layer. This includes a list of ISRs,
       
   189 code for adding and removing ISRs, enabling and disabling interrupt
       
   190 sources, and dispatching ISRs. The kernel only provides a pre-amble
       
   191 and post-amble. </p> <p>The kernel defines, but does not implement,
       
   192 a class called <xref href="GUID-E7A7083C-97B9-39B9-A147-4A6E314EE3A3.dita"><apiname>Interrupt</apiname></xref> that exports interrupt
       
   193 functionality to device drivers and other kernel code. The class provides
       
   194 the public API for using interrupts (but not for dispatching them).
       
   195 The port must provide an implementation for each function defined
       
   196 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
       
   197 Internals Book, Chapter 6  - Interrupts and Exceptions</b></p> </section>
       
   198 </conbody></concept>