source: rtems-docs/c-user/interrupt_manager.rst @ e52906b

5
Last change on this file since e52906b was e52906b, checked in by Sebastian Huber <sebastian.huber@…>, on 01/09/19 at 15:14:06

Simplify SPDX-License-Identifier comment

  • Property mode set to 100644
File size: 22.0 KB
Line 
1.. SPDX-License-Identifier: CC-BY-SA-4.0
2
3.. Copyright (C) 1988, 2008 On-Line Applications Research Corporation (OAR)
4
5.. index:: interrupts
6
7Interrupt Manager
8*****************
9
10Introduction
11============
12
13Any real-time executive must provide a mechanism for quick response to
14externally generated interrupts to satisfy the critical time constraints of the
15application.  The interrupt manager provides this mechanism for RTEMS.  This
16manager permits quick interrupt response times by providing the critical
17ability to alter task execution which allows a task to be preempted upon exit
18from an ISR.  The interrupt manager includes the following directive:
19
20- rtems_interrupt_catch_ - Establish an ISR
21
22- rtems_interrupt_disable_ - Disable Interrupts
23
24- rtems_interrupt_enable_ - Restore Interrupt Level
25
26- rtems_interrupt_flash_ - Flash Interrupt
27
28- rtems_interrupt_local_disable_ - Disable Interrupts on Current Processor
29
30- rtems_interrupt_local_enable_ - Restore Interrupt Level on Current Processor
31
32- rtems_interrupt_lock_initialize_ - Initialize an ISR Lock
33
34- rtems_interrupt_lock_acquire_ - Acquire an ISR Lock
35
36- rtems_interrupt_lock_release_ - Release an ISR Lock
37
38- rtems_interrupt_lock_acquire_isr_ - Acquire an ISR Lock from ISR
39
40- rtems_interrupt_lock_release_isr_ - Release an ISR Lock from ISR
41
42- rtems_interrupt_is_in_progress_ - Is an ISR in Progress
43
44Background
45==========
46
47.. index:: interrupt processing
48
49Processing an Interrupt
50-----------------------
51
52The interrupt manager allows the application to connect a function to a
53hardware interrupt vector.  When an interrupt occurs, the processor will
54automatically vector to RTEMS.  RTEMS saves and restores all registers which
55are not preserved by the normal C calling convention for the target processor
56and invokes the user's ISR.  The user's ISR is responsible for processing the
57interrupt, clearing the interrupt if necessary, and device specific
58manipulation.
59
60.. index:: rtems_vector_number
61
62The ``rtems_interrupt_catch`` directive connects a procedure to an interrupt
63vector.  The vector number is managed using the ``rtems_vector_number`` data
64type.
65
66The interrupt service routine is assumed to abide by these conventions and have
67a prototype similar to the following:
68
69.. index:: rtems_isr
70
71.. code-block:: c
72
73    rtems_isr user_isr(
74      rtems_vector_number vector
75    );
76
77The vector number argument is provided by RTEMS to allow the application to
78identify the interrupt source.  This could be used to allow a single routine to
79service interrupts from multiple instances of the same device.  For example, a
80single routine could service interrupts from multiple serial ports and use the
81vector number to identify which port requires servicing.
82
83To minimize the masking of lower or equal priority level interrupts, the ISR
84should perform the minimum actions required to service the interrupt.  Other
85non-essential actions should be handled by application tasks.  Once the user's
86ISR has completed, it returns control to the RTEMS interrupt manager which will
87perform task dispatching and restore the registers saved before the ISR was
88invoked.
89
90The RTEMS interrupt manager guarantees that proper task scheduling and
91dispatching are performed at the conclusion of an ISR.  A system call made by
92the ISR may have readied a task of higher priority than the interrupted task.
93Therefore, when the ISR completes, the postponed dispatch processing must be
94performed.  No dispatch processing is performed as part of directives which
95have been invoked by an ISR.
96
97Applications must adhere to the following rule if proper task scheduling and
98dispatching is to be performed:
99
100.. note::
101
102  The interrupt manager must be used for all ISRs which may be interrupted by
103  the highest priority ISR which invokes an RTEMS directive.
104
105Consider a processor which allows a numerically low interrupt level to
106interrupt a numerically greater interrupt level.  In this example, if an RTEMS
107directive is used in a level 4 ISR, then all ISRs which execute at levels 0
108through 4 must use the interrupt manager.
109
110Interrupts are nested whenever an interrupt occurs during the execution of
111another ISR.  RTEMS supports efficient interrupt nesting by allowing the nested
112ISRs to terminate without performing any dispatch processing.  Only when the
113outermost ISR terminates will the postponed dispatching occur.
114
115.. index:: interrupt levels
116
117RTEMS Interrupt Levels
118----------------------
119
120Many processors support multiple interrupt levels or priorities.  The exact
121number of interrupt levels is processor dependent.  RTEMS internally supports
122256 interrupt levels which are mapped to the processor's interrupt levels.  For
123specific information on the mapping between RTEMS and the target processor's
124interrupt levels, refer to the Interrupt Processing chapter of the Applications
125Supplement document for a specific target processor.
126
127.. index:: disabling interrupts
128
129Disabling of Interrupts by RTEMS
130--------------------------------
131
132During the execution of directive calls, critical sections of code may be
133executed.  When these sections are encountered, RTEMS disables all maskable
134interrupts before the execution of the section and restores them to the
135previous level upon completion of the section.  RTEMS has been optimized to
136ensure that interrupts are disabled for a minimum length of time.  The maximum
137length of time interrupts are disabled by RTEMS is processor dependent and is
138detailed in the Timing Specification chapter of the Applications Supplement
139document for a specific target processor.
140
141Non-maskable interrupts (NMI) cannot be disabled, and ISRs which execute at
142this level MUST NEVER issue RTEMS system calls.  If a directive is invoked,
143unpredictable results may occur due to the inability of RTEMS to protect its
144critical sections.  However, ISRs that make no system calls may safely execute
145as non-maskable interrupts.
146
147Operations
148==========
149
150Establishing an ISR
151-------------------
152
153The ``rtems_interrupt_catch`` directive establishes an ISR for the system.  The
154address of the ISR and its associated CPU vector number are specified to this
155directive.  This directive installs the RTEMS interrupt wrapper in the
156processor's Interrupt Vector Table and the address of the user's ISR in the
157RTEMS' Vector Table.  This directive returns the previous contents of the
158specified vector in the RTEMS' Vector Table.
159
160Directives Allowed from an ISR
161------------------------------
162
163Using the interrupt manager ensures that RTEMS knows when a directive is being
164called from an ISR.  The ISR may then use system calls to synchronize itself
165with an application task.  The synchronization may involve messages, events or
166signals being passed by the ISR to the desired task.  Directives invoked by an
167ISR must operate only on objects which reside on the local node.  The following
168is a list of RTEMS system calls that may be made from an ISR:
169
170- Task Management
171  Although it is acceptable to operate on the RTEMS_SELF task (e.g.  the
172  currently executing task), while in an ISR, this will refer to the
173  interrupted task.  Most of the time, it is an application implementation
174  error to use RTEMS_SELF from an ISR.
175
176  - rtems_task_suspend
177  - rtems_task_resume
178
179- Interrupt Management
180
181  - rtems_interrupt_enable
182  - rtems_interrupt_disable
183  - rtems_interrupt_flash
184  - rtems_interrupt_lock_acquire
185  - rtems_interrupt_lock_release
186  - rtems_interrupt_lock_acquire_isr
187  - rtems_interrupt_lock_release_isr
188  - rtems_interrupt_is_in_progress
189  - rtems_interrupt_catch
190
191- Clock Management
192
193  - rtems_clock_set
194  - rtems_clock_get_tod
195  - rtems_clock_get_tod_timeval
196  - rtems_clock_get_seconds_since_epoch
197  - rtems_clock_get_ticks_per_second
198  - rtems_clock_get_ticks_since_boot
199  - rtems_clock_get_uptime
200
201- Timer Management
202
203  - rtems_timer_cancel
204  - rtems_timer_reset
205  - rtems_timer_fire_after
206  - rtems_timer_fire_when
207  - rtems_timer_server_fire_after
208  - rtems_timer_server_fire_when
209
210- Event Management
211
212  - rtems_event_send
213  - rtems_event_system_send
214  - rtems_event_transient_send
215
216- Semaphore Management
217
218  - rtems_semaphore_release
219
220- Message Management
221
222  - rtems_message_queue_send
223  - rtems_message_queue_urgent
224
225- Signal Management
226
227  - rtems_signal_send
228
229- Dual-Ported Memory Management
230
231  - rtems_port_external_to_internal
232  - rtems_port_internal_to_external
233
234- IO Management
235  The following services are safe to call from an ISR if and only if
236  the device driver service invoked is also safe.  The IO Manager itself
237  is safe but the invoked driver entry point may or may not be.
238
239  - rtems_io_initialize
240  - rtems_io_open
241  - rtems_io_close
242  - rtems_io_read
243  - rtems_io_write
244  - rtems_io_control
245
246- Fatal Error Management
247
248  - rtems_fatal
249  - rtems_fatal_error_occurred
250
251- Multiprocessing
252
253  - rtems_multiprocessing_announce
254
255Directives
256==========
257
258This section details the interrupt manager's directives.  A subsection is
259dedicated to each of this manager's directives and describes the calling
260sequence, related constants, usage, and status codes.
261
262.. raw:: latex
263
264   \clearpage
265
266.. index:: establish an ISR
267.. index:: install an ISR
268.. index:: rtems_interrupt_catch
269
270.. _rtems_interrupt_catch:
271
272INTERRUPT_CATCH - Establish an ISR
273----------------------------------
274
275CALLING SEQUENCE:
276    .. code-block:: c
277
278        rtems_status_code rtems_interrupt_catch(
279          rtems_isr_entry      new_isr_handler,
280          rtems_vector_number  vector,
281          rtems_isr_entry     *old_isr_handler
282        );
283
284DIRECTIVE STATUS CODES:
285    .. list-table::
286     :class: rtems-wrap
287
288     * - ``RTEMS_SUCCESSFUL``
289       -  ISR established successfully
290     * - ``RTEMS_INVALID_NUMBER``
291       -  illegal vector number
292     * - ``RTEMS_INVALID_ADDRESS``
293       -  illegal ISR entry point or invalid ``old_isr_handler``
294
295DESCRIPTION:
296    This directive establishes an interrupt service routine (ISR) for the
297    specified interrupt vector number.  The ``new_isr_handler`` parameter
298    specifies the entry point of the ISR.  The entry point of the previous ISR
299    for the specified vector is returned in ``old_isr_handler``.
300
301    To release an interrupt vector, pass the old handler's address obtained
302    when the vector was first capture.
303
304NOTES:
305    This directive will not cause the calling task to be preempted.
306
307.. raw:: latex
308
309   \clearpage
310
311.. index:: disable interrupts
312.. index:: rtems_interrupt_disable
313
314.. _rtems_interrupt_disable:
315
316INTERRUPT_DISABLE - Disable Interrupts
317--------------------------------------
318
319CALLING SEQUENCE:
320    .. code-block:: c
321
322        void rtems_interrupt_disable(
323          rtems_interrupt_level level
324        );
325
326DIRECTIVE STATUS CODES:
327    NONE
328
329DESCRIPTION:
330    This directive disables all maskable interrupts and returns the previous
331    interrupt level in ``level``.
332
333NOTES:
334    A later invocation of the ``rtems_interrupt_enable`` directive should be
335    used to restore the interrupt level.
336
337    This directive is implemented as a macro which sets the ``level``
338    parameter.
339
340    This directive will not cause the calling task to be preempted.
341
342    This directive is only available in uniprocessor configurations.  The
343    directive ``rtems_interrupt_local_disable`` is available in all
344    configurations.
345
346    .. code-block:: c
347
348        void critical_section( void )
349        {
350          rtems_interrupt level;
351
352          /*
353           * Please note that the rtems_interrupt_disable() is a macro.  The
354           * previous interrupt level (before the maskable interrupts are
355           * disabled) is returned here in the level macro parameter.  This
356           * would be wrong:
357           *
358           * rtems_interrupt_disable( &level );
359           */
360          rtems_interrupt_disable( level );
361
362          /* Critical section, maskable interrupts are disabled */
363
364          {
365            rtems_interrupt level2;
366
367            rtems_interrupt_disable( level2 );
368
369            /* Nested critical section */
370
371            rtems_interrupt_enable( level2 );
372          }
373
374          /* Maskable interrupts are still disabled */
375
376          rtems_interrupt_enable( level );
377        }
378
379.. raw:: latex
380
381   \clearpage
382
383.. index:: enable interrupts
384.. index:: restore interrupt level
385.. index:: rtems_interrupt_enable
386
387.. _rtems_interrupt_enable:
388
389INTERRUPT_ENABLE - Restore Interrupt Level
390------------------------------------------
391
392CALLING SEQUENCE:
393    .. code-block:: c
394
395        void rtems_interrupt_enable(
396          rtems_interrupt_level level
397        );
398
399DIRECTIVE STATUS CODES:
400    NONE
401
402DESCRIPTION:
403    This directive restores the interrupt level specified by ``level``.
404
405NOTES:
406    The ``level`` parameter value must be obtained by a previous call to
407    ``rtems_interrupt_disable`` or ``rtems_interrupt_flash``.  Using an
408    otherwise obtained value is undefined behaviour.
409
410    This directive is unsuitable to enable particular interrupt sources, for
411    example in an interrupt controller.
412
413    This directive will not cause the calling task to be preempted.
414
415    This directive is only available in uniprocessor configurations.  The
416    directive ``rtems_interrupt_local_enable`` is available in all
417    configurations.
418
419.. raw:: latex
420
421   \clearpage
422
423.. index:: flash interrupts
424.. index:: rtems_interrupt_flash
425
426.. _rtems_interrupt_flash:
427
428INTERRUPT_FLASH - Flash Interrupts
429----------------------------------
430
431CALLING SEQUENCE:
432    .. code-block:: c
433
434        void rtems_interrupt_flash(
435          rtems_interrupt_level level
436        );
437
438DIRECTIVE STATUS CODES:
439    NONE
440
441DESCRIPTION:
442    This directive is functionally equivalent to a
443    ``rtems_interrupt_enable( level )`` immediately followed by a
444    ``rtems_interrupt_disable( level )``.  On some
445    architectures it is possible to provide an optimized implementation for
446    this sequence.
447
448NOTES:
449    The ``level`` parameter value must be obtained by a previous call to
450    ``rtems_interrupt_disable`` or ``rtems_interrupt_flash``.  Using an
451    otherwise obtained value is undefined behaviour.
452
453    This directive will not cause the calling task to be preempted.
454
455    This directive is only available in uniprocessor configurations.  The
456    directives ``rtems_interrupt_local_disable`` and
457    ``rtems_interrupt_local_enable`` are available in all configurations.
458
459    Historically, the interrupt flash directive was heavily used in the
460    operating system implementation.  However, this is no longer the case.  The
461    interrupt flash directive is provided for backward compatibility reasons.
462
463.. raw:: latex
464
465   \clearpage
466
467.. index:: disable interrupts
468.. index:: rtems_interrupt_local_disable
469
470.. _rtems_interrupt_local_disable:
471
472INTERRUPT_LOCAL_DISABLE - Disable Interrupts on Current Processor
473-----------------------------------------------------------------
474
475CALLING SEQUENCE:
476    .. code-block:: c
477
478        void rtems_interrupt_local_disable(
479          rtems_interrupt_level level
480        );
481
482DIRECTIVE STATUS CODES:
483    NONE
484
485DESCRIPTION:
486    This directive disables all maskable interrupts on the current processor
487    and returns the previous interrupt level in ``level``.
488
489NOTES:
490    A later invocation of the ``rtems_interrupt_local_enable`` directive should
491    be used to restore the interrupt level.
492
493    This directive is implemented as a macro which sets the ``level``
494    parameter.
495
496    This directive will not cause the calling task to be preempted.
497
498    In SMP configurations, this will not ensure system wide mutual exclusion.
499    Use interrupt locks instead.
500
501    .. code-block:: c
502
503        void local_critical_section( void )
504        {
505          rtems_interrupt level;
506
507          /*
508           * Please note that the rtems_interrupt_local_disable() is a macro.
509           * The previous interrupt level (before the maskable interrupts are
510           * disabled) is returned here in the level macro parameter.  This
511           * would be wrong:
512           *
513           * rtems_interrupt_local_disable( &level );
514           */
515          rtems_interrupt_local_disable( level );
516
517          /*
518           * Local critical section, maskable interrupts on the current
519           * processor are disabled.
520           */
521
522          {
523            rtems_interrupt level2;
524
525            rtems_interrupt_local_disable( level2 );
526
527            /* Nested local critical section */
528
529            rtems_interrupt_local_enable( level2 );
530          }
531
532          /* Maskable interrupts are still disabled */
533
534          rtems_interrupt_local_enable( level );
535        }
536
537.. raw:: latex
538
539   \clearpage
540
541.. index:: enable interrupts
542.. index:: restore interrupt level
543.. index:: rtems_interrupt_local_enable
544
545.. _rtems_interrupt_local_enable:
546
547INTERRUPT_LOCAL_ENABLE - Restore Interrupt Level on Current Processor
548---------------------------------------------------------------------
549
550CALLING SEQUENCE:
551    .. code-block:: c
552
553        void rtems_interrupt_local_enable(
554          rtems_interrupt_level level
555        );
556
557DIRECTIVE STATUS CODES:
558    NONE
559
560DESCRIPTION:
561    This directive restores the interrupt level specified by ``level`` on the
562    current processor.
563
564NOTES:
565    The ``level`` parameter value must be obtained by a previous call to
566    ``rtems_interrupt_local_disable``.  Using an otherwise obtained value is
567    undefined behaviour.
568
569    This directive is unsuitable to enable particular interrupt sources, for
570    example in an interrupt controller.
571
572    This directive will not cause the calling task to be preempted.
573
574.. raw:: latex
575
576   \clearpage
577
578.. index:: rtems_interrupt_lock_initialize
579
580.. _rtems_interrupt_lock_initialize:
581
582INTERRUPT_LOCK_INITIALIZE - Initialize an ISR Lock
583--------------------------------------------------
584
585CALLING SEQUENCE:
586    .. code-block:: c
587
588        void rtems_interrupt_lock_initialize(
589          rtems_interrupt_lock *lock,
590          const char           *name
591        );
592
593DIRECTIVE STATUS CODES:
594    NONE
595
596DESCRIPTION:
597    Initializes an interrupt lock.  The name must be persistent throughout the
598    lifetime of the lock.
599
600NOTES:
601    Concurrent initialization leads to unpredictable results.
602
603.. raw:: latex
604
605   \clearpage
606
607.. index:: rtems_interrupt_lock_acquire
608
609.. _rtems_interrupt_lock_acquire:
610
611INTERRUPT_LOCK_ACQUIRE - Acquire an ISR Lock
612--------------------------------------------
613
614CALLING SEQUENCE:
615    .. code-block:: c
616
617        void rtems_interrupt_lock_acquire(
618          rtems_interrupt_lock         *lock,
619          rtems_interrupt_lock_context *lock_context
620        );
621
622DIRECTIVE STATUS CODES:
623    NONE
624
625DESCRIPTION:
626    Maskable interrupts will be disabled.  In SMP configurations, this
627    directive acquires an SMP lock.
628
629NOTES:
630    A separate lock context must be provided for each acquire/release pair, for
631    example an automatic variable.
632
633    An attempt to recursively acquire the lock may result in an infinite loop
634    with maskable interrupts disabled.
635
636    This directive will not cause the calling thread to be preempted.  This
637    directive can be used in thread and interrupt context.
638
639.. raw:: latex
640
641   \clearpage
642
643.. index:: rtems_interrupt_lock_release
644
645.. _rtems_interrupt_lock_release:
646
647INTERRUPT_LOCK_RELEASE - Release an ISR Lock
648--------------------------------------------
649
650CALLING SEQUENCE:
651    .. code-block:: c
652
653        void rtems_interrupt_lock_release(
654          rtems_interrupt_lock         *lock,
655          rtems_interrupt_lock_context *lock_context
656        );
657
658DIRECTIVE STATUS CODES:
659    NONE
660
661DESCRIPTION:
662    The interrupt level will be restored.  In SMP configurations, this
663    directive releases an SMP lock.
664
665NOTES:
666    The lock context must be the one used to acquire the lock, otherwise the
667    result is unpredictable.
668
669    This directive will not cause the calling thread to be preempted.  This
670    directive can be used in thread and interrupt context.
671
672.. raw:: latex
673
674   \clearpage
675
676.. index:: rtems_interrupt_lock_acquire_isr
677
678.. _rtems_interrupt_lock_acquire_isr:
679
680INTERRUPT_LOCK_ACQUIRE_ISR - Acquire an ISR Lock from ISR
681---------------------------------------------------------
682
683CALLING SEQUENCE:
684    .. code-block:: c
685
686        void rtems_interrupt_lock_acquire_isr(
687          rtems_interrupt_lock         *lock,
688          rtems_interrupt_lock_context *lock_context
689        );
690
691DIRECTIVE STATUS CODES:
692    NONE
693
694DESCRIPTION:
695    The interrupt level will remain unchanged.  In SMP configurations, this
696    directive acquires an SMP lock.
697
698NOTES:
699    A separate lock context must be provided for each acquire/release pair, for
700    example an automatic variable.
701
702    An attempt to recursively acquire the lock may result in an infinite loop.
703
704    This directive is intended for device drivers and should be called from the
705    corresponding interrupt service routine.
706
707    In case the corresponding interrupt service routine can be interrupted by
708    higher priority interrupts and these interrupts enter the critical section
709    protected by this lock, then the result is unpredictable.
710
711.. raw:: latex
712
713   \clearpage
714
715.. index:: rtems_interrupt_lock_release_isr
716
717.. _rtems_interrupt_lock_release_isr:
718
719INTERRUPT_LOCK_RELEASE_ISR - Release an ISR Lock from ISR
720---------------------------------------------------------
721
722CALLING SEQUENCE:
723    .. code-block:: c
724
725        void rtems_interrupt_lock_release_isr(
726          rtems_interrupt_lock         *lock,
727          rtems_interrupt_lock_context *lock_context
728        );
729
730DIRECTIVE STATUS CODES:
731    NONE
732
733DESCRIPTION:
734    The interrupt level will remain unchanged.  In SMP configurations, this
735    directive releases an SMP lock.
736
737NOTES:
738    The lock context must be the one used to acquire the lock, otherwise the
739    result is unpredictable.
740
741    This directive is intended for device drivers and should be called from the
742    corresponding interrupt service routine.
743
744.. raw:: latex
745
746   \clearpage
747
748.. index:: is interrupt in progress
749.. index:: rtems_interrupt_is_in_progress
750
751.. _rtems_interrupt_is_in_progress:
752
753INTERRUPT_IS_IN_PROGRESS - Is an ISR in Progress
754------------------------------------------------
755
756CALLING SEQUENCE:
757    .. code-block:: c
758
759        bool rtems_interrupt_is_in_progress( void );
760
761DIRECTIVE STATUS CODES:
762    NONE
763
764DESCRIPTION:
765    This directive returns ``TRUE`` if the processor is currently servicing an
766    interrupt and ``FALSE`` otherwise.  A return value of ``TRUE`` indicates
767    that the caller is an interrupt service routine, *NOT* a task.  The
768    directives available to an interrupt service routine are restricted.
769
770NOTES:
771    This directive will not cause the calling task to be preempted.
Note: See TracBrowser for help on using the repository browser.