Adaptation/GUID-8B7E2A72-B793-5E70-87F0-92AA0A482F23.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-8B7E2A72-B793-5E70-87F0-92AA0A482F23" xml:lang="en"><title>Interrupt::Bind()
       
    13 and Interrupt::Unbind() </title><shortdesc>Describes two types of configuration used in the implementation
       
    14 of bind and unbind functions.</shortdesc><prolog><metadata><keywords/></metadata></prolog><conbody>
       
    15 <p>The functions <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> provide
       
    16 device drivers with a way of binding ISRs to interrupt sources, and unbinding
       
    17 ISRs from interrupt sources. The implementation of these functions follows
       
    18 a standard pattern that can be re-used in most cases. </p>
       
    19 <p>The implementation can be different if there is a single Variant DLL, or
       
    20 if there is also an ASSP extension. </p>
       
    21 <section id="GUID-D6F47DE3-7320-4C3A-A7BB-96B57DFF40DA"><title>Variant DLL only configuration</title> <p>The following example
       
    22 implementation 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> assumes that all ISRs
       
    23 in the ISR table have been bound, by default, to the <xref href="GUID-76A30EC4-4B99-5471-9E80-F853C91485BC.dita#GUID-76A30EC4-4B99-5471-9E80-F853C91485BC/GUID-9D98586F-AD1D-5C50-9AD8-F81D72135382">spurious interrupts</xref> handler function as done in <xref href="GUID-423537D5-2C8A-5C26-8D7B-60446E95F681.dita">initialising
       
    24 the table</xref>. To bind an interrupt source, the spurious interrupts handler
       
    25 is replaced with the provided ISR. The implementation prevents an ISR from
       
    26 being bound to an interrupt source that is already bound, by assuming that
       
    27 an unbound interrupt source is bound to the spurious interrupts handler. </p> <p>The
       
    28 implementation shows the basic idea but may need to be extended, especially
       
    29 where <xref href="GUID-76A30EC4-4B99-5471-9E80-F853C91485BC.dita#GUID-76A30EC4-4B99-5471-9E80-F853C91485BC/GUID-9026A4AC-57AF-545D-887C-AF43E0B37EDC">chained
       
    30 interrupts</xref> and/or <xref href="GUID-76A30EC4-4B99-5471-9E80-F853C91485BC.dita#GUID-76A30EC4-4B99-5471-9E80-F853C91485BC/GUID-ED6F2F47-7A16-5AE6-8E5B-B2475F6EDEAA">multiple
       
    31 interrupt sources and pseudo interrupt sources</xref> are involved. </p> <codeblock id="GUID-EF5B6524-6070-5563-919B-881039629E2B" xml:space="preserve">EXPORT_C TInt Interrupt::Bind(TInt aId, TIsr aIsr, TAny* aPtr)
       
    32     {
       
    33        TInt r = KErrNone;
       
    34     If(TUint(aId)&gt;=TUint(KInterruptSourceCount))
       
    35         {
       
    36         r = KErrArgument; // Illegal interrupt number
       
    37         }
       
    38        else 
       
    39         {
       
    40            SInterruptHandler&amp; h = IsrHandlers[aId];
       
    41         TInt irq = NKern::DisableAllInterrupts();
       
    42         if (h.iIsr != &amp;SpuriousHandler)
       
    43             {
       
    44             r = KErrInUse; // Already bound to an ISR
       
    45             }
       
    46            else
       
    47             {
       
    48             h.iPtr = aPtr; // The ISR parameter
       
    49             h.iIsr = aIsr; // Pointer to the ISR
       
    50             }
       
    51         NKern::RestoreInterrupts(irq);
       
    52         }
       
    53     return r;
       
    54     }
       
    55 </codeblock> <p> <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> is the logical opposite
       
    56 of <codeph>Bind()</codeph>, replacing the ISR with the spurious handler function.
       
    57 The following code is the matching example implementation. </p> <codeblock id="GUID-B3240465-BF03-5977-B73C-9FF61B209F5C" xml:space="preserve">EXPORT_C TInt Interrupt::Unbind(TInt aId)
       
    58     {
       
    59        TInt r = KErrNone;
       
    60        if (TUint(aId) &gt;= TUint(KInterruptSourceCount))
       
    61         {
       
    62         r = KErrArgument;    // Illegal interrupt number
       
    63         }
       
    64        else
       
    65         {
       
    66         SInterruptHandler&amp; h = IsrHandlers[aId];
       
    67         TInt irq = NKern::DisableAllInterrupts();
       
    68         if (h.iIsr == &amp;SpuriousHandler)
       
    69             {
       
    70             r = KErrGeneral; // Already unbound
       
    71             }
       
    72         else
       
    73             {
       
    74             h.iPtr =(TAny*)aId;
       
    75             h.iIsr = SpuriousHandler;  // Replace with spurious handler
       
    76             // NOTE: at this point it may be wise to
       
    77             // force the hardware interrupt source to disabled.
       
    78             }
       
    79         NKern::RestoreInterrupts(irq);
       
    80         }
       
    81     return r;
       
    82        }
       
    83 </codeblock> <p>Note that functions in the <xref href="GUID-E7A7083C-97B9-39B9-A147-4A6E314EE3A3.dita"><apiname>Interrupt</apiname></xref> class
       
    84 can be called from anywhere in kernel-side code, including ISRs, DFCs and
       
    85 IDFCs, and kernel threads. You need to ensure that if you are manipulating
       
    86 the ISR table, or any other structure that is shared, you need to <i>disable</i> interrupts
       
    87 to prevent corruption of the data. Interrupts are disabled and re-enabled
       
    88 using <xref href="GUID-3A3C08F3-3D33-3D9E-80E7-7855C7B21E02.dita#GUID-3A3C08F3-3D33-3D9E-80E7-7855C7B21E02/GUID-8C251C65-FDE7-3161-8D2B-61401FB6487F"><apiname>NKern::DisableAllInterrupts()</apiname></xref> and <xref href="GUID-3A3C08F3-3D33-3D9E-80E7-7855C7B21E02.dita#GUID-3A3C08F3-3D33-3D9E-80E7-7855C7B21E02/GUID-2D328082-3A9F-3467-81CF-B1C68866E163"><apiname>NKern::RestoreInterrupts()</apiname></xref>. </p> </section>
       
    89 <section id="GUID-883CCAD1-8339-4D95-A05C-AC2AFA2786F7"><title>ASSP Extension and Variant DLL configuration</title> <p>When
       
    90 a common ASSP extension is used, the Variant DLL may have to implement extra
       
    91 interrupt binding and dispatch functions for the device-specific interrupts. </p> <p>The
       
    92 following code is an example of an implementation 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> in
       
    93 the ASSP layer, where negative Interrupt IDs represent device specific interrupts. </p> <codeblock id="GUID-B1FF5AEC-30D2-5A4F-8677-5757906C629B" xml:space="preserve">EXPORT_C TInt Interrupt::Bind(TInt aId, TIsr aIsr, TAny* aPtr)
       
    94     {
       
    95     TInt r = KErrNone;
       
    96     if(aId &lt; 0 )
       
    97         {
       
    98         return MyAsic-&gt;VariantBind( aId, aIsr, aPtr ); // Device specific ID, call variant
       
    99         }
       
   100     else if (aId &gt;= KInterruptSourceCount)
       
   101             {
       
   102             r = KErrArgument; // Illegal interrupt number
       
   103             }
       
   104         else
       
   105             {
       
   106             SInterruptHandler&amp; h = IsrHandlers[aId];
       
   107             TInt irq = NKern::DisableAllInterrupts();
       
   108             if (h.iIsr != SpuriousHandler)
       
   109                 {
       
   110                 r = KErrInUse; // Already bound to an ISR
       
   111                 }
       
   112             else
       
   113                 {
       
   114                 h.iPtr = aPtr;
       
   115                 h.iIsr = anIsr;
       
   116                 }
       
   117             NKern::RestoreInterrupts(irq);
       
   118             }
       
   119     return r;
       
   120     }</codeblock> <p>The default device specific implementation of the <codeph>VariantBind()</codeph> function
       
   121 might be as follows: </p> <codeblock id="GUID-99850E43-605F-5FA0-95B3-3E472CA6FD56" xml:space="preserve">TInt TMyAsic::VariantBind( TInt aId, TIsr aIsr, TAny* aPtr )
       
   122     // Default implementation when device specific layer does not override
       
   123     // and this is therefore an illegal aId.
       
   124     {
       
   125     return KErrArgument;
       
   126     }
       
   127 </codeblock> <p>The device specific implementation of <codeph>VariantBind()</codeph> would
       
   128 follow the same general pattern as for the <codeph>Interrupt::Bind()</codeph> function
       
   129 in the ASSP layer. The main difference is that the code refers to the device
       
   130 specific ISR table, <codeph>VariantHandlers[]</codeph>, defined within the
       
   131 device specific layer, and the interrupt ID is converted to a positive number
       
   132 so that it can be used as an index into this table: </p> <codeblock id="GUID-547FA8BB-F5BB-56A4-AC8F-7FCA07C7BD9A" xml:space="preserve">SInterruptHandler VariantHandlers[KNumVariantInts];</codeblock> <codeblock id="GUID-7D86B6BA-6FED-52F7-9DB8-4EF21A734CE1" xml:space="preserve">EXPORT_C TInt TMyVariant::VariantBind(TInt aId, TIsr aIsr, TAny* aPtr)
       
   133     {
       
   134     TInt r = KErrNone;
       
   135     aId = (-aId)-1;    // convert to positive number &gt;=0
       
   136     If (aId &gt;= KInterruptSourceCount || aId &lt; 0)
       
   137         {
       
   138         r = KErrArgument; // Illegal interrupt number
       
   139         }
       
   140     else
       
   141         {
       
   142         SInterruptHandler&amp; h = VariantHandlers[aId];
       
   143         TInt irq = NKern::DisableAllInterrupts();
       
   144         if (h.iIsr != VariantSpuriousHandler)
       
   145             {
       
   146             r = KErrInUse; // Already bound to an ISR
       
   147             }
       
   148         else
       
   149             {
       
   150             h.iPtr = aPtr;
       
   151             h.iIsr = anIsr;
       
   152             }
       
   153         NKern::RestoreInterrupts(irq);
       
   154         }
       
   155     return r;
       
   156     }</codeblock> <p>Now you need a way of dispatching the interrupts and
       
   157 since this is really a chained interrupt, the dispatch function can be packaged
       
   158 as an ISR and bound to the core interrupt source it chains from. See <xref href="GUID-8B8CAEED-A89D-53B3-A311-51CF45B334B1.dita">IRQ and FIQ Dispatchers</xref> in
       
   159 general and <xref href="GUID-8B8CAEED-A89D-53B3-A311-51CF45B334B1.dita#GUID-8B8CAEED-A89D-53B3-A311-51CF45B334B1/GUID-3F0D4E4E-8D9C-51FD-A701-65C29D54AB94">Dealing
       
   160 with chained interrupts</xref> in particular. </p> </section>
       
   161 </conbody><related-links>
       
   162 <link href="GUID-76A30EC4-4B99-5471-9E80-F853C91485BC.dita#GUID-76A30EC4-4B99-5471-9E80-F853C91485BC/GUID-A87DE0F9-2095-5CA6-BE88-3A2EAABB0D33">
       
   163 <linktext>Interrupts in the                 split ASSP/Variant Configuration</linktext>
       
   164 </link>
       
   165 </related-links></concept>