1 // High-Priority Interrupt Handler Template
2 // $Id: //depot/rel/Cottonwood/Xtensa/OS/xtos/int-highpri-template.S#3 $
4 // Copyright (c) 2004-2010 Tensilica Inc.
6 // Permission is hereby granted, free of charge, to any person obtaining
7 // a copy of this software and associated documentation files (the
8 // "Software"), to deal in the Software without restriction, including
9 // without limitation the rights to use, copy, modify, merge, publish,
10 // distribute, sublicense, and/or sell copies of the Software, and to
11 // permit persons to whom the Software is furnished to do so, subject to
12 // the following conditions:
14 // The above copyright notice and this permission notice shall be included
15 // in all copies or substantial portions of the Software.
17 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20 // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
21 // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22 // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23 // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 // This file provides skeleton code for writing high-priority interrupt
27 // handlers in assembler for performance.
29 // By default, this file is included by inth-template.S .
30 // The default Makefile defines _INTERRUPT_LEVEL when assembling
31 // inth-template.S for each medium and high priority interrupt level.
33 // To use this template file, define a macro called _INTERRUPT_LEVEL
34 // to be the interrupt priority level of the vector, then include this file.
37 #include <xtensa/coreasm.h>
38 #include "xtos-internal.h"
41 #if XCHAL_HAVE_INTERRUPTS
43 #define INTERRUPT_MASK XCHAL_INTLEVEL_MASK(_INTERRUPT_LEVEL)
44 #define SINGLE_INTERRUPT (INTERRUPT_MASK & (INTERRUPT_MASK - 1) == 0)
45 #define SINGLE_INT_NUM XCHAL_INTLEVEL_NUM(_INTERRUPT_LEVEL)
48 // NOTE: It is strongly recommended that high-priority
49 // interrupt handlers be written in assembly.
51 // High-priority interrupt handlers can be written in C,
52 // but only at the cost of an unreasonable amount of state
53 // save and restore (including the entire physical address
54 // register file and others, see int-highpri-dispatcher.S)
55 // that makes high-priority interrupt dispatching much slower
56 // than for low and medium priority interrupts.
57 // (Low and medium priority interrupts are masked by atomic
58 // register window operations, so they take advantage of a
59 // coherent window state for fast entry. High priority
60 // interrupts are not masked by window operations so they
61 // can interrupt them, leading to a potentially incoherent
62 // window state at the time of the interrupt. Given that
63 // high priority handlers must save and restore everything
64 // they touch, they end up needing to save and restore the
65 // entire window state [physical address register file etc.]
66 // and all exception state which they can also interrupt.)
67 // See also the Microprocessor Programmer's Guide.
69 // High-priority interrupts are designed to be very fast and with
71 // Typical high-priority interrupt service routines are kept
72 // relatively small and fast. Either there is little to do,
73 // or the routine handles only the necessary high priority
74 // activities related to a device and leaves the rest
75 // (other more complex and time-consuming activities)
76 // to be scheduled later, eg. by triggering a level-one
77 // (low-priority) or medium-priority software interrupt whose
78 // handler can be written in C for the more extensive processing.
80 // NOTE: The following handler is just skeleton example
81 // code. It is NOT a functional handler. For software, edge-
82 // triggered and write-error interrupts, it simply does nothing
83 // and return. For other types (timer and level-triggered),
84 // this code does not clear the source(s) of interrupt,
85 // hence if any interrupt at this priority level are both enabled
86 // and triggered, the processor repeatedly takes the interrupt
87 // in a loop. This is all okay as a default, because
88 // XTOS (and other operating systems) clears the INTENABLE
89 // register at startup, requiring the application to
90 // enable specific interrupts before they can be taken.
91 // So as long as you don't enable any interrupt of this
92 // priority level, this example handler will never execute.
95 .global LABEL(_Level,FromVector)
100 .space 4 // save area
104 LABEL(_Level,FromVector):
105 // The vectoring code has already saved a2 in EXCSAVEn.
106 // Save any other registers we'll use:
107 movi a2, LABEL(int,save)
109 // ... add more as needed (increase save area accordingly) ...
111 // WRITE YOUR INTERRUPT HANDLING CODE HERE...
113 // If multiple interrupts are mapped to this priority level,
114 // you'll probably need to distinguish which interrupt(s)
115 // occurred by reading the INTERRUPT (INTREAD) and
116 // INTENABLE registers, and'ing them together, and
117 // looking at what bits are set in both.
118 // If any of the interrupts are level-triggered, be ready
119 // to handle the case where no interrupts are to be handled
120 // -- this is called a spurious interrupt, and can happen
121 // when the level-triggered interrupt line goes inactive
122 // after the interrupt is taken but before the INTERRUPT
125 // You'll also normally want to clear the source of
126 // the interrupt before returning, to avoid getting
127 // the same interrupt again immediately. For illustration,
128 // this code clears all software, edge-triggered, and
129 // write-error interrupts at this priority level (if any).
130 // NOTE: Timer interrupts must be cleared by writing to
131 // the corresponding CCOMPAREn register; and level-sensitive
132 // interrupts can only be cleared externally, usually by
133 // requesting the associated device to do so (in a
134 // device-specific manner).
136 movi a1, INTERRUPT_MASK
139 // Restore registers:
142 movi a2, LABEL(_Level,FromVector) // restore handler address
143 xsr a2, EXCSAVE_LEVEL
145 rsr a2, EXCSAVE_LEVEL
147 // ... add more if more are saved above ...
152 .size LABEL(_Level,FromVector), . - LABEL(_Level,FromVector)
154 #endif /* XCHAL_HAVE_INTERRUPTS */