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 * \brief 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_HARDWARE_EXCEPTION, Enable/disable assertions in the hardware_exception module, type=bool, default=0, group=hardware_exception 27 #ifndef PARAM_ASSERTIONS_ENABLED_HARDWARE_EXCEPTION 28 #ifdef PARAM_ASSERTIONS_ENABLED_EXCEPTION // backwards compatibility with SDK < 2.0.0 29 #define PARAM_ASSERTIONS_ENABLED_HARDWARE_EXCEPTION PARAM_ASSERTIONS_ENABLED_EXCEPTION 30 #else 31 #define PARAM_ASSERTIONS_ENABLED_HARDWARE_EXCEPTION 0 32 #endif 33 #endif 34 #ifdef __cplusplus 35 extern "C" { 36 #endif 37 38 /*! \brief Exception number definitions 39 * 40 * On Arm these are vector table indices: 41 * 42 * Name | Value | Exception 43 * ----------------------|-------|----------------------- 44 * NMI_EXCEPTION | 2 | Non Maskable Interrupt 45 * HARDFAULT_EXCEPTION | 3 | HardFault 46 * \if rp2350_specific 47 * MEMMANAGE_EXCEPTION | 4 | MemManage 48 * BUSFAULT_EXCEPTION | 5 | BusFault 49 * USAGEFAULT_EXCEPTION | 6 | UsageFault 50 * SECUREFAULT_EXCEPTION | 7 | SecureFault 51 * \endif 52 * SVCALL_EXCEPTION | 11 | SV Call 53 * PENDSV_EXCEPTION | 14 | Pend SV 54 * SYSTICK_EXCEPTION | 15 | System Tick 55 * 56 * \if rp2350_specific 57 * On RISC-V these are exception cause numbers: 58 * 59 * Name | Value | Exception 60 * ------------------------|-------|----------------------------- 61 * INSTR_ALIGN_EXCEPTION | 0 | Instruction fetch misaligned 62 * INSTR_FAULT_EXCEPTION | 1 | Instruction fetch bus fault 63 * INSTR_ILLEGAL_EXCEPTION | 2 | Invalid or illegal instruction 64 * EBREAK_EXCEPTION | 3 | ebreak was not caught by an ex 65 * LOAD_ALIGN_EXCEPTION | 4 | Load address not naturally ali 66 * LOAD_FAULT_EXCEPTION | 5 | Load bus fault 67 * STORE_ALIGN_EXCEPTION | 6 | Store or AMO address not natur 68 * STORE_FAULT_EXCEPTION | 7 | Store or AMO bus fault 69 * ECALL_UMODE_EXCEPTION | 8 | ecall was executed in U-mode 70 * ECALL_SMODE_EXCEPTION | 9 | ecall was executed in S-mode 71 * ECALL_MMODE_EXCEPTION | 11 | ecall was executed in M-mode 72 * \endif 73 * 74 * \ingroup hardware_exception 75 */ 76 #ifdef __riscv 77 enum exception_number { 78 // Assigned to non-IRQ xcause values 79 MIN_EXCEPTION_NUM = 0, 80 INSTR_ALIGN_EXCEPTION = 0, ///< Instruction fetch misaligned (never fires if C/Zca is present) 81 INSTR_FAULT_EXCEPTION = 1, ///< Instruction fetch bus fault 82 INSTR_ILLEGAL_EXCEPTION = 2, ///< Invalid or illegal instruction 83 EBREAK_EXCEPTION = 3, ///< ebreak was not caught by an external debugger 84 LOAD_ALIGN_EXCEPTION = 4, ///< Load address not naturally aligned 85 LOAD_FAULT_EXCEPTION = 5, ///< Load bus fault 86 STORE_ALIGN_EXCEPTION = 6, ///< Store or AMO address not naturally aligned 87 STORE_FAULT_EXCEPTION = 7, ///< Store or AMO bus fault 88 ECALL_UMODE_EXCEPTION = 8, ///< ecall was executed in U-mode 89 ECALL_SMODE_EXCEPTION = 9, ///< ecall was executed in S-mode 90 ECALL_MMODE_EXCEPTION = 11, ///< ecall was executed in M-mode 91 MAX_EXCEPTION_NUM = 11 92 }; 93 #else 94 enum exception_number { 95 // Assigned to VTOR indices 96 MIN_EXCEPTION_NUM = 2, 97 NMI_EXCEPTION = 2, ///< Non Maskable Interrupt 98 HARDFAULT_EXCEPTION = 3, ///< HardFault Interrupt 99 #if PICO_RP2350 100 MEMMANAGE_EXCEPTION = 4, ///< MemManage Interrupt 101 BUSFAULT_EXCEPTION = 5, ///< BusFault Interrupt 102 USAGEFAULT_EXCEPTION = 6, ///< UsageFault Interrupt 103 SECUREFAULT_EXCEPTION = 7, ///< SecureFault Interrupt 104 #endif 105 SVCALL_EXCEPTION = 11, ///< SV Call Interrupt 106 PENDSV_EXCEPTION = 14, ///< Pend SV Interrupt 107 SYSTICK_EXCEPTION = 15, ///< System Tick Interrupt 108 MAX_EXCEPTION_NUM = 15 109 }; 110 #endif 111 112 #define PICO_LOWEST_EXCEPTION_PRIORITY 0xff 113 #define PICO_HIGHEST_EXCEPTION_PRIORITY 0x00 114 115 116 /*! \brief Exception handler function type 117 * \ingroup hardware_exception 118 * 119 * All exception handlers should be of this type, and follow normal ARM EABI register saving conventions 120 */ 121 typedef void (*exception_handler_t)(void); 122 123 /*! \brief Set the exception handler for an exception on the executing core. 124 * \ingroup hardware_exception 125 * 126 * This method will assert if an exception handler has been set for this exception number on this core via 127 * this method, without an intervening restore via exception_restore_handler. 128 * 129 * \note this method may not be used to override an exception handler that was specified at link time by 130 * providing a strong replacement for the weakly defined stub exception handlers. It will assert in this case too. 131 * 132 * \param num Exception number 133 * \param handler The handler to set 134 * \see exception_number 135 */ 136 exception_handler_t exception_set_exclusive_handler(enum exception_number num, exception_handler_t handler); 137 138 /*! \brief Restore the original exception handler for an exception on this core 139 * \ingroup hardware_exception 140 * 141 * This method may be used to restore the exception handler for an exception on this core to the state 142 * prior to the call to exception_set_exclusive_handler(), so that exception_set_exclusive_handler() 143 * may be called again in the future. 144 * 145 * \param num Exception number \ref exception_number 146 * \param original_handler The original handler returned from \ref exception_set_exclusive_handler 147 * \see exception_set_exclusive_handler() 148 */ 149 void exception_restore_handler(enum exception_number num, exception_handler_t original_handler); 150 151 /*! \brief Get the current exception handler for the specified exception from the currently installed vector table 152 * of the execution core 153 * \ingroup hardware_exception 154 * 155 * \param num Exception number 156 * \return the address stored in the VTABLE for the given exception number 157 */ 158 exception_handler_t exception_get_vtable_handler(enum exception_number num); 159 160 #ifndef __riscv 161 /*! \brief Set specified exception's priority 162 * \ingroup hardware_exception 163 * 164 * \param num Exception number \ref exception_number 165 * \param hardware_priority Priority to set. 166 * 167 * Numerically-lower values indicate a higher priority. Hardware priorities 168 * range from 0 (highest priority) to 255 (lowest priority). 169 * 170 * \if rp2040_specific 171 * Only the top 2 bits are significant on ARM Cortex-M0+ on RP2040. 172 * \endif 173 * 174 * \if rp2350_specific 175 * Only the top 4 bits are significant on ARM Cortex-M33 on RP2350, and exception priorities 176 * are not supported on RISC-V 177 * \endif 178 */ 179 bool exception_set_priority(uint num, uint8_t hardware_priority); 180 181 /*! \brief Get specified exception's priority 182 * \ingroup hardware_exception 183 * 184 * Numerically-lower values indicate a higher priority. Hardware priorities 185 * range from 0 (highest priority) to 255 (lowest priority). 186 * 187 * \if rp2040_specific 188 * Only the top 2 bits are significant on ARM Cortex-M0+ on RP2040. 189 * \endif 190 * 191 * \if rp2350_specific 192 * Only the top 4 bits are significant on ARM Cortex-M33 on RP2350, and exception priorities 193 * are not supported on RISC-V 194 * \endif 195 * 196 * \param num Exception number \ref exception_number 197 * \return the exception priority 198 */ 199 uint exception_get_priority(uint num); 200 #endif 201 202 #ifdef __cplusplus 203 } 204 #endif 205 206 #endif 207