|
0
|
1 #ifndef CYGONCE_KERNEL_INTR_HXX |
|
|
2 #define CYGONCE_KERNEL_INTR_HXX |
|
|
3 |
|
|
4 //========================================================================== |
|
|
5 // |
|
|
6 // intr.hxx |
|
|
7 // |
|
|
8 // Interrupt class declaration(s) |
|
|
9 // |
|
|
10 //========================================================================== |
|
|
11 //####COPYRIGHTBEGIN#### |
|
|
12 // |
|
|
13 // ------------------------------------------- |
|
|
14 // The contents of this file are subject to the Cygnus eCos Public License |
|
|
15 // Version 1.0 (the "License"); you may not use this file except in |
|
|
16 // compliance with the License. You may obtain a copy of the License at |
|
|
17 // http://sourceware.cygnus.com/ecos |
|
|
18 // |
|
|
19 // Software distributed under the License is distributed on an "AS IS" |
|
|
20 // basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the |
|
|
21 // License for the specific language governing rights and limitations under |
|
|
22 // the License. |
|
|
23 // |
|
|
24 // The Original Code is eCos - Embedded Cygnus Operating System, released |
|
|
25 // September 30, 1998. |
|
|
26 // |
|
|
27 // The Initial Developer of the Original Code is Cygnus. Portions created |
|
|
28 // by Cygnus are Copyright (C) 1998 Cygnus Solutions. All Rights Reserved. |
|
|
29 // ------------------------------------------- |
|
|
30 // |
|
|
31 //####COPYRIGHTEND#### |
|
|
32 //========================================================================== |
|
|
33 //#####DESCRIPTIONBEGIN#### |
|
|
34 // |
|
|
35 // Author(s): nickg |
|
|
36 // Contributors: nickg |
|
|
37 // Date: 1997-09-09 |
|
|
38 // Purpose: Define Interrupt class interfaces |
|
|
39 // Description: The classes defined here provide the APIs for handling |
|
|
40 // interrupts. |
|
|
41 // Usage: #include "intr.hxx" |
|
|
42 // |
|
|
43 // |
|
|
44 //####DESCRIPTIONEND#### |
|
|
45 // |
|
|
46 //========================================================================== |
|
|
47 |
|
|
48 #include <cyg/kernel/ktypes.h> |
|
|
49 |
|
|
50 // ------------------------------------------------------------------------- |
|
|
51 // Function prototype typedefs |
|
|
52 |
|
|
53 |
|
|
54 // VSR = Vector Service Routine. This is the code attached directly to an |
|
|
55 // interrupt vector. It is very architecture/platform specific and usually |
|
|
56 // must be written in assembler. |
|
|
57 |
|
|
58 typedef void cyg_VSR(); |
|
|
59 |
|
|
60 // ISR = Interrupt Service Routine. This is called from the default |
|
|
61 // VSR in response to an interrupt. It may access shared data but may |
|
|
62 // not call kernel routines. The return value may be |
|
|
63 // Cyg_Interrupt::HANDLED and/or Cyg_Interrupt::CALL_DSR. |
|
|
64 |
|
|
65 typedef cyg_uint32 cyg_ISR(cyg_vector vector, CYG_ADDRWORD data); |
|
|
66 |
|
|
67 // DSR = Deferred Service Routine. This is called if the ISR returns |
|
|
68 // the Cyg_Interrupt::CALL_DSR bit. It is called at a "safe" point in |
|
|
69 // the kernel where it may make calls on kernel routines. The count |
|
|
70 // argument indicates how many times the ISR has asked for the DSR to |
|
|
71 // be posted since the last time the DSR ran. |
|
|
72 |
|
|
73 typedef void cyg_DSR(cyg_vector vector, cyg_ucount32 count, CYG_ADDRWORD data); |
|
|
74 |
|
|
75 // ------------------------------------------------------------------------- |
|
|
76 // Include HAL definitions |
|
|
77 |
|
|
78 class Cyg_Interrupt; |
|
|
79 |
|
|
80 #include <cyg/hal/hal_arch.h> |
|
|
81 |
|
|
82 #include <cyg/hal/hal_intr.h> |
|
|
83 |
|
|
84 externC void interrupt_end( |
|
|
85 cyg_uint32 isr_ret, |
|
|
86 Cyg_Interrupt *intr, |
|
|
87 HAL_SavedRegisters *ctx |
|
|
88 ); |
|
|
89 |
|
|
90 // ------------------------------------------------------------------------- |
|
|
91 // Interrupt class. This both represents each interrupt and provides a static |
|
|
92 // interface for controlling the interrupt hardware. |
|
|
93 |
|
|
94 class Cyg_Interrupt |
|
|
95 { |
|
|
96 |
|
|
97 friend class Cyg_Scheduler; |
|
|
98 friend void interrupt_end( cyg_uint32, |
|
|
99 Cyg_Interrupt *, |
|
|
100 HAL_SavedRegisters *); |
|
|
101 |
|
|
102 cyg_vector vector; // Interrupt vector |
|
|
103 |
|
|
104 cyg_priority priority; // Queuing priority |
|
|
105 |
|
|
106 cyg_ISR *isr; // Pointer to ISR |
|
|
107 |
|
|
108 cyg_DSR *dsr; // Pointer to DSR |
|
|
109 |
|
|
110 CYG_ADDRWORD data; // Data pointer |
|
|
111 |
|
|
112 |
|
|
113 |
|
|
114 // DSR handling interface called by the scheduler |
|
|
115 |
|
|
116 // Check for pending DSRs |
|
|
117 static cyg_bool DSRs_pending(); |
|
|
118 |
|
|
119 // Call any pending DSRs |
|
|
120 static void call_pending_DSRs(); |
|
|
121 |
|
|
122 void post_dsr(); // Post the DSR for this interrupt |
|
|
123 |
|
|
124 // Data structures for handling DSR calls. We implement two DSR |
|
|
125 // handling mechanisms, a list based one and a table based |
|
|
126 // one. The list based mechanism is safe with respect to temporary |
|
|
127 // overloads and will not run out of resource. However it requires |
|
|
128 // extra data per interrupt object, and interrupts must be turned |
|
|
129 // off briefly when delivering the DSR. The table based mechanism |
|
|
130 // does not need unnecessary interrupt switching, but may be prone |
|
|
131 // to overflow on overload. However, since a correctly programmed |
|
|
132 // real time application should not experience such a condition, |
|
|
133 // the table based mechanism is more efficient for real use. The |
|
|
134 // list based mechainsm is enabled by default since it is safer to |
|
|
135 // use during development. |
|
|
136 |
|
|
137 #ifdef CYGIMP_KERNEL_INTERRUPTS_DSRS_TABLE |
|
|
138 |
|
|
139 static Cyg_Interrupt *dsr_table[CYGNUM_KERNEL_INTERRUPTS_DSRS_TABLE_SIZE]; |
|
|
140 |
|
|
141 static cyg_ucount32 dsr_table_head; |
|
|
142 |
|
|
143 static cyg_ucount32 dsr_table_tail; |
|
|
144 |
|
|
145 #endif |
|
|
146 #ifdef CYGIMP_KERNEL_INTERRUPTS_DSRS_LIST |
|
|
147 |
|
|
148 cyg_ucount32 dsr_count; // Number of DSR posts made |
|
|
149 |
|
|
150 Cyg_Interrupt *next_dsr; // next DSR in list |
|
|
151 |
|
|
152 static Cyg_Interrupt *dsr_list; // static list of pending DSRs |
|
|
153 |
|
|
154 #endif |
|
|
155 |
|
|
156 #ifdef CYGIMP_KERNEL_INTERRUPTS_CHAIN |
|
|
157 |
|
|
158 // The default mechanism for handling interrupts is to attach just |
|
|
159 // one Interrupt object to each vector. In some cases, and on some |
|
|
160 // hardware, this is not possible, and each vector must carry a chain |
|
|
161 // of interrupts. |
|
|
162 |
|
|
163 Cyg_Interrupt *next; // Next Interrupt in list |
|
|
164 |
|
|
165 // Chaining ISR inserted in HAL vector |
|
|
166 static cyg_uint32 chain_isr(cyg_vector vector, CYG_ADDRWORD data); |
|
|
167 |
|
|
168 // Table of interrupt chains |
|
|
169 static Cyg_Interrupt *chain_list[CYG_ISR_COUNT]; |
|
|
170 |
|
|
171 #endif |
|
|
172 |
|
|
173 public: |
|
|
174 |
|
|
175 Cyg_Interrupt // Initialize interrupt |
|
|
176 ( |
|
|
177 cyg_vector vector, // Vector to attach to |
|
|
178 cyg_priority priority, // Queue priority |
|
|
179 CYG_ADDRWORD data, // Data pointer |
|
|
180 cyg_ISR *isr, // Interrupt Service Routine |
|
|
181 cyg_DSR *dsr // Deferred Service Routine |
|
|
182 ); |
|
|
183 |
|
|
184 ~Cyg_Interrupt(); |
|
|
185 |
|
|
186 // ISR return values |
|
|
187 enum { |
|
|
188 HANDLED = 1, // Interrupt was handled |
|
|
189 CALL_DSR = 2 // Schedule DSR |
|
|
190 }; |
|
|
191 |
|
|
192 // Interrupt management |
|
|
193 |
|
|
194 void attach(); // Attach to vector |
|
|
195 |
|
|
196 |
|
|
197 void detach(); // Detach from vector |
|
|
198 |
|
|
199 |
|
|
200 // Static Interrupt management functions |
|
|
201 |
|
|
202 // Get the current service routine |
|
|
203 static void get_vsr(cyg_vector vector, cyg_VSR **vsr); |
|
|
204 |
|
|
205 // Install a vector service routine |
|
|
206 static void set_vsr( |
|
|
207 cyg_vector vector, // hardware vector to replace |
|
|
208 cyg_VSR *vsr, // my new service routine |
|
|
209 cyg_VSR **old = NULL // pointer to old vsr, if required |
|
|
210 ); |
|
|
211 |
|
|
212 |
|
|
213 // Static interrupt masking functions |
|
|
214 |
|
|
215 // Disable interrupts at the CPU |
|
|
216 static void disable_interrupts(); |
|
|
217 |
|
|
218 // Re-enable CPU interrupts |
|
|
219 static void enable_interrupts(); |
|
|
220 |
|
|
221 // Are interrupts enabled at the CPU? |
|
|
222 static inline cyg_bool interrupts_enabled() |
|
|
223 { |
|
|
224 CYG_WORD result; // needs to be register sized |
|
|
225 HAL_QUERY_INTERRUPTS( result ); |
|
|
226 return (0 != result); |
|
|
227 } |
|
|
228 |
|
|
229 // Get the vector for the following calls |
|
|
230 inline cyg_vector get_vector() |
|
|
231 { |
|
|
232 return vector; |
|
|
233 } |
|
|
234 |
|
|
235 // Static PIC control functions |
|
|
236 |
|
|
237 // Mask a specific interrupt in a PIC |
|
|
238 static void mask_interrupt(cyg_vector vector); |
|
|
239 |
|
|
240 // Clear PIC mask |
|
|
241 static void unmask_interrupt(cyg_vector vector); |
|
|
242 |
|
|
243 // Acknowledge interrupt at PIC |
|
|
244 static void acknowledge_interrupt(cyg_vector vector); |
|
|
245 |
|
|
246 // Change interrupt detection at PIC |
|
|
247 static void configure_interrupt( |
|
|
248 cyg_vector vector, // vector to control |
|
|
249 cyg_bool level, // level or edge triggered |
|
|
250 cyg_bool up // hi/lo level, rising/falling edge |
|
|
251 ); |
|
|
252 |
|
|
253 }; |
|
|
254 |
|
|
255 #ifdef CYGIMP_KERNEL_INTERRUPTS_DSRS |
|
|
256 // ------------------------------------------------------------------------- |
|
|
257 // Check for pending DSRs |
|
|
258 |
|
|
259 inline cyg_bool Cyg_Interrupt::DSRs_pending() |
|
|
260 { |
|
|
261 #ifdef CYGIMP_KERNEL_INTERRUPTS_DSRS_TABLE |
|
|
262 |
|
|
263 return dsr_table_head != dsr_table_tail; |
|
|
264 |
|
|
265 #endif |
|
|
266 #ifdef CYGIMP_KERNEL_INTERRUPTS_DSRS_LIST |
|
|
267 |
|
|
268 return dsr_list != NULL; |
|
|
269 |
|
|
270 #endif |
|
|
271 }; |
|
|
272 #endif // CYGIMP_KERNEL_INTERRUPTS_DSRS |
|
|
273 |
|
|
274 // ------------------------------------------------------------------------- |
|
|
275 #endif // ifndef CYGONCE_KERNEL_INTR_HXX |
|
|
276 // EOF intr.hxx |