]> git.sur5r.net Git - freertos/blob
c8c53effe722a96e506223453a5d977af54e430b
[freertos] /
1 Exception Handlers
2 ==================
3
4 CPU exceptions are the mechanism by which various execution and memory system
5 errors are handled. When an exception occurs, Freedom Metal will call the
6 corresponding exception handler function, if one has been registered by the
7 application.
8
9 Initializing the CPU
10 --------------------
11
12 When the user application enters the ``main()`` function, the Freedom Metal
13 framework has not yet performed the initialization necessary to register
14 exception handlers. If this initialization is not performed before an exception
15 occurs, any exception will cause the CPU to spin in a tight loop until reset.
16
17 To initialize the Freedom Metal exception handlers, initialize CPU interrupts:
18
19 .. code-block:: C
20
21    struct metal_cpu *cpu0 = metal_get_cpu(0);
22    if(!cpu) {
23       /* There was an error acquiring the CPU hart 0 handle */
24    }
25
26    struct metal_interrupt *cpu_int = metal_cpu_interrupt_controller(cpu0);
27    if(!cpu_int) {
28       /* There was an error acquiring the CPU interrupt controller */
29    }
30
31    metal_interrupt_init(cpu_int);
32
33 The Freedom Metal interrupt API is further documented in :doc:`/devguide/interrupts`
34 and :doc:`/apiref/interrupt`.
35
36 Defining an Exception Handler
37 -----------------------------
38
39 Exception handlers must conform to the following function signature:
40
41 .. doxygentypedef:: metal_exception_handler_t
42    :project: metal
43    :no-link:
44
45 Therefore, an example exception handler might look like:
46
47 .. code-block:: C
48
49    void my_exception_handler(struct metal_cpu *cpu, int ecode) {
50       /* Contents of handler */
51    }
52
53 Registering an Exception Handler
54 --------------------------------
55
56 Exception handlers are registered with a given CPU hart for an individual exception
57 code.
58
59 .. code-block:: C
60
61    /* CPU Hart 0's interrupt controller must be initialized
62     * if it is not already */
63    struct metal_cpu *cpu0 = metal_get_cpu(0);
64
65    int rc = metal_cpu_exception_register(cpu0,
66                <my_ecode>, /* Set to your desired value */
67                my_exception_handler);
68    if(rc != 0) {
69       /* Failed to register exception handler */
70    }
71
72 A single exception handler may be used for multiple exception codes. For this reason,
73 exception handlers receive the exception code as the ``ecode`` parameter and may use
74 this to determine how to handle the exception.
75
76 Returing Execution after a Faulting Instruction
77 -----------------------------------------------
78
79 The default behavior of a RISC-V CPU is to return execution to the faulting instruction.
80 If this is not the desired behavior, execution can be returned to the instruction after
81 the faulting instruction using the following method:
82
83 .. code-block:: C
84
85    void return_after_fault(struct metal_cpu *cpu, int ecode)
86    {
87       /* Get the faulting instruction address */
88       uintptr_t epc = metal_cpu_get_exception_pc(cpu);
89
90       /* Get the length of the faulting instruction */
91       size_t len = metal_cpu_get_instruction_length(cpu, epc);
92
93       /* Advance stored exception program counter by the
94        * instruction length */
95       metal_cpu_set_exception_pc(cpu, epc + len);
96    }
97
98 Additional Documentation
99 ------------------------
100
101 Additional documentation for the exception handler API can be found in :doc:`The CPU API Reference </apiref/cpu>`.
102
103