|
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)>=TUint(KInterruptSourceCount)) |
|
35 { |
|
36 r = KErrArgument; // Illegal interrupt number |
|
37 } |
|
38 else |
|
39 { |
|
40 SInterruptHandler& h = IsrHandlers[aId]; |
|
41 TInt irq = NKern::DisableAllInterrupts(); |
|
42 if (h.iIsr != &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) >= TUint(KInterruptSourceCount)) |
|
61 { |
|
62 r = KErrArgument; // Illegal interrupt number |
|
63 } |
|
64 else |
|
65 { |
|
66 SInterruptHandler& h = IsrHandlers[aId]; |
|
67 TInt irq = NKern::DisableAllInterrupts(); |
|
68 if (h.iIsr == &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 < 0 ) |
|
97 { |
|
98 return MyAsic->VariantBind( aId, aIsr, aPtr ); // Device specific ID, call variant |
|
99 } |
|
100 else if (aId >= KInterruptSourceCount) |
|
101 { |
|
102 r = KErrArgument; // Illegal interrupt number |
|
103 } |
|
104 else |
|
105 { |
|
106 SInterruptHandler& 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 >=0 |
|
136 If (aId >= KInterruptSourceCount || aId < 0) |
|
137 { |
|
138 r = KErrArgument; // Illegal interrupt number |
|
139 } |
|
140 else |
|
141 { |
|
142 SInterruptHandler& 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> |