Adaptation/GUID-8B8CAEED-A89D-53B3-A311-51CF45B334B1.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-8B8CAEED-A89D-53B3-A311-51CF45B334B1" xml:lang="en"><title>IRQ
       
    13 and FIQ Dispatchers</title><shortdesc>The ASSP must supply two dispatcher functions, one for IRQ interrupts,
       
    14 and one for FIQ interrupts.</shortdesc><prolog><metadata><keywords/></metadata></prolog><conbody>
       
    15 <p> The following example code is a simple dispatcher for IRQ interrupts.
       
    16 It assumes a simplistic interrupt controller that provides 32 interrupt sources,
       
    17 and has a 32-bit pending-interrupt register where a 'one' bit indicates a
       
    18 pending interrupt and all ones are cleared when the register is read. </p>
       
    19 <codeblock id="GUID-1603305D-1509-5E80-89C1-B3998B557216" xml:space="preserve">void IrqDispatch()
       
    20     {
       
    21     TUint32 pendingIrqs = TheAssp::IrqPendingRegister();
       
    22     // for the purposes of this example we assume that reading
       
    23     // this register also clears the pending flags
       
    24 
       
    25     TInt index = 0;
       
    26     while( pendingIrqs )
       
    27         {
       
    28         // while there is at least one pending IRQ
       
    29         if( pendingIrqs &amp; 1 )
       
    30             {
       
    31             // the next interrupt is pending - dispatch it
       
    32             (IsrHandlers[index].iIsr)(IsrHandlers[index].iPtr);
       
    33             }
       
    34         ++index;
       
    35         pendingIrqs &gt;&gt;= 1;
       
    36         }
       
    37     }
       
    38 </codeblock>
       
    39 <p>The code assumes that the interrupt source represented by the low order
       
    40 bit in the pending-interrupt register is represented by interrupt ID number
       
    41 0 etc. </p>
       
    42 <p>When implementing the dispatcher it is usual to write it in C++ initially,
       
    43 but once you have it working you would probably want to rewrite it in assembler
       
    44 to gain maximum efficiency for what is a time-critical section of code. </p>
       
    45 <section id="GUID-3F0D4E4E-8D9C-51FD-A701-65C29D54AB94"><title>Dealing with
       
    46 chained interrupts</title> <p>There are two considerations when dealing with <xref href="GUID-76A30EC4-4B99-5471-9E80-F853C91485BC.dita#GUID-76A30EC4-4B99-5471-9E80-F853C91485BC/GUID-9026A4AC-57AF-545D-887C-AF43E0B37EDC">chained
       
    47 interrupts</xref>: </p> <ol id="GUID-DB84BE88-14E8-5124-9D43-4FC523311B65">
       
    48 <li id="GUID-DA20FB18-6949-5CDC-B44B-65A43283558A"><p>how to identify interrupts
       
    49 on the lower priority chained controllers </p> </li>
       
    50 <li id="GUID-17C8A3C8-CCC5-574F-B7E2-C72CC2685569"><p>how to handle the dispatch
       
    51 of a chained interrupt. </p> </li>
       
    52 </ol> <p>The first point is a question of allocating locations in your <xref href="GUID-76A30EC4-4B99-5471-9E80-F853C91485BC.dita#GUID-76A30EC4-4B99-5471-9E80-F853C91485BC/GUID-77E83634-BBF6-5190-9434-9FB700547CD0">ISR
       
    53 table</xref> for the secondary controllers so that 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> identifies which hardware controller the interrupt is
       
    54 on. For example, if each interrupt controller handles 32 interrupt sources,
       
    55 you could make the first 32 IDs refer to the highest-level controller, the
       
    56 next 32 refer to one of the second-level controllers etc. </p> <p>There is
       
    57 no need to change the <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> and <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> functions,
       
    58 although you may need to consider extending the <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> and <xref href="GUID-E7A7083C-97B9-39B9-A147-4A6E314EE3A3.dita#GUID-E7A7083C-97B9-39B9-A147-4A6E314EE3A3/GUID-2D14E023-E6ED-39BF-8B31-6FA510957A8A"><apiname>Interrupt::Disable()</apiname></xref> functions
       
    59 to enable and disable the chain interrupt in a higher-level interrupt controller,
       
    60 if necessary. </p> <p>There are at least two ways of dispatching a chained
       
    61 interrupt: </p> <p><b>Dispatching a chained interrupt (1)</b> </p> <p>One
       
    62 way of dispatching a chained interrupt is simply to make it a special case
       
    63 in the main interrupt dispatcher. For example: </p> <codeblock id="GUID-189585CD-03BF-5E1F-ACD0-4AE2578D061B" xml:space="preserve">void IrqDispatch()
       
    64     {
       
    65     TUint32 pendingIrqs = TheAssp::IrqPendingRegister();
       
    66 
       
    67     TInt index = 0;
       
    68     while( pendingIrqs )
       
    69         {
       
    70         if( pendingIrqs &amp; 1 )
       
    71             {
       
    72             if( index == EMainIntChainIrq )
       
    73                 {
       
    74                 // second-level controller is signalling
       
    75                 SecondLevelIrqDispatch();
       
    76                 }
       
    77             else
       
    78                 {
       
    79                 // call ISR
       
    80                 (IsrHandlers[index].iIsr)(IsrHandlers[index].iPtr);
       
    81                 }
       
    82             }
       
    83         ++index;
       
    84         pendingIrqs &gt;&gt;= 1;
       
    85         }
       
    86     }
       
    87 </codeblock> <p>This approach works for a simple case, for example, where
       
    88 there is only a main and secondary interrupt controller. It is does not scale
       
    89 well because the special cases in the dispatcher become an overhead on the
       
    90 dispatch of normal, unchained interrupts as the number and depth of the chaining
       
    91 increases. </p> <p><b>Dispatching a chained interrupt (2)</b> </p> <p>A better
       
    92 way of handling chained interrupts is to bind an ISR to the interrupt source
       
    93 in the main interrupt controller and use it to dispatch the chained interrupt.
       
    94 This is far more scalable because you can bind any number of ISRs without
       
    95 having to add special cases to any of the interrupt dispatchers. </p> <p>The
       
    96 dispatcher code could then be re-implemented as: </p> <codeblock id="GUID-3B8BE593-C391-5D1F-BE94-5386306F773B" xml:space="preserve">void IrqDispatch()
       
    97     // MAIN IRQ DISPATCHER, FIRST-LEVEL INTERRUPT
       
    98     {
       
    99     TUint32 pendingIrqs = TheAssp::IrqPendingRegister();
       
   100 
       
   101     TInt index = 0;
       
   102     while( pendingIrqs )
       
   103         {
       
   104         if( pendingIrqs &amp; 1 )
       
   105             {
       
   106             (IsrHandlers[index].iIsr)(IsrHandlers[index].iPtr);
       
   107             }
       
   108         ++index;
       
   109         pendingIrqs &gt;&gt;= 1;
       
   110         }
       
   111     }
       
   112 </codeblock> <codeblock id="GUID-D38C0DE2-3171-59AB-AEE2-7CC5E26C4E17" xml:space="preserve">void SecondLevelIrqDispatch( TAny* /* aParam */ )
       
   113     {
       
   114     TUint32 pendingIrqs = TheAssp::SecondLevelIrqPendingRegister();
       
   115  
       
   116     TInt index = EStartOfSecondLevelIntId;
       
   117     while( pendingIrqs )
       
   118         {
       
   119         if( pendingIrqs &amp; 1 )
       
   120             {
       
   121             (IsrHandlers[index].iIsr)(IsrHandlers[index].iPtr);
       
   122             }
       
   123         ++index;
       
   124         pendingIrqs &gt;&gt;= 1;
       
   125         }
       
   126     }
       
   127 </codeblock> <codeblock id="GUID-87385945-E0DB-5396-A8EB-8B8F2B2EA80F" xml:space="preserve">void InitialiseSecondLevelDispatch()
       
   128     // Bind and enable the second-level dispatcher
       
   129     {
       
   130     Interrupt::Bind(EMainIntChainIrq,SecondLevelIrqDispatch,NULL);
       
   131     Interrupt::Enable( EMainIntChainIrq );
       
   132     }
       
   133 </codeblock> <fig id="GUID-4109B9AA-BAE7-5454-9556-DC6D40AC75B9">
       
   134 <title>Interrupt sources</title>
       
   135 <image href="GUID-970EC5A9-8ED3-53C5-93A3-2EC1A7B6F25F_d0e13980_href.png" placement="inline"/>
       
   136 </fig> <ul>
       
   137 <li id="GUID-7257146C-52C7-5C2F-B6F6-B32B558A0620"><p>The second level dispatcher, <codeph>SecondLevelIrqDispatch()</codeph>,
       
   138 is itself an ISR, and takes a <xref href="GUID-6D079976-9119-31FA-8E21-C3B815F94648.dita"><apiname>TAny</apiname></xref> * parameter, but is
       
   139 not needed in this specific example. It reads the interrupt pending register
       
   140 of the second-level interrupt controller. Note, however, that the <xref href="GUID-6D079976-9119-31FA-8E21-C3B815F94648.dita"><apiname>TAny</apiname></xref> *
       
   141 parameter may be useful when the second level dispatcher is in the variant
       
   142 as opposed to the ASSP. In that case you have separate interrupt IDs for variant
       
   143 level interrupts and separate ISR tables. The <xref href="GUID-6D079976-9119-31FA-8E21-C3B815F94648.dita"><apiname>TAny</apiname></xref> * parameter
       
   144 can point to the appropriate ISR table. Alternatively the <xref href="GUID-6D079976-9119-31FA-8E21-C3B815F94648.dita"><apiname>TAny</apiname></xref> *
       
   145 can point to a data block containing IO addresses - especially useful if you
       
   146 have many I/O devices mapped as hardware chunks. See the code in <filepath>...\assabet\specific\variant.cpp</filepath>. </p> </li>
       
   147 <li id="GUID-7ACA87E5-136F-56C2-855C-2F0C7486C13F"><p>The index count starts
       
   148 at offset <codeph>EStartOfSecondLevelIntId</codeph> into the ISR table, where
       
   149 the second-level interrupt ISRs are located. In this example, this symbol
       
   150 would equate to 32. </p> </li>
       
   151 <li id="GUID-0CDF7519-D979-5F49-ABBB-C3DC55426065"><p> <codeph>EMainIntChainIrq</codeph> is
       
   152 the interrupt ID of the chained interrupt source to the main interrupt controller. </p> </li>
       
   153 </ul> </section>
       
   154 <section id="GUID-BE4C910E-5FC7-4F83-AFF9-1070464FDA59"><title>Dealing with multiple interrupt sources</title> <p>The case
       
   155 where multiple peripherals are connected to the same interrupt source can
       
   156 be handled through the technique of pseudo interrupt sources. This involves
       
   157 assigning pseudo-interrupt IDs in the ISR table to correspond to each of the
       
   158 peripherals that is attached to the interrupt line, i.e. ISRs are bound to
       
   159 these pseudo-interrupt sources. </p> <p>Dealing with pseudo interrupt sources
       
   160 is, in essence, a special case of <xref href="GUID-76A30EC4-4B99-5471-9E80-F853C91485BC.dita#GUID-76A30EC4-4B99-5471-9E80-F853C91485BC/GUID-9026A4AC-57AF-545D-887C-AF43E0B37EDC">Chained
       
   161 interrupts</xref>. </p> <p>The dispatcher can do one of two things: </p> <ul>
       
   162 <li id="GUID-152A4626-FE77-5EED-9648-6ED1B08C04E8"><p>examine the peripheral
       
   163 hardware to determine which of the interrupts are pending, and then call the
       
   164 appropriate ISR </p> </li>
       
   165 <li id="GUID-320CC5CC-A60D-5681-92AD-922DE1F97D95"><p>call all the ISRs and
       
   166 leave them to determine whether their peripheral is actually signalling an
       
   167 interrupt. </p> </li>
       
   168 </ul> <p>As usual, it is entirely up to you to choose the ID numbers for these
       
   169 pseudo-interrupts. </p> <p>There should be no need to alter the implementations
       
   170 of <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> or <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> but
       
   171 you will need some special handling in <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> to
       
   172 enable the true interrupt source, and <xref href="GUID-E7A7083C-97B9-39B9-A147-4A6E314EE3A3.dita#GUID-E7A7083C-97B9-39B9-A147-4A6E314EE3A3/GUID-2D14E023-E6ED-39BF-8B31-6FA510957A8A"><apiname>Interrupt::Disable()</apiname></xref> to
       
   173 disable this interrupt source. </p> <p>Dispatching the interrupt can be done
       
   174 in either of the two ways described in dealing with <xref href="GUID-76A30EC4-4B99-5471-9E80-F853C91485BC.dita#GUID-76A30EC4-4B99-5471-9E80-F853C91485BC/GUID-9026A4AC-57AF-545D-887C-AF43E0B37EDC">chained interrupts</xref>. Making use of a special case in the main interrupt
       
   175 dispatcher is acceptable for simple cases, but for more complicated cases
       
   176 with large numbers of pseudo-interrupts or a combination of chained and pseudo-interrupts,
       
   177 it is better to use an ISR dispatcher bound to the true interrupt source. </p> </section>
       
   178 </conbody></concept>