]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_GCC/freedom-metal/doc/sphinx/devguide/interrupts.rst
Added the "full" demo to the RISC-V_RV32_SiFive_HiFive1_GCC demo - backup check in...
[freertos] / FreeRTOS / Demo / RISC-V_RV32_SiFive_HiFive1_GCC / freedom-metal / doc / sphinx / devguide / interrupts.rst
1 Interrupt Handlers
2 ==================
3
4 The Interrupt Heirarchy
5 -----------------------
6
7 Freedom Metal conceptualizes interrupts as a heirarchy of interrupt controllers.
8 This heirarchy is established by the interrupt heirarchy of the target platform
9 itself. Presently, the interrupt heirarchy for a given platform is best documented
10 by the target's DeviceTree representation, which can be found in
11 ``bsp/<target-name>/design.dts``.
12
13 In Freedom Metal, the heirarchy is a tree. The nodes of the tree consist of
14 ``struct metal_interrupt``:
15
16 .. doxygenstruct:: metal_interrupt
17    :project: metal
18
19 And the vertices of the tree consist of interrupt ``id``.
20
21 .. digraph:: int_heirarchy_graph
22
23    cpu [label="CPU"];
24    cpu_int [label="CPU Interrupt Controller", shape=box];
25    timer_int [label="Timer Interrupt Controller", shape=box];
26    soft_int [label="Software Interrupt Controller", shape=box];
27
28    cpu -> cpu_int [label="ID = 0"];
29    cpu_int -> timer_int [label="ID = timer_id"];
30    cpu_int -> soft_int [label="ID = software_id"];
31
32 The CPU Interrupt Controller
33 ----------------------------
34
35 The CPU interrupt controller is the top of the interrupt heirarchy. It must be
36 initialized before any other interrupt controllers are initialized. In example:
37
38 .. code-block:: C
39
40    struct metal_cpu *cpu0 = metal_get_cpu(0);
41    if(!cpu) {
42       /* Unable to get CPU handle */
43    }
44    struct metal_interrupt *cpu_int = metal_cpu_interrupt_controller(cpu0);
45    if(!cpu_int) {
46       /* Unable to get CPU interrupt handle */
47    }
48    metal_interrupt_init(cpu_int);
49
50 The CPU interrupt must be enabled for the CPU to receive any interrupts, and any
51 enabled interrupts can be masked by disabling the CPU interrupt.
52
53 .. code-block:: C
54
55    int rc = 0;
56
57    /* Enable the CPU interrupt */
58    rc = metal_interrupt_enable(cpu_int, 0);
59    if(rc != 0) {
60       /* Failed to enable the CPU interrupt */
61    }
62
63    /* Disable the CPU interrupt */
64    rc = metal_interrupt_disable(cpu_int, 0);
65    if(rc != 0) {
66       /* Failed to disable the CPU interrupt */
67    }
68
69 Interrupt Handlers
70 ------------------
71
72 Interrupt handlers must conform to the following function signature:
73
74 .. doxygentypedef:: metal_interrupt_handler_t
75    :project: metal
76
77 Therefore, an interrupt handler might look like:
78
79 .. code-block:: C
80
81    void my_interrupt_handler(int id, void *priv_data) {
82       /* Contents of handler */
83    }
84
85 Registering an Interrupt Handler
86 --------------------------------
87
88 Interrupt handlers are registered with the interrupt controller for the interrupt
89 they are servicing. For example, if we want to register a CPU timer interrupt:
90
91 .. code-block:: C
92
93    struct metal_interrupt *timer_int = metal_cpu_timer_interrupt_controller(cpu0);
94    if(!timer_int) {
95       /* Failed to get timer interrupt controller */
96    }
97    metal_interrupt_init(timer_int);
98
99    int timer_id = metal_cpu_timer_get_interrupt_id(cpu0);
100
101    int rc = metal_interrupt_register_handler(timer_int, timer_id, my_interrupt_handler, cpu0);
102    if(rc != 0) {
103       /* Failed to register interrupt handler */
104    }
105
106 Additional Documentation
107 ------------------------
108
109 Additional documentation for the interrupt handler API can be found in
110 :doc:`the CPU API reference </apiref/cpu>` and
111 :doc:`the Interrupt API reference </apiref/interrupt>`.
112