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

5
Last change on this file since 690b7f9 was 0ef3449, checked in by Sebastian Huber <sebastian.huber@…>, on 12/01/17 at 08:31:57

c-user: Clarify local interrupt disable

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