1 /*
2  * Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #ifndef _HARDWARE_EXCEPTION_H
8 #define _HARDWARE_EXCEPTION_H
9 
10 #include "pico.h"
11 #include "hardware/address_mapped.h"
12 
13 /** \file exception.h
14  *  \defgroup hardware_exception hardware_exception
15  *
16  * Methods for setting processor exception handlers
17  *
18  * Exceptions are identified by a \ref exception_number which is a number from -15 to -1; these are the numbers relative to
19  * the index of the first IRQ vector in the vector table. (i.e. vector table index is exception_num plus 16)
20  *
21  * There is one set of exception handlers per core, so the exception handlers for each core as set by these methods are independent.
22  *
23  * \note That all exception APIs affect the executing core only (i.e. the core calling the function).
24  */
25 
26 // PICO_CONFIG: PARAM_ASSERTIONS_ENABLED_EXCEPTION, Enable/disable assertions in the exception module, type=bool, default=0, group=hardware_exception
27 #ifndef PARAM_ASSERTIONS_ENABLED_EXCEPTION
28 #define PARAM_ASSERTIONS_ENABLED_EXCEPTION 0
29 #endif
30 
31 #ifdef __cplusplus
32 extern "C" {
33 #endif
34 
35 /*! \brief  Exception number definitions
36  *
37  * Note for consistency with irq numbers, these numbers are defined to be negative. The VTABLE index is
38  * the number here plus 16.
39  *
40  * Name                 | Value | Exception
41  * ---------------------|-------|----------
42  * NMI_EXCEPTION        |  -14  | Non Maskable Interrupt
43  * HARDFAULT_EXCEPTION  |  -13  | HardFault
44  * SVCALL_EXCEPTION     |   -5  | SV Call
45  * PENDSV_EXCEPTION     |   -2  | Pend SV
46  * SYSTICK_EXCEPTION    |   -1  | System Tick
47  *
48  * \ingroup hardware_exception
49  */
50 enum exception_number {
51     NMI_EXCEPTION        = -14,     /* Non Maskable Interrupt */
52     HARDFAULT_EXCEPTION  = -13,     /* HardFault Interrupt */
53     SVCALL_EXCEPTION     =  -5,     /* SV Call Interrupt */
54     PENDSV_EXCEPTION     =  -2,     /* Pend SV Interrupt */
55     SYSTICK_EXCEPTION    =  -1,     /* System Tick Interrupt */
56 };
57 
58 /*! \brief Exception handler function type
59  *  \ingroup hardware_exception
60  *
61  * All exception handlers should be of this type, and follow normal ARM EABI register saving conventions
62  */
63 typedef void (*exception_handler_t)(void);
64 
65 /*! \brief  Set the exception handler for an exception on the executing core.
66  *  \ingroup hardware_exception
67  *
68  * This method will assert if an exception handler has been set for this exception number on this core via
69  * this method, without an intervening restore via exception_restore_handler.
70  *
71  * \note this method may not be used to override an exception handler that was specified at link time by
72  * providing a strong replacement for the weakly defined stub exception handlers. It will assert in this case too.
73  *
74  * \param num Exception number
75  * \param handler The handler to set
76  * \see exception_number
77  */
78 exception_handler_t exception_set_exclusive_handler(enum exception_number num, exception_handler_t handler);
79 
80 /*! \brief Restore the original exception handler for an exception on this core
81  *  \ingroup hardware_exception
82  *
83  * This method may be used to restore the exception handler for an exception on this core to the state
84  * prior to the call to exception_set_exclusive_handler(), so that exception_set_exclusive_handler()
85  * may be called again in the future.
86  *
87  * \param num Exception number \ref exception_number
88  * \param original_handler The original handler returned from \ref exception_set_exclusive_handler
89  * \see exception_set_exclusive_handler()
90  */
91 void exception_restore_handler(enum exception_number num, exception_handler_t original_handler);
92 
93 /*! \brief Get the current exception handler for the specified exception from the currently installed vector table
94  * of the execution core
95  *  \ingroup hardware_exception
96  *
97  * \param num Exception number
98  * \return the address stored in the VTABLE for the given exception number
99  */
100 exception_handler_t exception_get_vtable_handler(enum exception_number num);
101 #ifdef __cplusplus
102 }
103 #endif
104 
105 #endif
106