|
2
|
1 //========================================================================== |
|
|
2 // |
|
|
3 // drv_api.c |
|
|
4 // |
|
|
5 // Driver API for non-kernel configurations |
|
|
6 // |
|
|
7 //========================================================================== |
|
|
8 //####COPYRIGHTBEGIN#### |
|
|
9 // |
|
|
10 // ------------------------------------------- |
|
|
11 // The contents of this file are subject to the Cygnus eCos Public License |
|
|
12 // Version 1.0 (the "License"); you may not use this file except in |
|
|
13 // compliance with the License. You may obtain a copy of the License at |
|
|
14 // http://sourceware.cygnus.com/ecos |
|
|
15 // |
|
|
16 // Software distributed under the License is distributed on an "AS IS" |
|
|
17 // basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the |
|
|
18 // License for the specific language governing rights and limitations under |
|
|
19 // the License. |
|
|
20 // |
|
|
21 // The Original Code is eCos - Embedded Cygnus Operating System, released |
|
|
22 // September 30, 1998. |
|
|
23 // |
|
|
24 // The Initial Developer of the Original Code is Cygnus. Portions created |
|
|
25 // by Cygnus are Copyright (C) 1998, 1999 Cygnus Solutions. |
|
|
26 // All Rights Reserved. |
|
|
27 // ------------------------------------------- |
|
|
28 // |
|
|
29 //####COPYRIGHTEND#### |
|
|
30 //========================================================================== |
|
|
31 //#####DESCRIPTIONBEGIN#### |
|
|
32 // |
|
|
33 // Author(s): Nick Garnett |
|
|
34 // Date: 1999-02-24 |
|
|
35 // Purpose: Driver API for non-kernel configurations |
|
|
36 // Description: These functions are used to support drivers when the kernel |
|
|
37 // is not present. |
|
|
38 // |
|
|
39 // |
|
|
40 // |
|
|
41 //####DESCRIPTIONEND#### |
|
|
42 // |
|
|
43 //========================================================================== |
|
|
44 |
|
|
45 #include <pkgconf/system.h> |
|
|
46 |
|
|
47 #ifndef CYGPKG_KERNEL |
|
|
48 |
|
|
49 #include <cyg/infra/cyg_type.h> |
|
|
50 #include <cyg/infra/cyg_trac.h> |
|
|
51 #include <cyg/infra/cyg_ass.h> |
|
|
52 |
|
|
53 #include <pkgconf/hal.h> |
|
|
54 #include <cyg/hal/drv_api.h> |
|
|
55 |
|
|
56 #include <cyg/hal/hal_arch.h> |
|
|
57 #include <cyg/hal/hal_intr.h> |
|
|
58 |
|
|
59 //-------------------------------------------------------------------------- |
|
|
60 // Statics |
|
|
61 |
|
|
62 static volatile cyg_int32 isr_disable_counter; // ISR disable counter |
|
|
63 |
|
|
64 volatile cyg_int32 dsr_disable_counter asm("cyg_scheduler_sched_lock"); // DSR disable counter |
|
|
65 |
|
|
66 static volatile cyg_interrupt *dsr_list; // List of pending DSRs |
|
|
67 |
|
|
68 #ifdef CYGIMP_HAL_COMMON_INTERRUPTS_CHAIN |
|
|
69 |
|
|
70 cyg_interrupt *chain_list[CYGNUM_HAL_ISR_COUNT]; |
|
|
71 |
|
|
72 #endif |
|
|
73 |
|
|
74 //-------------------------------------------------------------------------- |
|
|
75 // DSR handling functions. |
|
|
76 // post_dsr() places a DSR on the list of DSRs to be called. |
|
|
77 // call_dsrs() calls the DSRs. |
|
|
78 |
|
|
79 static void post_dsr( cyg_interrupt *intr ) |
|
|
80 { |
|
|
81 CYG_INTERRUPT_STATE old_intr; |
|
|
82 |
|
|
83 CYG_REPORT_FUNCTION(); |
|
|
84 |
|
|
85 HAL_DISABLE_INTERRUPTS(old_intr); |
|
|
86 |
|
|
87 if( intr->dsr_count++ == 0 ) |
|
|
88 { |
|
|
89 intr->next_dsr = dsr_list; |
|
|
90 dsr_list = intr; |
|
|
91 } |
|
|
92 |
|
|
93 HAL_RESTORE_INTERRUPTS(old_intr); |
|
|
94 |
|
|
95 CYG_REPORT_RETURN(); |
|
|
96 } |
|
|
97 |
|
|
98 static void call_dsrs(void) |
|
|
99 { |
|
|
100 CYG_REPORT_FUNCTION(); |
|
|
101 |
|
|
102 while( dsr_list != NULL ) |
|
|
103 { |
|
|
104 volatile cyg_interrupt *intr; |
|
|
105 cyg_int32 count; |
|
|
106 CYG_INTERRUPT_STATE old_intr; |
|
|
107 |
|
|
108 HAL_DISABLE_INTERRUPTS(old_intr); |
|
|
109 |
|
|
110 intr = dsr_list; |
|
|
111 dsr_list = intr->next_dsr; |
|
|
112 count = intr->dsr_count; |
|
|
113 intr->dsr_count = 0; |
|
|
114 |
|
|
115 HAL_RESTORE_INTERRUPTS(old_intr); |
|
|
116 |
|
|
117 intr->dsr( intr->vector, count, (CYG_ADDRWORD)intr->data ); |
|
|
118 } |
|
|
119 |
|
|
120 CYG_REPORT_RETURN(); |
|
|
121 |
|
|
122 } |
|
|
123 |
|
|
124 //-------------------------------------------------------------------------- |
|
|
125 // Interrupt end function called from HAL VSR to tidy up. This is where |
|
|
126 // DSRs will be called if necessary. |
|
|
127 |
|
|
128 externC void |
|
|
129 interrupt_end( |
|
|
130 cyg_uint32 isr_ret, |
|
|
131 cyg_interrupt *intr, |
|
|
132 HAL_SavedRegisters *regs |
|
|
133 ) |
|
|
134 { |
|
|
135 CYG_REPORT_FUNCTION(); |
|
|
136 |
|
|
137 #ifndef CYGIMP_HAL_COMMON_INTERRUPTS_CHAIN |
|
|
138 |
|
|
139 // Only do this if we are in a non-chained configuration. |
|
|
140 // If we are chained, then chain_isr will do the DSR |
|
|
141 // posting. |
|
|
142 |
|
|
143 if( isr_ret & CYG_ISR_CALL_DSR && intr != NULL ) post_dsr(intr); |
|
|
144 |
|
|
145 #endif |
|
|
146 |
|
|
147 if( dsr_disable_counter == 0 ) call_dsrs(); |
|
|
148 |
|
|
149 CYG_REPORT_RETURN(); |
|
|
150 } |
|
|
151 |
|
|
152 //-------------------------------------------------------------------------- |
|
|
153 // ISR for handling chained interrupts. |
|
|
154 |
|
|
155 #ifdef CYGIMP_HAL_COMMON_INTERRUPTS_CHAIN |
|
|
156 |
|
|
157 cyg_uint32 chain_isr(cyg_vector_t vector, CYG_ADDRWORD data) |
|
|
158 { |
|
|
159 CYG_REPORT_FUNCTION(); |
|
|
160 |
|
|
161 cyg_interrupt *p = *(cyg_interrupt **)data; |
|
|
162 |
|
|
163 while( p != NULL ) |
|
|
164 { |
|
|
165 if( p->vector == vector ) |
|
|
166 { |
|
|
167 register cyg_uint32 isr_ret = p->isr(vector, p->data); |
|
|
168 |
|
|
169 if( isr_ret & CYG_ISR_CALL_DSR ) post_dsr(p); |
|
|
170 |
|
|
171 if( isr_ret & CYG_ISR_HANDLED ) break; |
|
|
172 } |
|
|
173 |
|
|
174 p = p->next; |
|
|
175 } |
|
|
176 |
|
|
177 CYG_REPORT_RETURN(); |
|
|
178 |
|
|
179 return 0; |
|
|
180 } |
|
|
181 |
|
|
182 #endif |
|
|
183 |
|
|
184 //-------------------------------------------------------------------------- |
|
|
185 // ISR lock. This disables interrupts and keeps a count of the number |
|
|
186 // times it has been called. |
|
|
187 |
|
|
188 externC void cyg_drv_isr_lock() |
|
|
189 { |
|
|
190 CYG_INTERRUPT_STATE dummy; |
|
|
191 |
|
|
192 CYG_REPORT_FUNCTION(); |
|
|
193 |
|
|
194 HAL_DISABLE_INTERRUPTS(dummy); |
|
|
195 |
|
|
196 CYG_ASSERT( isr_disable_counter >= 0 , "Disable counter negative"); |
|
|
197 |
|
|
198 isr_disable_counter++; |
|
|
199 |
|
|
200 CYG_REPORT_RETURN(); |
|
|
201 } |
|
|
202 |
|
|
203 //-------------------------------------------------------------------------- |
|
|
204 // Unlock ISRs. This decrements the count and re-enables interrupts if it |
|
|
205 // goes zero. |
|
|
206 |
|
|
207 externC void cyg_drv_isr_unlock() |
|
|
208 { |
|
|
209 CYG_REPORT_FUNCTION(); |
|
|
210 |
|
|
211 CYG_ASSERT( isr_disable_counter > 0 , "Disable counter not greater than zero"); |
|
|
212 |
|
|
213 isr_disable_counter--; |
|
|
214 |
|
|
215 if ( isr_disable_counter == 0 ) |
|
|
216 { |
|
|
217 HAL_ENABLE_INTERRUPTS(); |
|
|
218 } |
|
|
219 |
|
|
220 CYG_REPORT_RETURN(); |
|
|
221 } |
|
|
222 |
|
|
223 //-------------------------------------------------------------------------- |
|
|
224 // Lock DSR lock. Simply increment the counter. |
|
|
225 |
|
|
226 externC void cyg_drv_dsr_lock() |
|
|
227 { |
|
|
228 CYG_REPORT_FUNCTION(); |
|
|
229 |
|
|
230 dsr_disable_counter++; |
|
|
231 |
|
|
232 CYG_REPORT_RETURN(); |
|
|
233 } |
|
|
234 |
|
|
235 //-------------------------------------------------------------------------- |
|
|
236 // Unlock DSR lock. If the counter is about to go zero, call any pending |
|
|
237 // DSRs and then zero the counter. |
|
|
238 |
|
|
239 externC void cyg_drv_dsr_unlock() |
|
|
240 { |
|
|
241 CYG_REPORT_FUNCTION(); |
|
|
242 |
|
|
243 do |
|
|
244 { |
|
|
245 if( dsr_disable_counter == 1 ) |
|
|
246 { |
|
|
247 call_dsrs(); |
|
|
248 } |
|
|
249 |
|
|
250 HAL_REORDER_BARRIER(); |
|
|
251 |
|
|
252 dsr_disable_counter = 0; |
|
|
253 |
|
|
254 HAL_REORDER_BARRIER(); |
|
|
255 |
|
|
256 // Check that no DSRs have been posted between calling |
|
|
257 // call_dsrs() and zeroing dsr_disable_counter. If so, |
|
|
258 // loop back and call them. |
|
|
259 |
|
|
260 if( dsr_list != NULL ) |
|
|
261 { |
|
|
262 dsr_disable_counter = 1; |
|
|
263 continue; |
|
|
264 } |
|
|
265 |
|
|
266 CYG_REPORT_RETURN(); |
|
|
267 |
|
|
268 return; |
|
|
269 |
|
|
270 } while(1); |
|
|
271 |
|
|
272 CYG_FAIL( "Should not be executed" ); |
|
|
273 } |
|
|
274 |
|
|
275 //-------------------------------------------------------------------------- |
|
|
276 // Initialize a mutex. |
|
|
277 |
|
|
278 externC void cyg_drv_mutex_init( cyg_drv_mutex_t *mutex ) |
|
|
279 { |
|
|
280 CYG_REPORT_FUNCTION(); |
|
|
281 |
|
|
282 mutex->lock = 0; |
|
|
283 |
|
|
284 CYG_REPORT_RETURN(); |
|
|
285 } |
|
|
286 |
|
|
287 //-------------------------------------------------------------------------- |
|
|
288 // Destroy a mutex. |
|
|
289 |
|
|
290 externC void cyg_drv_mutex_destroy( cyg_drv_mutex_t *mutex ) |
|
|
291 { |
|
|
292 CYG_REPORT_FUNCTION(); |
|
|
293 |
|
|
294 mutex->lock = -1; |
|
|
295 |
|
|
296 CYG_REPORT_RETURN(); |
|
|
297 } |
|
|
298 |
|
|
299 //-------------------------------------------------------------------------- |
|
|
300 // Lock a mutex. We check that we are not trying to lock a locked or |
|
|
301 // destroyed mutex and if not, set it locked. |
|
|
302 |
|
|
303 externC cyg_bool_t cyg_drv_mutex_lock( cyg_drv_mutex_t *mutex ) |
|
|
304 { |
|
|
305 CYG_REPORT_FUNCTION(); |
|
|
306 |
|
|
307 CYG_ASSERT( mutex->lock == 0 , "Trying to lock locked mutex"); |
|
|
308 |
|
|
309 mutex->lock = 1; |
|
|
310 |
|
|
311 CYG_REPORT_RETURN(); |
|
|
312 |
|
|
313 return true; |
|
|
314 } |
|
|
315 |
|
|
316 //-------------------------------------------------------------------------- |
|
|
317 // Attempt to claim a mutex, and return if it cannot be. |
|
|
318 |
|
|
319 externC cyg_bool_t cyg_drv_mutex_trylock( cyg_drv_mutex_t *mutex ) |
|
|
320 { |
|
|
321 cyg_bool_t result = true; |
|
|
322 |
|
|
323 CYG_REPORT_FUNCTION(); |
|
|
324 |
|
|
325 if( mutex->lock == 1 ) result = false; |
|
|
326 |
|
|
327 CYG_REPORT_RETURN(); |
|
|
328 |
|
|
329 return result; |
|
|
330 } |
|
|
331 |
|
|
332 //-------------------------------------------------------------------------- |
|
|
333 // Unlock a mutex. We check that the mutex is actually locked before doing |
|
|
334 // this. |
|
|
335 |
|
|
336 externC void cyg_drv_mutex_unlock( cyg_drv_mutex_t *mutex ) |
|
|
337 { |
|
|
338 CYG_REPORT_FUNCTION(); |
|
|
339 |
|
|
340 CYG_ASSERT( mutex->lock == 1 , "Trying to unlock unlocked mutex"); |
|
|
341 |
|
|
342 mutex->lock = 0; |
|
|
343 |
|
|
344 CYG_REPORT_RETURN(); |
|
|
345 } |
|
|
346 |
|
|
347 //-------------------------------------------------------------------------- |
|
|
348 // Release all threads waiting for the mutex. |
|
|
349 // This is really for threads, so we do nothing here. |
|
|
350 |
|
|
351 externC void cyg_drv_mutex_release( cyg_drv_mutex_t *mutex ) |
|
|
352 { |
|
|
353 CYG_REPORT_FUNCTION(); |
|
|
354 |
|
|
355 |
|
|
356 |
|
|
357 CYG_REPORT_RETURN(); |
|
|
358 } |
|
|
359 |
|
|
360 |
|
|
361 //-------------------------------------------------------------------------- |
|
|
362 // Initialized a condition variable. |
|
|
363 |
|
|
364 externC void cyg_drv_cond_init( cyg_drv_cond_t *cond, cyg_drv_mutex_t *mutex ) |
|
|
365 { |
|
|
366 CYG_REPORT_FUNCTION(); |
|
|
367 |
|
|
368 cond->wait = 0; |
|
|
369 cond->mutex = mutex; |
|
|
370 |
|
|
371 CYG_REPORT_RETURN(); |
|
|
372 } |
|
|
373 |
|
|
374 |
|
|
375 //-------------------------------------------------------------------------- |
|
|
376 // Destroy a condition variable. |
|
|
377 |
|
|
378 externC void cyg_drv_cond_destroy( cyg_drv_cond_t *cond ) |
|
|
379 { |
|
|
380 CYG_REPORT_FUNCTION(); |
|
|
381 |
|
|
382 cond->wait = -1; |
|
|
383 cond->mutex = NULL; |
|
|
384 |
|
|
385 CYG_REPORT_RETURN(); |
|
|
386 } |
|
|
387 |
|
|
388 // ------------------------------------------------------------------------- |
|
|
389 // Wait for a condition variable to be signalled. We simply busy wait |
|
|
390 // polling the condition variable's wait member until a DSR sets it to |
|
|
391 // 0. Note that the semantics of condition variables means that the |
|
|
392 // wakeup only happens if there is a thread actually waiting on the CV |
|
|
393 // when the signal is sent. |
|
|
394 |
|
|
395 externC void cyg_drv_cond_wait( cyg_drv_cond_t *cond ) |
|
|
396 { |
|
|
397 CYG_REPORT_FUNCTION(); |
|
|
398 |
|
|
399 CYG_ASSERT( cond->mutex != NULL, "Uninitialized condition variable"); |
|
|
400 CYG_ASSERT( cond->mutex->lock, "Mutex not locked"); |
|
|
401 |
|
|
402 cyg_drv_dsr_lock(); |
|
|
403 |
|
|
404 cond->wait = 1; |
|
|
405 |
|
|
406 while( cond->wait == 1 ) |
|
|
407 { |
|
|
408 // While looping we call call_dsrs() to service any DSRs that |
|
|
409 // get posted. One of these will make the call to cond_signal |
|
|
410 // to break us out of this loop. If we do not have the DSR |
|
|
411 // lock claimed, then a race condition could occur and keep us |
|
|
412 // stuck here forever. |
|
|
413 |
|
|
414 call_dsrs(); |
|
|
415 } |
|
|
416 |
|
|
417 cyg_drv_dsr_unlock(); |
|
|
418 |
|
|
419 CYG_REPORT_RETURN(); |
|
|
420 } |
|
|
421 |
|
|
422 //-------------------------------------------------------------------------- |
|
|
423 // Signal a condition variable. This sets the wait member to zero, which |
|
|
424 // has no effect when there is no waiter, but will wake up any waiting |
|
|
425 // thread. |
|
|
426 |
|
|
427 externC void cyg_drv_cond_signal( cyg_drv_cond_t *cond ) |
|
|
428 { |
|
|
429 CYG_REPORT_FUNCTION(); |
|
|
430 |
|
|
431 cond->wait = 0; |
|
|
432 |
|
|
433 CYG_REPORT_RETURN(); |
|
|
434 } |
|
|
435 |
|
|
436 |
|
|
437 //-------------------------------------------------------------------------- |
|
|
438 // Broadcast to condition variable. This is exactly the same a signal since |
|
|
439 // there can only be one waiter. |
|
|
440 |
|
|
441 externC void cyg_drv_cond_broadcast( cyg_drv_cond_t *cond ) |
|
|
442 { |
|
|
443 CYG_REPORT_FUNCTION(); |
|
|
444 |
|
|
445 cond->wait = 0; |
|
|
446 |
|
|
447 CYG_REPORT_RETURN(); |
|
|
448 } |
|
|
449 |
|
|
450 |
|
|
451 //-------------------------------------------------------------------------- |
|
|
452 // Create an interrupt object. |
|
|
453 |
|
|
454 externC void cyg_drv_interrupt_create( |
|
|
455 cyg_vector_t vector, |
|
|
456 cyg_priority_t priority, |
|
|
457 cyg_addrword_t data, |
|
|
458 cyg_ISR_t *isr, |
|
|
459 cyg_DSR_t *dsr, |
|
|
460 cyg_handle_t *handle, |
|
|
461 cyg_interrupt *intr |
|
|
462 ) |
|
|
463 { |
|
|
464 CYG_REPORT_FUNCTION(); |
|
|
465 |
|
|
466 intr->vector = vector; |
|
|
467 intr->priority = priority; |
|
|
468 intr->isr = isr; |
|
|
469 intr->dsr = dsr; |
|
|
470 intr->data = data; |
|
|
471 intr->next_dsr = NULL; |
|
|
472 intr->dsr_count = 0; |
|
|
473 |
|
|
474 #ifdef CYGIMP_HAL_COMMON_INTERRUPTS_CHAIN |
|
|
475 |
|
|
476 intr->next = NULL; |
|
|
477 |
|
|
478 #endif |
|
|
479 |
|
|
480 *handle = (cyg_handle_t)intr; |
|
|
481 |
|
|
482 CYG_REPORT_RETURN(); |
|
|
483 } |
|
|
484 |
|
|
485 //-------------------------------------------------------------------------- |
|
|
486 // Delete an interrupt object. This merely ensures that it is detached from |
|
|
487 // the vector. |
|
|
488 |
|
|
489 externC void cyg_drv_interrupt_delete( cyg_handle_t interrupt ) |
|
|
490 { |
|
|
491 CYG_REPORT_FUNCTION(); |
|
|
492 |
|
|
493 cyg_drv_interrupt_detach( interrupt ); |
|
|
494 |
|
|
495 CYG_REPORT_RETURN(); |
|
|
496 } |
|
|
497 |
|
|
498 //-------------------------------------------------------------------------- |
|
|
499 // |
|
|
500 |
|
|
501 externC void cyg_drv_interrupt_attach( cyg_handle_t interrupt ) |
|
|
502 { |
|
|
503 cyg_interrupt *intr = (cyg_interrupt *)interrupt; |
|
|
504 |
|
|
505 CYG_REPORT_FUNCTION(); |
|
|
506 |
|
|
507 CYG_ASSERT( intr->vector >= CYGNUM_HAL_ISR_MIN, "Invalid vector"); |
|
|
508 CYG_ASSERT( intr->vector <= CYGNUM_HAL_ISR_MAX, "Invalid vector"); |
|
|
509 |
|
|
510 HAL_INTERRUPT_SET_LEVEL( intr->vector, intr->priority ); |
|
|
511 |
|
|
512 #ifdef CYGIMP_HAL_COMMON_INTERRUPTS_CHAIN |
|
|
513 |
|
|
514 CYG_ASSERT( intr->next == NULL , "cyg_interrupt already on a list"); |
|
|
515 |
|
|
516 cyg_uint32 index; |
|
|
517 |
|
|
518 HAL_TRANSLATE_VECTOR( intr->vector, index ); |
|
|
519 |
|
|
520 if( chain_list[index] == NULL ) |
|
|
521 { |
|
|
522 // First Interrupt on this chain, just assign it and register |
|
|
523 // the chain_isr with the HAL. |
|
|
524 |
|
|
525 chain_list[index] = intr; |
|
|
526 |
|
|
527 HAL_INTERRUPT_ATTACH( intr->vector, chain_isr, &chain_list[index], NULL ); |
|
|
528 } |
|
|
529 else |
|
|
530 { |
|
|
531 // There are already interrupts chained, add this one into the |
|
|
532 // chain in priority order. |
|
|
533 |
|
|
534 Cyg_Interrupt **p = &chain_list[index]; |
|
|
535 |
|
|
536 while( *p != NULL ) |
|
|
537 { |
|
|
538 cyg_interrupt *n = *p; |
|
|
539 |
|
|
540 if( n->priority < intr->priority ) break; |
|
|
541 |
|
|
542 p = &n->next; |
|
|
543 } |
|
|
544 next = *p; |
|
|
545 *p = intr; |
|
|
546 } |
|
|
547 |
|
|
548 #else |
|
|
549 |
|
|
550 HAL_INTERRUPT_ATTACH( intr->vector, intr->isr, intr->data, intr ); |
|
|
551 |
|
|
552 #endif |
|
|
553 |
|
|
554 CYG_REPORT_RETURN(); |
|
|
555 } |
|
|
556 |
|
|
557 |
|
|
558 //-------------------------------------------------------------------------- |
|
|
559 // Detach an interrupt from its vector. |
|
|
560 |
|
|
561 externC void cyg_drv_interrupt_detach( cyg_handle_t interrupt ) |
|
|
562 { |
|
|
563 cyg_interrupt *intr = (cyg_interrupt *)interrupt; |
|
|
564 |
|
|
565 CYG_REPORT_FUNCTION(); |
|
|
566 |
|
|
567 CYG_ASSERT( intr->vector >= CYGNUM_HAL_ISR_MIN, "Invalid vector"); |
|
|
568 CYG_ASSERT( intr->vector <= CYGNUM_HAL_ISR_MAX, "Invalid vector"); |
|
|
569 |
|
|
570 #ifdef CYGIMP_HAL_COMMON_INTERRUPTS_CHAIN |
|
|
571 |
|
|
572 // Remove the interrupt object from the vector chain. |
|
|
573 |
|
|
574 cyg_uint32 index; |
|
|
575 |
|
|
576 HAL_TRANSLATE_VECTOR( vector, index ); |
|
|
577 |
|
|
578 cyg_interrupt **p = &chain_list[index]; |
|
|
579 |
|
|
580 while( *p != NULL ) |
|
|
581 { |
|
|
582 cyg_interrupt *n = *p; |
|
|
583 |
|
|
584 if( n == intr ) |
|
|
585 { |
|
|
586 *p = intr->next; |
|
|
587 break; |
|
|
588 } |
|
|
589 |
|
|
590 p = &n->next; |
|
|
591 } |
|
|
592 |
|
|
593 // If this was the last one, detach the vector. |
|
|
594 |
|
|
595 if( chain_list[index] == NULL ) |
|
|
596 HAL_INTERRUPT_DETACH( intr->vector, chain_isr ); |
|
|
597 |
|
|
598 #else |
|
|
599 |
|
|
600 HAL_INTERRUPT_DETACH( intr->vector, intr->isr ); |
|
|
601 |
|
|
602 #endif |
|
|
603 |
|
|
604 CYG_REPORT_RETURN(); |
|
|
605 } |
|
|
606 |
|
|
607 |
|
|
608 //-------------------------------------------------------------------------- |
|
|
609 // Mask delivery of an interrupt at the interrupt controller. |
|
|
610 |
|
|
611 externC void cyg_drv_interrupt_mask( cyg_vector_t vector ) |
|
|
612 { |
|
|
613 CYG_REPORT_FUNCTION(); |
|
|
614 CYG_REPORT_FUNCARG1("vector=%d", vector); |
|
|
615 |
|
|
616 CYG_ASSERT( vector >= CYGNUM_HAL_ISR_MIN, "Invalid vector"); |
|
|
617 CYG_ASSERT( vector <= CYGNUM_HAL_ISR_MAX, "Invalid vector"); |
|
|
618 |
|
|
619 HAL_INTERRUPT_MASK( vector ); |
|
|
620 |
|
|
621 CYG_REPORT_RETURN(); |
|
|
622 } |
|
|
623 |
|
|
624 //-------------------------------------------------------------------------- |
|
|
625 // Unmask delivery of an interrupt at the interrupt controller. |
|
|
626 |
|
|
627 externC void cyg_drv_interrupt_unmask( cyg_vector_t vector ) |
|
|
628 { |
|
|
629 CYG_REPORT_FUNCTION(); |
|
|
630 |
|
|
631 CYG_ASSERT( vector >= CYGNUM_HAL_ISR_MIN, "Invalid vector"); |
|
|
632 CYG_ASSERT( vector <= CYGNUM_HAL_ISR_MAX, "Invalid vector"); |
|
|
633 |
|
|
634 HAL_INTERRUPT_UNMASK( vector ); |
|
|
635 |
|
|
636 CYG_REPORT_RETURN(); |
|
|
637 } |
|
|
638 |
|
|
639 //-------------------------------------------------------------------------- |
|
|
640 // Acknowledge an interrupt at the controller to allow another interrupt |
|
|
641 // to be delivered. |
|
|
642 |
|
|
643 externC void cyg_drv_interrupt_acknowledge( cyg_vector_t vector ) |
|
|
644 { |
|
|
645 // CYG_REPORT_FUNCTION(); |
|
|
646 |
|
|
647 CYG_ASSERT( vector >= CYGNUM_HAL_ISR_MIN, "Invalid vector"); |
|
|
648 CYG_ASSERT( vector <= CYGNUM_HAL_ISR_MAX, "Invalid vector"); |
|
|
649 |
|
|
650 HAL_INTERRUPT_ACKNOWLEDGE( vector ); |
|
|
651 |
|
|
652 // CYG_REPORT_RETURN(); |
|
|
653 } |
|
|
654 |
|
|
655 //-------------------------------------------------------------------------- |
|
|
656 // Configure interrupt detection parameters. |
|
|
657 |
|
|
658 externC void cyg_drv_interrupt_configure( |
|
|
659 cyg_vector_t vector, |
|
|
660 cyg_bool_t level, |
|
|
661 cyg_bool_t up |
|
|
662 ) |
|
|
663 { |
|
|
664 CYG_REPORT_FUNCTION(); |
|
|
665 CYG_REPORT_FUNCARG3("vector = %d, level = %d, up = %d", vector, level, |
|
|
666 up); |
|
|
667 |
|
|
668 CYG_ASSERT( vector >= CYGNUM_HAL_ISR_MIN, "Invalid vector"); |
|
|
669 CYG_ASSERT( vector <= CYGNUM_HAL_ISR_MAX, "Invalid vector"); |
|
|
670 |
|
|
671 HAL_INTERRUPT_CONFIGURE( vector, level, up ); |
|
|
672 |
|
|
673 CYG_REPORT_RETURN(); |
|
|
674 } |
|
|
675 |
|
|
676 //-------------------------------------------------------------------------- |
|
|
677 // Configure interrupt priority level. |
|
|
678 |
|
|
679 externC void cyg_drv_interrupt_level( cyg_vector_t vector, cyg_priority_t level ) |
|
|
680 { |
|
|
681 CYG_REPORT_FUNCTION(); |
|
|
682 CYG_REPORT_FUNCARG2("vector = %d, level = %d", vector, level); |
|
|
683 |
|
|
684 CYG_ASSERT( vector >= CYGNUM_HAL_ISR_MIN, "Invalid vector"); |
|
|
685 CYG_ASSERT( vector <= CYGNUM_HAL_ISR_MAX, "Invalid vector"); |
|
|
686 |
|
|
687 HAL_INTERRUPT_SET_LEVEL( vector, level ); |
|
|
688 |
|
|
689 CYG_REPORT_RETURN(); |
|
|
690 } |
|
|
691 |
|
|
692 |
|
|
693 // ------------------------------------------------------------------------- |
|
|
694 // Exception delivery function called from the HAL as a result of a |
|
|
695 // hardware exception being raised. |
|
|
696 |
|
|
697 externC void cyg_hal_deliver_exception( CYG_WORD code, CYG_ADDRWORD data ) |
|
|
698 { |
|
|
699 CYG_FAIL(" !!! Exception !!! "); |
|
|
700 } |
|
|
701 |
|
|
702 |
|
|
703 #endif |
|
|
704 |
|
|
705 //-------------------------------------------------------------------------- |
|
|
706 // EOF drv_api.c |