]> git.kernelconcepts.de Git - karo-tx-redboot.git/blob - doc/html/ref/kernel-interrupts.html
RedBoot TX53 Release 2012-02-15
[karo-tx-redboot.git] / doc / html / ref / kernel-interrupts.html
1 <!-- Copyright (C) 2003 Red Hat, Inc.                                -->
2 <!-- This material may be distributed only subject to the terms      -->
3 <!-- and conditions set forth in the Open Publication License, v1.0  -->
4 <!-- or later (the latest version is presently available at          -->
5 <!-- http://www.opencontent.org/openpub/).                           -->
6 <!-- Distribution of the work or derivative of the work in any       -->
7 <!-- standard (paper) book form is prohibited unless prior           -->
8 <!-- permission is obtained from the copyright holder.               -->
9 <HTML
10 ><HEAD
11 ><TITLE
12 >Interrupt Handling</TITLE
13 ><meta name="MSSmartTagsPreventParsing" content="TRUE">
14 <META
15 NAME="GENERATOR"
16 CONTENT="Modular DocBook HTML Stylesheet Version 1.76b+
17 "><LINK
18 REL="HOME"
19 TITLE="eCos Reference Manual"
20 HREF="ecos-ref.html"><LINK
21 REL="UP"
22 TITLE="The eCos Kernel"
23 HREF="kernel.html"><LINK
24 REL="PREVIOUS"
25 TITLE="Scheduler Control"
26 HREF="kernel-schedcontrol.html"><LINK
27 REL="NEXT"
28 TITLE="Kernel Real-time Characterization"
29 HREF="kernel-characterization.html"></HEAD
30 ><BODY
31 CLASS="REFENTRY"
32 BGCOLOR="#FFFFFF"
33 TEXT="#000000"
34 LINK="#0000FF"
35 VLINK="#840084"
36 ALINK="#0000FF"
37 ><DIV
38 CLASS="NAVHEADER"
39 ><TABLE
40 SUMMARY="Header navigation table"
41 WIDTH="100%"
42 BORDER="0"
43 CELLPADDING="0"
44 CELLSPACING="0"
45 ><TR
46 ><TH
47 COLSPAN="3"
48 ALIGN="center"
49 >eCos Reference Manual</TH
50 ></TR
51 ><TR
52 ><TD
53 WIDTH="10%"
54 ALIGN="left"
55 VALIGN="bottom"
56 ><A
57 HREF="kernel-schedcontrol.html"
58 ACCESSKEY="P"
59 >Prev</A
60 ></TD
61 ><TD
62 WIDTH="80%"
63 ALIGN="center"
64 VALIGN="bottom"
65 ></TD
66 ><TD
67 WIDTH="10%"
68 ALIGN="right"
69 VALIGN="bottom"
70 ><A
71 HREF="kernel-characterization.html"
72 ACCESSKEY="N"
73 >Next</A
74 ></TD
75 ></TR
76 ></TABLE
77 ><HR
78 ALIGN="LEFT"
79 WIDTH="100%"></DIV
80 ><H1
81 ><A
82 NAME="KERNEL-INTERRUPTS">Interrupt Handling</H1
83 ><DIV
84 CLASS="REFNAMEDIV"
85 ><A
86 NAME="AEN1834"
87 ></A
88 ><H2
89 >Name</H2
90 >cyg_interrupt_create, cyg_interrupt_delete, cyg_interrupt_attach, cyg_interrupt_detach, cyg_interrupt_configure, cyg_interrupt_acknowledge, cyg_interrupt_enable, cyg_interrupt_disable, cyg_interrupt_mask, cyg_interrupt_mask_intunsafe, cyg_interrupt_unmask, cyg_interrupt_unmask_intunsafe, cyg_interrupt_set_cpu, cyg_interrupt_get_cpu, cyg_interrupt_get_vsr, cyg_interrupt_set_vsr&nbsp;--&nbsp;Manage interrupt handlers</DIV
91 ><DIV
92 CLASS="REFSYNOPSISDIV"
93 ><A
94 NAME="AEN1852"><H2
95 >Synopsis</H2
96 ><DIV
97 CLASS="FUNCSYNOPSIS"
98 ><A
99 NAME="AEN1853"><P
100 ></P
101 ><TABLE
102 BORDER="5"
103 BGCOLOR="#E0E0F0"
104 WIDTH="70%"
105 ><TR
106 ><TD
107 ><PRE
108 CLASS="FUNCSYNOPSISINFO"
109 >#include &lt;cyg/kernel/kapi.h&gt;
110         </PRE
111 ></TD
112 ></TR
113 ></TABLE
114 ><P
115 ><CODE
116 ><CODE
117 CLASS="FUNCDEF"
118 >void cyg_interrupt_create</CODE
119 >(cyg_vector_t vector, cyg_priority_t priority, cyg_addrword_t data, cyg_ISR_t* isr, cyg_DSR_t* dsr, cyg_handle_t* handle, cyg_interrupt* intr);</CODE
120 ></P
121 ><P
122 ><CODE
123 ><CODE
124 CLASS="FUNCDEF"
125 >void cyg_interrupt_delete</CODE
126 >(cyg_handle_t interrupt);</CODE
127 ></P
128 ><P
129 ><CODE
130 ><CODE
131 CLASS="FUNCDEF"
132 >void cyg_interrupt_attach</CODE
133 >(cyg_handle_t interrupt);</CODE
134 ></P
135 ><P
136 ><CODE
137 ><CODE
138 CLASS="FUNCDEF"
139 >void cyg_interrupt_detach</CODE
140 >(cyg_handle_t interrupt);</CODE
141 ></P
142 ><P
143 ><CODE
144 ><CODE
145 CLASS="FUNCDEF"
146 >void cyg_interrupt_configure</CODE
147 >(cyg_vector_t vector, cyg_bool_t level, cyg_bool_t up);</CODE
148 ></P
149 ><P
150 ><CODE
151 ><CODE
152 CLASS="FUNCDEF"
153 >void cyg_interrupt_acknowledge</CODE
154 >(cyg_vector_t vector);</CODE
155 ></P
156 ><P
157 ><CODE
158 ><CODE
159 CLASS="FUNCDEF"
160 >void cyg_interrupt_disable</CODE
161 >(void);</CODE
162 ></P
163 ><P
164 ><CODE
165 ><CODE
166 CLASS="FUNCDEF"
167 >void cyg_interrupt_enable</CODE
168 >(void);</CODE
169 ></P
170 ><P
171 ><CODE
172 ><CODE
173 CLASS="FUNCDEF"
174 >void cyg_interrupt_mask</CODE
175 >(cyg_vector_t vector);</CODE
176 ></P
177 ><P
178 ><CODE
179 ><CODE
180 CLASS="FUNCDEF"
181 >void cyg_interrupt_mask_intunsafe</CODE
182 >(cyg_vector_t vector);</CODE
183 ></P
184 ><P
185 ><CODE
186 ><CODE
187 CLASS="FUNCDEF"
188 >void cyg_interrupt_unmask</CODE
189 >(cyg_vector_t vector);</CODE
190 ></P
191 ><P
192 ><CODE
193 ><CODE
194 CLASS="FUNCDEF"
195 >void cyg_interrupt_unmask_intunsafe</CODE
196 >(cyg_vector_t vector);</CODE
197 ></P
198 ><P
199 ><CODE
200 ><CODE
201 CLASS="FUNCDEF"
202 >void cyg_interrupt_set_cpu</CODE
203 >(cyg_vector_t vector, cyg_cpu_t cpu);</CODE
204 ></P
205 ><P
206 ><CODE
207 ><CODE
208 CLASS="FUNCDEF"
209 >cyg_cpu_t cyg_interrupt_get_cpu</CODE
210 >(cyg_vector_t vector);</CODE
211 ></P
212 ><P
213 ><CODE
214 ><CODE
215 CLASS="FUNCDEF"
216 >void cyg_interrupt_get_vsr</CODE
217 >(cyg_vector_t vector, cyg_VSR_t** vsr);</CODE
218 ></P
219 ><P
220 ><CODE
221 ><CODE
222 CLASS="FUNCDEF"
223 >void cyg_interrupt_set_vsr</CODE
224 >(cyg_vector_t vector, cyg_VSR_t* vsr);</CODE
225 ></P
226 ><P
227 ></P
228 ></DIV
229 ></DIV
230 ><DIV
231 CLASS="REFSECT1"
232 ><A
233 NAME="KERNEL-INTERRUPTS-DESCRIPTION"
234 ></A
235 ><H2
236 >Description</H2
237 ><P
238 >The kernel provides an interface for installing interrupt handlers and
239 controlling when interrupts occur. This functionality is used
240 primarily by eCos device drivers and by any application code that
241 interacts directly with hardware. However in most cases it is better
242 to avoid using this kernel functionality directly, and instead the
243 device driver API provided by the common HAL package should be used.
244 Use of the kernel package is optional, and some applications such as
245 RedBoot work with no need for multiple threads or synchronization
246 primitives. Any code which calls the kernel directly rather than the
247 device driver API will not function in such a configuration. When the
248 kernel package is present the device driver API is implemented as
249 <TT
250 CLASS="LITERAL"
251 >#define</TT
252 >'s to the equivalent kernel calls, otherwise
253 it is implemented inside the common HAL package. The latter
254 implementation can be simpler than the kernel one because there is no
255 need to consider thread preemption and similar issues.
256       </P
257 ><P
258 >The exact details of interrupt handling vary widely between
259 architectures. The functionality provided by the kernel abstracts away
260 from many of the details of the underlying hardware, thus simplifying
261 application development. However this is not always successful. For
262 example, if some hardware does not provide any support at all for
263 masking specific interrupts then calling
264 <TT
265 CLASS="FUNCTION"
266 >cyg_interrupt_mask</TT
267 > may not behave as intended:
268 instead of masking just the one interrupt source it might disable all
269 interrupts, because that is as close to the desired behaviour as is
270 possible given the hardware restrictions. Another possibility is that
271 masking a given interrupt source also affects all lower-priority
272 interrupts, but still allows higher-priority ones. The documentation
273 for the appropriate HAL packages should be consulted for more
274 information about exactly how interrupts are handled on any given
275 hardware. The HAL header files will also contain useful information. 
276       </P
277 ></DIV
278 ><DIV
279 CLASS="REFSECT1"
280 ><A
281 NAME="KERNEL-INTERRUPTS-HANDLERS"
282 ></A
283 ><H2
284 >Interrupt Handlers</H2
285 ><P
286 >Interrupt handlers are created by a call to
287 <TT
288 CLASS="FUNCTION"
289 >cyg_interrupt_create</TT
290 >. This takes the following
291 arguments: 
292       </P
293 ><P
294 ></P
295 ><DIV
296 CLASS="VARIABLELIST"
297 ><DL
298 ><DT
299 >cyg_vector_t <TT
300 CLASS="PARAMETER"
301 ><I
302 >vector</I
303 ></TT
304 ></DT
305 ><DD
306 ><P
307 >The interrupt vector, a small integer, identifies the specific
308 interrupt source. The appropriate hardware documentation or HAL header
309 files should be consulted for details of which vector corresponds to
310 which device.
311           </P
312 ></DD
313 ><DT
314 >cyg_priority_t <TT
315 CLASS="PARAMETER"
316 ><I
317 >priority</I
318 ></TT
319 ></DT
320 ><DD
321 ><P
322 >Some hardware may support interrupt priorities, where a low priority
323 interrupt handler can in turn be interrupted by a higher priority one.
324 Again hardware-specific documentation should be consulted for details
325 about what the valid interrupt priority levels are.
326           </P
327 ></DD
328 ><DT
329 >cyg_addrword_t <TT
330 CLASS="PARAMETER"
331 ><I
332 >data</I
333 ></TT
334 ></DT
335 ><DD
336 ><P
337 >When an interrupt occurs eCos will first call the associated
338 interrupt service routine or ISR, then optionally a deferred service
339 routine or DSR. The <TT
340 CLASS="PARAMETER"
341 ><I
342 >data</I
343 ></TT
344 > argument to
345 <TT
346 CLASS="FUNCTION"
347 >cyg_interrupt_create</TT
348 > will be passed to both these
349 functions. Typically it will be a pointer to some data structure.
350           </P
351 ></DD
352 ><DT
353 >cyg_ISR_t <TT
354 CLASS="PARAMETER"
355 ><I
356 >isr</I
357 ></TT
358 ></DT
359 ><DD
360 ><P
361 >When an interrupt occurs the hardware will transfer control to the
362 appropriate vector service routine or VSR, which is usually provided
363 by eCos. This performs any appropriate processing, for example to work
364 out exactly which interrupt occurred, and then as quickly as possible
365 transfers control the installed ISR. An ISR is a C function which
366 takes the following form:
367           </P
368 ><TABLE
369 BORDER="5"
370 BGCOLOR="#E0E0F0"
371 WIDTH="70%"
372 ><TR
373 ><TD
374 ><PRE
375 CLASS="PROGRAMLISTING"
376 >cyg_uint32
377 isr_function(cyg_vector_t vector, cyg_addrword_t data)
378 {
379     cyg_bool_t dsr_required = 0;
380
381     &#8230;
382
383     return dsr_required ? CYG_ISR_CALL_DSR : CYG_ISR_HANDLED;
384 }
385           </PRE
386 ></TD
387 ></TR
388 ></TABLE
389 ><P
390 >The first argument identifies the particular interrupt source,
391 especially useful if there multiple instances of a given device and a
392 single ISR can be used for several different interrupt vectors. The
393 second argument is the <TT
394 CLASS="PARAMETER"
395 ><I
396 >data</I
397 ></TT
398 > field passed to
399 <TT
400 CLASS="FUNCTION"
401 >cyg_interrupt_create</TT
402 >, usually a pointer to some
403 data structure. The exact conditions under which an ISR runs will
404 depend partly on the hardware and partly on configuration options.
405 Interrupts may currently be disabled globally, especially if the
406 hardware does not support interrupt priorities. Alternatively
407 interrupts may be enabled such that higher priority interrupts are
408 allowed through. The ISR may be running on a separate interrupt stack,
409 or on the stack of whichever thread was running at the time the
410 interrupt happened.
411           </P
412 ><P
413 >A typical ISR will do as little work as possible, just enough to meet
414 the needs of the hardware and then acknowledge the interrupt by
415 calling <TT
416 CLASS="FUNCTION"
417 >cyg_interrupt_acknowledge</TT
418 >. This ensures
419 that interrupts will be quickly reenabled, so higher priority devices
420 can be serviced. For some applications there may be one device which
421 is especially important and whose ISR can take much longer than
422 normal. However eCos device drivers usually will not assume that they
423 are especially important, so their ISRs will be as short as possible.
424           </P
425 ><P
426 >The return value of an ISR is normally one of
427 <TT
428 CLASS="LITERAL"
429 >CYG_ISR_CALL_DSR</TT
430 > or
431 <TT
432 CLASS="LITERAL"
433 >CYG_ISR_HANDLED</TT
434 >. The former indicates that further
435 processing is required at DSR level, and the interrupt handler's DSR
436 will be run as soon as possible. The latter indicates that the
437 interrupt has been fully handled and no further effort is required.
438           </P
439 ><P
440 >An ISR is allowed to make very few kernel calls. It can manipulate the
441 interrupt mask, and on SMP systems it can use spinlocks. However an
442 ISR must not make higher-level kernel calls such as posting to a
443 semaphore, instead any such calls must be made from the DSR. This
444 avoids having to disable interrupts throughout the kernel and thus
445 improves interrupt latency.
446           </P
447 ></DD
448 ><DT
449 >cyg_DSR_t <TT
450 CLASS="PARAMETER"
451 ><I
452 >dsr</I
453 ></TT
454 ></DT
455 ><DD
456 ><P
457 >If an interrupt has occurred and the ISR has returned a value
458 <TT
459 CLASS="LITERAL"
460 >CYG_ISR_CALL_DSR</TT
461 >, the system will call the
462 deferred service routine or DSR associated with this interrupt
463 handler. If the scheduler is not currently locked then the DSR will
464 run immediately. However if the interrupted thread was in the middle
465 of a kernel call and had locked the scheduler, then the DSR will be
466 deferred until the scheduler is again unlocked. This allows the
467 DSR to make certain kernel calls safely, for example posting to a
468 semaphore or signalling a condition variable. A DSR is a C function
469 which takes the following form:
470           </P
471 ><TABLE
472 BORDER="5"
473 BGCOLOR="#E0E0F0"
474 WIDTH="70%"
475 ><TR
476 ><TD
477 ><PRE
478 CLASS="PROGRAMLISTING"
479 >void
480 dsr_function(cyg_vector_t vector,
481              cyg_ucount32 count,
482              cyg_addrword_t data)
483 {
484 }
485           </PRE
486 ></TD
487 ></TR
488 ></TABLE
489 ><P
490 >The first argument identifies the specific interrupt that has caused
491 the DSR to run. The second argument indicates the number of these
492 interrupts that have occurred and for which the ISR requested a DSR.
493 Usually this will be <TT
494 CLASS="LITERAL"
495 >1</TT
496 >, unless the system is
497 suffering from a very heavy load. The third argument is the
498 <TT
499 CLASS="PARAMETER"
500 ><I
501 >data</I
502 ></TT
503 > field passed to
504 <TT
505 CLASS="FUNCTION"
506 >cyg_interrupt_create</TT
507 >. 
508           </P
509 ></DD
510 ><DT
511 >cyg_handle_t* <TT
512 CLASS="PARAMETER"
513 ><I
514 >handle</I
515 ></TT
516 ></DT
517 ><DD
518 ><P
519 >The kernel will return a handle to the newly created interrupt handler
520 via this argument. Subsequent operations on the interrupt handler such
521 as attaching it to the interrupt source will use this handle.
522           </P
523 ></DD
524 ><DT
525 >cyg_interrupt* <TT
526 CLASS="PARAMETER"
527 ><I
528 >intr</I
529 ></TT
530 ></DT
531 ><DD
532 ><P
533 >This provides the kernel with an area of memory for holding this
534 interrupt handler and associated data.
535           </P
536 ></DD
537 ></DL
538 ></DIV
539 ><P
540 >The call to <TT
541 CLASS="FUNCTION"
542 >cyg_interrupt_create</TT
543 > simply fills in
544 a kernel data structure. A typical next step is to call
545 <TT
546 CLASS="FUNCTION"
547 >cyg_interrupt_attach</TT
548 > using the handle returned by
549 the create operation. This makes it possible to have several different
550 interrupt handlers for a given vector, attaching whichever one is
551 currently appropriate. Replacing an interrupt handler requires a call
552 to <TT
553 CLASS="FUNCTION"
554 >cyg_interrupt_detach</TT
555 >, followed by another call
556 to <TT
557 CLASS="FUNCTION"
558 >cyg_interrupt_attach</TT
559 > for the replacement
560 handler. <TT
561 CLASS="FUNCTION"
562 >cyg_interrupt_delete</TT
563 > can be used if an
564 interrupt handler is no longer required.
565       </P
566 ><P
567 >Some hardware may allow for further control over specific interrupts,
568 for example whether an interrupt is level or edge triggered. Any such
569 hardware functionality can be accessed using
570 <TT
571 CLASS="FUNCTION"
572 >cyg_interrupt_configure</TT
573 >: the
574 <TT
575 CLASS="PARAMETER"
576 ><I
577 >level</I
578 ></TT
579 > argument selects between level versus
580 edge triggered; the <TT
581 CLASS="PARAMETER"
582 ><I
583 >up</I
584 ></TT
585 > argument selects between
586 high and low level, or between rising and falling edges.
587       </P
588 ><P
589 >Usually interrupt handlers are created, attached and configured during
590 system initialization, while global interrupts are still disabled. On
591 most hardware it will also be necessary to call
592 <TT
593 CLASS="FUNCTION"
594 >cyg_interrupt_unmask</TT
595 >, since the sensible default
596 for interrupt masking is to ignore any interrupts for which no handler
597 is installed.
598       </P
599 ></DIV
600 ><DIV
601 CLASS="REFSECT1"
602 ><A
603 NAME="KERNEL-INTERRUPTS-ENABLE"
604 ></A
605 ><H2
606 >Controlling Interrupts</H2
607 ><P
608 >eCos provides two ways of controlling whether or not interrupts
609 happen. It is possible to disable and reenable all interrupts
610 globally, using <TT
611 CLASS="FUNCTION"
612 >cyg_interrupt_disable</TT
613 > and
614 <TT
615 CLASS="FUNCTION"
616 >cyg_interrupt_enable</TT
617 >. Typically this works by
618 manipulating state inside the cpu itself, for example setting a flag
619 in a status register or executing special instructions. Alternatively
620 it may be possible to mask a specific interrupt source by writing to
621 one or to several interrupt mask registers. Hardware-specific
622 documentation should be consulted for the exact details of how
623 interrupt masking works, because a full implementation is not possible
624 on all hardware.
625       </P
626 ><P
627 >The primary use for these functions is to allow data to be shared
628 between ISRs and other code such as DSRs or threads. If both a thread
629 and an ISR need to manipulate either a data structure or the hardware
630 itself, there is a possible conflict if an interrupt happens just when
631 the thread is doing such manipulation. Problems can be avoided by the
632 thread either disabling or masking interrupts during the critical
633 region. If this critical region requires only a few instructions then
634 usually it is more efficient to disable interrupts. For larger
635 critical regions it may be more appropriate to use interrupt masking,
636 allowing other interrupts to occur. There are other uses for interrupt
637 masking. For example if a device is not currently being used by the
638 application then it may be desirable to mask all interrupts generated
639 by that device.
640       </P
641 ><P
642 >There are two functions for masking a specific interrupt source,
643 <TT
644 CLASS="FUNCTION"
645 >cyg_interrupt_mask</TT
646 > and
647 <TT
648 CLASS="FUNCTION"
649 >cyg_interrupt_mask_intunsafe</TT
650 >. On typical hardware
651 masking an interrupt is not an atomic operation, so if two threads
652 were to perform interrupt masking operations at the same time there
653 could be problems. <TT
654 CLASS="FUNCTION"
655 >cyg_interrupt_mask</TT
656 > disables
657 all interrupts while it manipulates the interrupt mask. In situations
658 where interrupts are already know to be disabled,
659 <TT
660 CLASS="FUNCTION"
661 >cyg_interrupt_mask_intunsafe</TT
662 > can be used
663 instead. There are matching functions
664 <TT
665 CLASS="FUNCTION"
666 >cyg_interrupt_unmask</TT
667 > and
668 <TT
669 CLASS="FUNCTION"
670 >cyg_interrupt_unmask_intsafe</TT
671 >.
672       </P
673 ></DIV
674 ><DIV
675 CLASS="REFSECT1"
676 ><A
677 NAME="KERNEL-INTERRUPTS-SMP"
678 ></A
679 ><H2
680 >SMP Support</H2
681 ><P
682 >On SMP systems the kernel provides an additional two functions related
683 to interrupt handling. <TT
684 CLASS="FUNCTION"
685 >cyg_interrupt_set_cpu</TT
686 >
687 specifies that a particular hardware interrupt should always be
688 handled on one specific processor in the system. In other words when
689 the interrupt triggers it is only that processor which detects it, and
690 it is only on that processor that the VSR and ISR will run. If a DSR
691 is requested then it will also run on the same CPU. The
692 function <TT
693 CLASS="FUNCTION"
694 >cyg_interrupt_get_cpu</TT
695 > can be used to
696 find out which interrupts are handled on which processor. 
697       </P
698 ></DIV
699 ><DIV
700 CLASS="REFSECT1"
701 ><A
702 NAME="KERNEL-INTERRUPTS-VSR"
703 ></A
704 ><H2
705 >VSR Support</H2
706 ><P
707 >When an interrupt occurs the hardware will transfer control to a piece
708 of code known as the VSR, or Vector Service Routine. By default this
709 code is provided by eCos. Usually it is written in assembler, but on
710 some architectures it may be possible to implement VSRs in C by
711 specifying an interrupt attribute. Compiler documentation should be
712 consulted for more information on this. The default eCos VSR will work
713 out which ISR function should process the interrupt, and set up a C
714 environment suitable for this ISR.
715       </P
716 ><P
717 >For some applications it may be desirable to replace the default eCos
718 VSR and handle some interrupts directly. This minimizes interrupt
719 latency, but it requires application developers to program at a lower
720 level. Usually the best way to write a custom VSR is to copy the
721 existing one supplied by eCos and then make appropriate modifications.
722 The function <TT
723 CLASS="FUNCTION"
724 >cyg_interrupt_get_vsr</TT
725 > can be used to
726 get hold of the current VSR for a given interrupt vector, allowing it
727 to be restored if the custom VSR is no longer required.
728 <TT
729 CLASS="FUNCTION"
730 >cyg_interrupt_set_vsr</TT
731 > can be used to install a
732 replacement VSR. Usually the <TT
733 CLASS="PARAMETER"
734 ><I
735 >vsr</I
736 ></TT
737 > argument will
738 correspond to an exported label in an assembler source file.
739       </P
740 ></DIV
741 ><DIV
742 CLASS="REFSECT1"
743 ><A
744 NAME="KERNEL-INTERRUPTS-CONTEXT"
745 ></A
746 ><H2
747 >Valid contexts</H2
748 ><P
749 >In a typical configuration interrupt handlers are created and attached
750 during system initialization, and never detached or deleted. However
751 it is possible to perform these operations at thread level, if
752 desired. Similarly <TT
753 CLASS="FUNCTION"
754 >cyg_interrupt_configure</TT
755 >,
756 <TT
757 CLASS="FUNCTION"
758 >cyg_interrupt_set_vsr</TT
759 >, and
760 <TT
761 CLASS="FUNCTION"
762 >cyg_interrupt_set_cpu</TT
763 > are usually called only
764 during system initialization, but on typical hardware may be called at
765 any time. <TT
766 CLASS="FUNCTION"
767 >cyg_interrupt_get_vsr</TT
768 > and
769 <TT
770 CLASS="FUNCTION"
771 >cyg_interrupt_get_cpu</TT
772 > may be called at any time.
773       </P
774 ><P
775 >The functions for enabling, disabling, masking and unmasking
776 interrupts can be called in any context, when appropriate. It is the
777 responsibility of application developers to determine when the use of
778 these functions is appropriate.
779       </P
780 ></DIV
781 ><DIV
782 CLASS="NAVFOOTER"
783 ><HR
784 ALIGN="LEFT"
785 WIDTH="100%"><TABLE
786 SUMMARY="Footer navigation table"
787 WIDTH="100%"
788 BORDER="0"
789 CELLPADDING="0"
790 CELLSPACING="0"
791 ><TR
792 ><TD
793 WIDTH="33%"
794 ALIGN="left"
795 VALIGN="top"
796 ><A
797 HREF="kernel-schedcontrol.html"
798 ACCESSKEY="P"
799 >Prev</A
800 ></TD
801 ><TD
802 WIDTH="34%"
803 ALIGN="center"
804 VALIGN="top"
805 ><A
806 HREF="ecos-ref.html"
807 ACCESSKEY="H"
808 >Home</A
809 ></TD
810 ><TD
811 WIDTH="33%"
812 ALIGN="right"
813 VALIGN="top"
814 ><A
815 HREF="kernel-characterization.html"
816 ACCESSKEY="N"
817 >Next</A
818 ></TD
819 ></TR
820 ><TR
821 ><TD
822 WIDTH="33%"
823 ALIGN="left"
824 VALIGN="top"
825 >Scheduler Control</TD
826 ><TD
827 WIDTH="34%"
828 ALIGN="center"
829 VALIGN="top"
830 ><A
831 HREF="kernel.html"
832 ACCESSKEY="U"
833 >Up</A
834 ></TD
835 ><TD
836 WIDTH="33%"
837 ALIGN="right"
838 VALIGN="top"
839 >Kernel Real-time Characterization</TD
840 ></TR
841 ></TABLE
842 ></DIV
843 ></BODY
844 ></HTML
845 >