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. -->
12 >Interrupt Handling</TITLE
13 ><meta name="MSSmartTagsPreventParsing" content="TRUE">
16 CONTENT="Modular DocBook HTML Stylesheet Version 1.76b+
19 TITLE="eCos Reference Manual"
20 HREF="ecos-ref.html"><LINK
22 TITLE="The eCos Kernel"
23 HREF="kernel.html"><LINK
25 TITLE="Scheduler Control"
26 HREF="kernel-schedcontrol.html"><LINK
28 TITLE="Kernel Real-time Characterization"
29 HREF="kernel-characterization.html"></HEAD
40 SUMMARY="Header navigation table"
49 >eCos Reference Manual</TH
57 HREF="kernel-schedcontrol.html"
71 HREF="kernel-characterization.html"
82 NAME="KERNEL-INTERRUPTS">Interrupt Handling</H1
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 -- Manage interrupt handlers</DIV
92 CLASS="REFSYNOPSISDIV"
108 CLASS="FUNCSYNOPSISINFO"
109 >#include <cyg/kernel/kapi.h>
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
125 >void cyg_interrupt_delete</CODE
126 >(cyg_handle_t interrupt);</CODE
132 >void cyg_interrupt_attach</CODE
133 >(cyg_handle_t interrupt);</CODE
139 >void cyg_interrupt_detach</CODE
140 >(cyg_handle_t interrupt);</CODE
146 >void cyg_interrupt_configure</CODE
147 >(cyg_vector_t vector, cyg_bool_t level, cyg_bool_t up);</CODE
153 >void cyg_interrupt_acknowledge</CODE
154 >(cyg_vector_t vector);</CODE
160 >void cyg_interrupt_disable</CODE
167 >void cyg_interrupt_enable</CODE
174 >void cyg_interrupt_mask</CODE
175 >(cyg_vector_t vector);</CODE
181 >void cyg_interrupt_mask_intunsafe</CODE
182 >(cyg_vector_t vector);</CODE
188 >void cyg_interrupt_unmask</CODE
189 >(cyg_vector_t vector);</CODE
195 >void cyg_interrupt_unmask_intunsafe</CODE
196 >(cyg_vector_t vector);</CODE
202 >void cyg_interrupt_set_cpu</CODE
203 >(cyg_vector_t vector, cyg_cpu_t cpu);</CODE
209 >cyg_cpu_t cyg_interrupt_get_cpu</CODE
210 >(cyg_vector_t vector);</CODE
216 >void cyg_interrupt_get_vsr</CODE
217 >(cyg_vector_t vector, cyg_VSR_t** vsr);</CODE
223 >void cyg_interrupt_set_vsr</CODE
224 >(cyg_vector_t vector, cyg_VSR_t* vsr);</CODE
233 NAME="KERNEL-INTERRUPTS-DESCRIPTION"
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
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.
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
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.
281 NAME="KERNEL-INTERRUPTS-HANDLERS"
284 >Interrupt Handlers</H2
286 >Interrupt handlers are created by a call to
289 >cyg_interrupt_create</TT
290 >. This takes the following
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
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.
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
347 >cyg_interrupt_create</TT
348 > will be passed to both these
349 functions. Typically it will be a pointer to some data structure.
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:
375 CLASS="PROGRAMLISTING"
377 isr_function(cyg_vector_t vector, cyg_addrword_t data)
379 cyg_bool_t dsr_required = 0;
383 return dsr_required ? CYG_ISR_CALL_DSR : CYG_ISR_HANDLED;
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
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
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
417 >cyg_interrupt_acknowledge</TT
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.
426 >The return value of an ISR is normally one of
429 >CYG_ISR_CALL_DSR</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.
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.
457 >If an interrupt has occurred and the ISR has returned a value
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:
478 CLASS="PROGRAMLISTING"
480 dsr_function(cyg_vector_t vector,
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
496 >, unless the system is
497 suffering from a very heavy load. The third argument is the
506 >cyg_interrupt_create</TT
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.
533 >This provides the kernel with an area of memory for holding this
534 interrupt handler and associated data.
542 >cyg_interrupt_create</TT
544 a kernel data structure. A typical next step is to call
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
554 >cyg_interrupt_detach</TT
555 >, followed by another call
558 >cyg_interrupt_attach</TT
559 > for the replacement
562 >cyg_interrupt_delete</TT
564 interrupt handler is no longer required.
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
572 >cyg_interrupt_configure</TT
579 > argument selects between level versus
580 edge triggered; the <TT
585 > argument selects between
586 high and low level, or between rising and falling edges.
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
594 >cyg_interrupt_unmask</TT
595 >, since the sensible default
596 for interrupt masking is to ignore any interrupts for which no handler
603 NAME="KERNEL-INTERRUPTS-ENABLE"
606 >Controlling Interrupts</H2
608 >eCos provides two ways of controlling whether or not interrupts
609 happen. It is possible to disable and reenable all interrupts
612 >cyg_interrupt_disable</TT
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
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
642 >There are two functions for masking a specific interrupt source,
645 >cyg_interrupt_mask</TT
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
655 >cyg_interrupt_mask</TT
657 all interrupts while it manipulates the interrupt mask. In situations
658 where interrupts are already know to be disabled,
661 >cyg_interrupt_mask_intunsafe</TT
663 instead. There are matching functions
666 >cyg_interrupt_unmask</TT
670 >cyg_interrupt_unmask_intsafe</TT
677 NAME="KERNEL-INTERRUPTS-SMP"
682 >On SMP systems the kernel provides an additional two functions related
683 to interrupt handling. <TT
685 >cyg_interrupt_set_cpu</TT
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
694 >cyg_interrupt_get_cpu</TT
696 find out which interrupts are handled on which processor.
702 NAME="KERNEL-INTERRUPTS-VSR"
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.
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.
724 >cyg_interrupt_get_vsr</TT
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.
730 >cyg_interrupt_set_vsr</TT
731 > can be used to install a
732 replacement VSR. Usually the <TT
738 correspond to an exported label in an assembler source file.
744 NAME="KERNEL-INTERRUPTS-CONTEXT"
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
754 >cyg_interrupt_configure</TT
758 >cyg_interrupt_set_vsr</TT
762 >cyg_interrupt_set_cpu</TT
763 > are usually called only
764 during system initialization, but on typical hardware may be called at
767 >cyg_interrupt_get_vsr</TT
771 >cyg_interrupt_get_cpu</TT
772 > may be called at any time.
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.
786 SUMMARY="Footer navigation table"
797 HREF="kernel-schedcontrol.html"
815 HREF="kernel-characterization.html"
825 >Scheduler Control</TD
839 >Kernel Real-time Characterization</TD