1 | @c |
---|
2 | @c Interrupt Stack Frame Picture |
---|
3 | @c |
---|
4 | @c COPYRIGHT (c) 1988-2002. |
---|
5 | @c On-Line Applications Research Corporation (OAR). |
---|
6 | @c All rights reserved. |
---|
7 | @c |
---|
8 | @c $Id$ |
---|
9 | @c |
---|
10 | |
---|
11 | @chapter Interrupt Processing |
---|
12 | |
---|
13 | @section Introduction |
---|
14 | |
---|
15 | Different types of processors respond to the |
---|
16 | occurrence of an interrupt in its own unique fashion. In |
---|
17 | addition, each processor type provides a control mechanism to |
---|
18 | allow for the proper handling of an interrupt. The processor |
---|
19 | dependent response to the interrupt modifies the current |
---|
20 | execution state and results in a change in the execution stream. |
---|
21 | Most processors require that an interrupt handler utilize some |
---|
22 | special control mechanisms to return to the normal processing |
---|
23 | stream. Although RTEMS hides many of the processor dependent |
---|
24 | details of interrupt processing, it is important to understand |
---|
25 | how the RTEMS interrupt manager is mapped onto the processor's |
---|
26 | unique architecture. Discussed in this chapter are the MC68xxx's |
---|
27 | interrupt response and control mechanisms as they pertain to |
---|
28 | RTEMS. |
---|
29 | |
---|
30 | @section Vectoring of an Interrupt Handler |
---|
31 | |
---|
32 | Depending on whether or not the particular CPU |
---|
33 | supports a separate interrupt stack, the MC68xxx family has two |
---|
34 | different interrupt handling models. |
---|
35 | |
---|
36 | @subsection Models Without Separate Interrupt Stacks |
---|
37 | |
---|
38 | Upon receipt of an interrupt the MC68xxx family |
---|
39 | members without separate interrupt stacks automatically perform |
---|
40 | the following actions: |
---|
41 | |
---|
42 | @itemize @bullet |
---|
43 | @item To Be Written |
---|
44 | @end itemize |
---|
45 | |
---|
46 | @subsection Models With Separate Interrupt Stacks |
---|
47 | |
---|
48 | Upon receipt of an interrupt the MC68xxx family |
---|
49 | members with separate interrupt stacks automatically perform the |
---|
50 | following actions: |
---|
51 | |
---|
52 | @itemize @bullet |
---|
53 | @item saves the current status register (SR), |
---|
54 | |
---|
55 | @item clears the master/interrupt (M) bit of the SR to |
---|
56 | indicate the switch from master state to interrupt state, |
---|
57 | |
---|
58 | @item sets the privilege mode to supervisor, |
---|
59 | |
---|
60 | @item suppresses tracing, |
---|
61 | |
---|
62 | @item sets the interrupt mask level equal to the level of the |
---|
63 | interrupt being serviced, |
---|
64 | |
---|
65 | @item pushes an interrupt stack frame (ISF), which includes |
---|
66 | the program counter (PC), the status register (SR), and the |
---|
67 | format/exception vector offset (FVO) word, onto the supervisor |
---|
68 | and interrupt stacks, |
---|
69 | |
---|
70 | @item switches the current stack to the interrupt stack and |
---|
71 | vectors to an interrupt service routine (ISR). If the ISR was |
---|
72 | installed with the interrupt_catch directive, then the RTEMS |
---|
73 | interrupt handler will begin execution. The RTEMS interrupt |
---|
74 | handler saves all registers which are not preserved according to |
---|
75 | the calling conventions and invokes the application's ISR. |
---|
76 | @end itemize |
---|
77 | |
---|
78 | A nested interrupt is processed similarly by these |
---|
79 | CPU models with the exception that only a single ISF is placed |
---|
80 | on the interrupt stack and the current stack need not be |
---|
81 | switched. |
---|
82 | |
---|
83 | The FVO word in the Interrupt Stack Frame is examined |
---|
84 | by RTEMS to determine when an outer most interrupt is being |
---|
85 | exited. Since the FVO is used by RTEMS for this purpose, the |
---|
86 | user application code MUST NOT modify this field. |
---|
87 | |
---|
88 | The following shows the Interrupt Stack Frame for |
---|
89 | MC68xxx CPU models with separate interrupt stacks: |
---|
90 | |
---|
91 | @ifset use-ascii |
---|
92 | @example |
---|
93 | @group |
---|
94 | +----------------------+ |
---|
95 | | Status Register | 0x0 |
---|
96 | +----------------------+ |
---|
97 | | Program Counter High | 0x2 |
---|
98 | +----------------------+ |
---|
99 | | Program Counter Low | 0x4 |
---|
100 | +----------------------+ |
---|
101 | | Format/Vector Offset | 0x6 |
---|
102 | +----------------------+ |
---|
103 | @end group |
---|
104 | @end example |
---|
105 | @end ifset |
---|
106 | |
---|
107 | @ifset use-tex |
---|
108 | @sp 1 |
---|
109 | @tex |
---|
110 | \centerline{\vbox{\offinterlineskip\halign{ |
---|
111 | \strut\vrule#& |
---|
112 | \hbox to 2.00in{\enskip\hfil#\hfil}& |
---|
113 | \vrule#& |
---|
114 | \hbox to 0.50in{\enskip\hfil#\hfil} |
---|
115 | \cr |
---|
116 | \multispan{3}\hrulefill\cr |
---|
117 | & Status Register && 0x0\cr |
---|
118 | \multispan{3}\hrulefill\cr |
---|
119 | & Program Counter High && 0x2\cr |
---|
120 | \multispan{3}\hrulefill\cr |
---|
121 | & Program Counter Low && 0x4\cr |
---|
122 | \multispan{3}\hrulefill\cr |
---|
123 | & Format/Vector Offset && 0x6\cr |
---|
124 | \multispan{3}\hrulefill\cr |
---|
125 | }}\hfil} |
---|
126 | @end tex |
---|
127 | @end ifset |
---|
128 | |
---|
129 | @ifset use-html |
---|
130 | @html |
---|
131 | <CENTER> |
---|
132 | <TABLE COLS=2 WIDTH="40%" BORDER=2> |
---|
133 | <TR><TD ALIGN=center><STRONG>Status Register</STRONG></TD> |
---|
134 | <TD ALIGN=center>0x0</TD></TR> |
---|
135 | <TR><TD ALIGN=center><STRONG>Program Counter High</STRONG></TD> |
---|
136 | <TD ALIGN=center>0x2</TD></TR> |
---|
137 | <TR><TD ALIGN=center><STRONG>Program Counter Low</STRONG></TD> |
---|
138 | <TD ALIGN=center>0x4</TD></TR> |
---|
139 | <TR><TD ALIGN=center><STRONG>Format/Vector Offset</STRONG></TD> |
---|
140 | <TD ALIGN=center>0x6</TD></TR> |
---|
141 | </TABLE> |
---|
142 | </CENTER> |
---|
143 | @end html |
---|
144 | @end ifset |
---|
145 | |
---|
146 | @section CPU Models Without VBR and RAM at 0 |
---|
147 | |
---|
148 | This is from a post by Zoltan Kocsi <zoltan@@bendor.com.au> and is |
---|
149 | a nice trick in certain situations. In his words: |
---|
150 | |
---|
151 | I think somebody on this list asked about the interupt vector |
---|
152 | handling w/o VBR and RAM at 0. The usual trick is |
---|
153 | to initialise the vector table (except the first 2 two entries, of |
---|
154 | course) to point to the same location BUT you also add the vector |
---|
155 | number times 0x1000000 to them. That is, bits 31-24 contain the vector |
---|
156 | number and 23-0 the address of the common handler. |
---|
157 | Since the PC is 32 bit wide but the actual address bus is only 24, |
---|
158 | the top byte will be in the PC but will be ignored when jumping |
---|
159 | onto your routine. |
---|
160 | |
---|
161 | Then your common interrupt routine gets this info by loading the PC |
---|
162 | into some register and based on that info, you can jump to a vector |
---|
163 | in a vector table pointed by a virtual VBR: |
---|
164 | |
---|
165 | @example |
---|
166 | // |
---|
167 | // Real vector table at 0 |
---|
168 | // |
---|
169 | |
---|
170 | .long initial_sp |
---|
171 | .long initial_pc |
---|
172 | .long myhandler+0x02000000 |
---|
173 | .long myhandler+0x03000000 |
---|
174 | .long myhandler+0x04000000 |
---|
175 | ... |
---|
176 | .long myhandler+0xff000000 |
---|
177 | |
---|
178 | |
---|
179 | // |
---|
180 | // This handler will jump to the interrupt routine of which |
---|
181 | // the address is stored at VBR[ vector_no ] |
---|
182 | // The registers and stackframe will be intact, the interrupt |
---|
183 | // routine will see exactly what it would see if it was called |
---|
184 | // directly from the HW vector table at 0. |
---|
185 | // |
---|
186 | |
---|
187 | .comm VBR,4,2 // This defines the 'virtual' VBR |
---|
188 | // From C: extern void *VBR; |
---|
189 | |
---|
190 | myhandler: // At entry, PC contains the full vector |
---|
191 | move.l %d0,-(%sp) // Save d0 |
---|
192 | move.l %a0,-(%sp) // Save a0 |
---|
193 | lea 0(%pc),%a0 // Get the value of the PC |
---|
194 | move.l %a0,%d0 // Copy it to a data reg, d0 is VV?????? |
---|
195 | swap %d0 // Now d0 is ????VV?? |
---|
196 | and.w #0xff00,%d0 // Now d0 is ????VV00 (1) |
---|
197 | lsr.w #6,%d0 // Now d0.w contains the VBR table offset |
---|
198 | move.l VBR,%a0 // Get the address from VBR to a0 |
---|
199 | move.l (%a0,%d0.w),%a0 // Fetch the vector |
---|
200 | move.l 4(%sp),%d0 // Restore d0 |
---|
201 | move.l %a0,4(%sp) // Place target address to the stack |
---|
202 | move.l (%sp)+,%a0 // Restore a0, target address is on TOS |
---|
203 | ret // This will jump to the handler and |
---|
204 | // restore the stack |
---|
205 | |
---|
206 | (1) If 'myhandler' is guaranteed to be in the first 64K, e.g. just |
---|
207 | after the vector table then that insn is not needed. |
---|
208 | |
---|
209 | @end example |
---|
210 | |
---|
211 | There are probably shorter ways to do this, but it I believe is enough |
---|
212 | to illustrate the trick. Optimisation is left as an exercise to the |
---|
213 | reader :-) |
---|
214 | |
---|
215 | |
---|
216 | @section Interrupt Levels |
---|
217 | |
---|
218 | Eight levels (0-7) of interrupt priorities are |
---|
219 | supported by MC68xxx family members with level seven (7) being |
---|
220 | the highest priority. Level zero (0) indicates that interrupts |
---|
221 | are fully enabled. Interrupt requests for interrupts with |
---|
222 | priorities less than or equal to the current interrupt mask |
---|
223 | level are ignored. |
---|
224 | |
---|
225 | Although RTEMS supports 256 interrupt levels, the |
---|
226 | MC68xxx family only supports eight. RTEMS interrupt levels 0 |
---|
227 | through 7 directly correspond to MC68xxx interrupt levels. All |
---|
228 | other RTEMS interrupt levels are undefined and their behavior is |
---|
229 | unpredictable. |
---|
230 | |
---|
231 | @section Disabling of Interrupts by RTEMS |
---|
232 | |
---|
233 | During the execution of directive calls, critical |
---|
234 | sections of code may be executed. When these sections are |
---|
235 | encountered, RTEMS disables interrupts to level seven (7) before |
---|
236 | the execution of this section and restores them to the previous |
---|
237 | level upon completion of the section. RTEMS has been optimized |
---|
238 | to insure that interrupts are disabled for less than |
---|
239 | RTEMS_MAXIMUM_DISABLE_PERIOD microseconds on a |
---|
240 | RTEMS_MAXIMUM_DISABLE_PERIOD_MHZ Mhz MC68020 with |
---|
241 | zero wait states. These numbers will vary based the |
---|
242 | number of wait states and processor speed present on the target board. |
---|
243 | [NOTE: The maximum period with interrupts disabled is hand calculated. This |
---|
244 | calculation was last performed for Release |
---|
245 | RTEMS_RELEASE_FOR_MAXIMUM_DISABLE_PERIOD.] |
---|
246 | |
---|
247 | Non-maskable interrupts (NMI) cannot be disabled, and |
---|
248 | ISRs which execute at this level MUST NEVER issue RTEMS system |
---|
249 | calls. If a directive is invoked, unpredictable results may |
---|
250 | occur due to the inability of RTEMS to protect its critical |
---|
251 | sections. However, ISRs that make no system calls may safely |
---|
252 | execute as non-maskable interrupts. |
---|
253 | |
---|
254 | @section Interrupt Stack |
---|
255 | |
---|
256 | RTEMS allocates the interrupt stack from the |
---|
257 | Workspace Area. The amount of memory allocated for the |
---|
258 | interrupt stack is determined by the interrupt_stack_size field |
---|
259 | in the CPU Configuration Table. During the initialization |
---|
260 | process, RTEMS will install its interrupt stack. |
---|
261 | |
---|
262 | The MC68xxx port of RTEMS supports a software managed |
---|
263 | dedicated interrupt stack on those CPU models which do not |
---|
264 | support a separate interrupt stack in hardware. |
---|
265 | |
---|
266 | |
---|