@@ -206,6 +206,130 @@ The following code demonstrates a direct ISR:
206
206
...
207
207
}
208
208
209
+ Implementation Details
210
+ ======================
211
+
212
+ Interrupt tables are set up at build time using some special build tools. The
213
+ details laid out here apply to all architectures except x86, which are
214
+ covered in the `x86 Details `_ section below.
215
+
216
+ Any invocation of :c:macro: `IRQ_CONNECT ` will declare an instance of
217
+ struct _isr_list which is placed in a special .intList section:
218
+
219
+ .. code-block :: c
220
+
221
+ struct _isr_list {
222
+ /** IRQ line number */
223
+ s32_t irq;
224
+ /** Flags for this IRQ, see ISR_FLAG_* definitions */
225
+ s32_t flags;
226
+ /** ISR to call */
227
+ void *func;
228
+ /** Parameter for non-direct IRQs */
229
+ void *param;
230
+ };
231
+
232
+ Zephyr is built in two phases; the first phase of the build produces
233
+ zephyr_prebuilt.elf which contains all the entries in the .intList section
234
+ preceded by a header:
235
+
236
+ .. code-block :: c
237
+
238
+ struct {
239
+ void *spurious_irq_handler;
240
+ void *sw_irq_handler;
241
+ u32_t num_isrs;
242
+ u32_t num_vectors;
243
+ struct _isr_list isrs[]; <- of size num_isrs
244
+ };
245
+
246
+ This data consisting of the header and instances of struct _isr_list inside
247
+ zephyr_prebuilt.elf is then used by the gen_isr_tables.py script to generate a
248
+ C file defining a vector table and software ISR table that are then compiled
249
+ and linked into the final application.
250
+
251
+ The priority level of any interrupt is not encoded in these tables, instead
252
+ :c:macro: `IRQ_CONNECT ` also has a runtime component which programs the desired
253
+ priority level of the interrupt to the interrupt controller. Some architectures
254
+ do not support the notion of interrupt priority, in which case the priority
255
+ argument is ignored.
256
+
257
+ Vector Table
258
+ ------------
259
+ A vector table is generated when CONFIG_GEN_IRQ_VECTOR_TABLE is enabled. This
260
+ data structure is used natively by the CPU and is simply an array of function
261
+ pointers, where each element n corresponds to the IRQ handler for IRQ line n,
262
+ and the function pointers are:
263
+
264
+ #. For 'direct' interrupts declared with :c:macro: `IRQ_DIRECT_CONNECT `, the
265
+ handler function will be placed here.
266
+ #. For regular interrupts declared with :c:macro: `IRQ_CONNECT `, the address
267
+ of the common software IRQ handler is placed here. This code does common
268
+ kernel interrupt bookkeeping and looks up the ISR and parameter from the
269
+ software ISR table.
270
+ #. For interrupt lines that are not configured at all, the address of the
271
+ spurious IRQ handler will be placed here. The spurious IRQ handler
272
+ causes a system fatal error if encountered.
273
+
274
+ Some architectures (such as the Nios II internal interrupt controller) have a
275
+ common entry point for all interrupts and do not support a vector table, in
276
+ which case the CONFIG_GEN_IRQ_VECTOR_TABLE option should be disabled.
277
+
278
+ Some architectures may reserve some initial vectors for system exceptions
279
+ and declare this in a table elsewhere, in which case
280
+ CONFIG_GEN_IRQ_START_VECTOR needs to be set to properly offset the indicies
281
+ in the table.
282
+
283
+ SW ISR Table
284
+ ------------
285
+ This is an array of struct _isr_table_entry:
286
+
287
+ .. code-block :: c
288
+
289
+ struct _isr_table_entry {
290
+ void *arg;
291
+ void (*isr)(void *);
292
+ };
293
+
294
+ This is used by the common software IRQ handler to look up the ISR and its
295
+ argument and execute it. The active IRQ line is looked up in an interrupt
296
+ controller register and used to index this table.
297
+
298
+ x86 Details
299
+ -----------
300
+
301
+ The x86 architecture has a special type of vector table called the Interrupt
302
+ Descriptor Table (IDT) which must be laid out in a certain way per the x86
303
+ processor documentation. It is still fundamentally a vector table, and the
304
+ gen_idt tool uses the .intList section to create it. However, on APIC-based
305
+ systems the indexes in the vector table do not correspond to the IRQ line. The
306
+ first 32 vectors are reserved for CPU exceptions, and all remaining vectors (up
307
+ to index 255) correspond to the priority level, in groups of 16. In this
308
+ scheme, interrupts of priority level 0 will be placed in vectors 32-47, level 1
309
+ 48-63, and so forth. When the gen_idt tool is constructing the IDT, when it
310
+ configures an interrupt it will look for a free vector in the appropriate range
311
+ for the requested priority level and set the handler there.
312
+
313
+ There are some APIC variants (such as MVIC) where priorities cannot be set
314
+ by the user and the position in the vector table does correspond to the
315
+ IRQ line. Systems like this will enable CONFIG_X86_FIXED_IRQ_MAPPING.
316
+
317
+ On x86 when an interrupt or exception vector is executed by the CPU, there is
318
+ no foolproof way to determine which vector was fired, so a software ISR table
319
+ indexed by IRQ line is not used. Instead, the :c:macro: `IRQ_CONNECT ` call
320
+ creates a small assembly language function which calls the common interrupt
321
+ code in :cpp:func: `_interrupt_enter ` with the ISR and parameter as arguments.
322
+ It is the address of this assembly interrupt stub which gets placed in the IDT.
323
+ For interrupts declared with :c:macro: `IRQ_DIRECT_CONNECT ` the parameterless
324
+ ISR is placed directly in the IDT.
325
+
326
+ On systems where the position in the vector table corresponds to the
327
+ interrupt's priority level, the interrupt controller needs to know at
328
+ runtime what vector is associated with an IRQ line. gen_idt additionally
329
+ creates an _irq_to_interrupt_vector array which maps an IRQ line to its
330
+ configured vector in the IDT. This is used at runtime by :c:macro: `IRQ_CONNECT `
331
+ to program the IRQ-to-vector association in the interrupt controller.
332
+
209
333
Suggested Uses
210
334
**************
211
335
0 commit comments