1 /***************************************************************************//** 2 * @file 3 * @brief Interrupt Management API to enable and configure interrupts. 4 ******************************************************************************* 5 * # License 6 * <b>Copyright 2023 Silicon Laboratories Inc. www.silabs.com</b> 7 ******************************************************************************* 8 * 9 * SPDX-License-Identifier: Zlib 10 * 11 * The licensor of this software is Silicon Laboratories Inc. 12 * 13 * This software is provided 'as-is', without any express or implied 14 * warranty. In no event will the authors be held liable for any damages 15 * arising from the use of this software. 16 * 17 * Permission is granted to anyone to use this software for any purpose, 18 * including commercial applications, and to alter it and redistribute it 19 * freely, subject to the following restrictions: 20 * 21 * 1. The origin of this software must not be misrepresented; you must not 22 * claim that you wrote the original software. If you use this software 23 * in a product, an acknowledgment in the product documentation would be 24 * appreciated but is not required. 25 * 2. Altered source versions must be plainly marked as such, and must not be 26 * misrepresented as being the original software. 27 * 3. This notice may not be removed or altered from any source distribution. 28 * 29 ******************************************************************************/ 30 31 #ifndef SL_INTERRUPT_MANAGER_H 32 #define SL_INTERRUPT_MANAGER_H 33 34 #include <stdint.h> 35 #include <stdbool.h> 36 #include "sl_core.h" 37 #include "sl_status.h" 38 39 #ifdef __cplusplus 40 extern "C" { 41 #endif 42 43 /***************************************************************************//** 44 * @addtogroup interrupt_manager Interrupt Manager 45 * @brief Interrupt management service can be used for general interrupt management. 46 * The source files for Interrupt Manager platform software module are present under 47 * platform/services/interrupt_manager. 48 * @details 49 * ## Overview 50 * The Interrupt Manager is a service that offers interupt management functions and configurations 51 * for setting the interrupt vector in RAM, managing the core reset initiation function and 52 * doing general interrupt management operations. 53 * 54 * ## Configuration Options 55 * 56 * Some properties of the Interrupt Manager are compile-time configurable. These 57 * properties are set in the sl_interrupt_manager_s2_config.h file. 58 * These are the available configuration parameters with default values defined. 59 * @code 60 * 61 * // <q SL_INTERRUPT_MANAGER_S2_INTERRUPTS_IN_RAM> Put the interrupt vector table in RAM. 62 * // <i> Set to 1 to put the vector table in RAM. 63 * // <i> Default: 0 64 * #define SL_INTERRUPT_MANAGER_S2_INTERRUPTS_IN_RAM 0 65 * @endcode 66 * 67 * @note The SL_INTERRUPT_MANAGER_S2_INTERRUPTS_IN_RAM configuration is only available 68 * on series 2. Enabling the S2_INTERRUPTS_IN_RAM configuration will tell the Interrupt Manager 69 * to copy the interrupt vector table from ROM to RAM and select it as the interrupt table. 70 * On newer series this feature is always enabled. 71 * 72 * ## The API 73 * 74 * This section contains brief descriptions of the functions in the API. For more 75 * information on input and output parameters and return values, 76 * click on the hyperlinked function names. 77 * 78 * @ref sl_interrupt_manager_disable_interrupts and @ref sl_interrupt_manager_enable_interrupts() 79 * are used to prevent interrupts from executing during a certain timelapse. 80 * 81 * @ref sl_interrupt_manager_is_irq_disabled, @ref sl_interrupt_manager_is_irq_blocked 82 * are used to know the status of an interrupt, either if it's disabled or blocked by one of the 83 * following reasons: priority masking, disabling or an active interrupt of higher priority 84 * is executing. 85 * 86 * @ref sl_interrupt_manager_is_irq_pending, @ref sl_interrupt_manager_set_irq_pending and 87 * @ref sl_interrupt_manager_clear_irq_pending 88 * are used for control and query of external interrupt source pending status. 89 * 90 * @ref sl_interrupt_manager_get_irq_priority and @ref sl_interrupt_manager_set_irq_priority 91 * are used to get or set the priority for a specific interrupt. 92 * 93 * ## Priority Stratification 94 * With the Interrupt Manager service and more generally in the Simplicity SDK, there are multiple distinct 95 * levels of priority stratification. 96 * 97 * Each of these has their own characteristics and purposes. 98 * For example, the higher priority group is considered to not be able to call kernel, power manager 99 * or protocol stacks functions. They will only be impacted by critical sections (general interrupt 100 * disable) but will be above atomic base interrupt priority level for execution. The higher level 101 * is considered to be between 0 and 2 and the base interrupt priority level is 3. 102 * 103 * In the normal priority group you will find most application interrupts and such interrupts will be 104 * the ones that will make calls to more features such as kernel, power manager and protocol stacks API. 105 * It is this way because they are less deterministic than the "higher priority interrupts". 106 * 107 * <table> 108 * <caption id="interrupt_priority_strat">Priority stratification inside SDK</caption> 109 * <tr><th>Priority<th>Purpose 110 * <tr><td>0 - 2 (Highest)<td> 111 * <ul> 112 * <li>No Kernel calls 113 * <li>No Power Manager calls 114 * <li>Not maskable by atomic sections 115 * </ul> 116 * <tr><td>3 - 7 (Normal)<td> 117 * <ul> 118 * <li>kernel calls 119 * <li>power manager 120 * <li>protocol stacks API 121 * </ul> 122 * <tr><td>7 (Lowest)<td> 123 * <ul> 124 * <li>PendSV level of priority 125 * </ul> 126 * </table> 127 * @{ 128 ******************************************************************************/ 129 130 /// @brief sl_interrupt_manager interrupt handler function. 131 typedef void(*sl_interrupt_manager_irq_handler_t)(void); 132 133 /***************************************************************************//** 134 * @brief 135 * Initialize interrupt controller hardware and initialise vector table 136 * in RAM. 137 * 138 * @note 139 * The interrupt manager init function will perform the initialization only 140 * once even if it's called multiple times. 141 ******************************************************************************/ 142 void sl_interrupt_manager_init(void); 143 144 /***************************************************************************//** 145 * @brief 146 * Reset the cpu core. 147 ******************************************************************************/ 148 void sl_interrupt_manager_reset_system(void); 149 150 /***************************************************************************//** 151 * @brief 152 * Disable interrupts. 153 ******************************************************************************/ 154 void sl_interrupt_manager_disable_interrupts(void); 155 156 /***************************************************************************//** 157 * @brief 158 * Enable interrupts. 159 ******************************************************************************/ 160 void sl_interrupt_manager_enable_interrupts(void); 161 162 /***************************************************************************//** 163 * @brief 164 * Disable interrupt for an interrupt source. 165 * 166 * @param[in] irqn 167 * The interrupt number of the interrupt source. 168 ******************************************************************************/ 169 void sl_interrupt_manager_disable_irq(int32_t irqn); 170 171 /***************************************************************************//** 172 * @brief 173 * Enable interrupt for an interrupt source. 174 * 175 * @param[in] irqn 176 * The interrupt number of the interrupt source. 177 ******************************************************************************/ 178 void sl_interrupt_manager_enable_irq(int32_t irqn); 179 180 /***************************************************************************//** 181 * @brief 182 * Check if an interrupt is disabled. 183 * 184 * @param[in] irqn 185 * The interrupt number of the interrupt source. 186 * 187 * @return 188 * True if the interrupt is disabled. 189 ******************************************************************************/ 190 bool sl_interrupt_manager_is_irq_disabled(int32_t irqn); 191 192 /***************************************************************************//** 193 * @brief 194 * Check if a specific interrupt is blocked. 195 * 196 * @note 197 * The function return true if the IRQ is disabled. 198 * 199 * @param[in] irqn 200 * The interrupt number of the interrupt source. 201 * 202 * @return 203 * True if the interrupt is disabled or blocked. 204 ******************************************************************************/ 205 bool sl_interrupt_manager_is_irq_blocked(int32_t irqn); 206 207 /***************************************************************************//** 208 * @brief 209 * Get Pending Interrupt 210 * 211 * @note 212 * Read the pending status of a specified interrupt and returns it status. 213 * 214 * @param[in] irqn 215 * The interrupt number of the interrupt source. 216 * 217 * @return 218 * false Interrupt status is not pending. 219 * true Interrupt status is pending. 220 ******************************************************************************/ 221 bool sl_interrupt_manager_is_irq_pending(int32_t irqn); 222 223 /***************************************************************************//** 224 * @brief 225 * Set interrupt status to pending. 226 * 227 * @note 228 * Sets an interrupt pending status to true. 229 * 230 * @param[in] irqn 231 * The interrupt number of the interrupt source. 232 ******************************************************************************/ 233 void sl_interrupt_manager_set_irq_pending(int32_t irqn); 234 235 /***************************************************************************//** 236 * @brief 237 * Clear Pending Interrupt 238 * 239 * @details 240 * Clear an interrupt pending status 241 * 242 * @param[in] irqn 243 * The interrupt number of the interrupt source. 244 * 245 * @note 246 * irqn must not be negative. 247 *******************************************************************************/ 248 void sl_interrupt_manager_clear_irq_pending(int32_t irqn); 249 250 /***************************************************************************//** 251 * @brief 252 * Set the interrupt handler of an interrupt source. 253 * 254 * @note 255 * This function depends on a RAM based interrupt vector table, i.e. 256 * SL_INTERRUPT_MANAGER_S2_INTERRUPTS_IN_RAM must be true. Or the device 257 * must be Series 3. 258 * 259 * @param[in] irqn 260 * The interrupt number of the interrupt source. 261 * 262 * @param[in] handler 263 * The new interrupt handler for the interrupt source. 264 * 265 * @return 266 * The prior interrupt handler for the interrupt source. 267 ******************************************************************************/ 268 sl_status_t sl_interrupt_manager_set_irq_handler(int32_t irqn, 269 sl_interrupt_manager_irq_handler_t handler); 270 271 /***************************************************************************//** 272 * @brief 273 * Get the interrupt preemption priority of an interrupt source. 274 * 275 * @note 276 * The number of priority levels is platform dependent. 277 * 278 * @param[in] irqn 279 * The interrupt number of the interrupt source. 280 * 281 * @return 282 * The interrupt priority for the interrupt source. 283 * Value 0 denotes the highest priority. 284 ******************************************************************************/ 285 uint32_t sl_interrupt_manager_get_irq_priority(int32_t irqn); 286 287 /***************************************************************************//** 288 * @brief 289 * Set the interrupt preemption priority of an interrupt source. 290 * 291 * @note 292 * The number of priority levels is platform dependent. 293 * 294 * @param[in] irqn 295 * The interrupt number of the interrupt source. 296 * 297 * @param[in] priority 298 * The new interrupt priority for the interrupt source. 299 * Value 0 denotes the highest priority. 300 ******************************************************************************/ 301 void sl_interrupt_manager_set_irq_priority(int32_t irqn, uint32_t priority); 302 303 /***************************************************************************//** 304 * @brief 305 * Increase the interrupt preemption priority of an interrupt source. 306 * relative to the default priority. 307 * 308 * @details 309 * This function is useful to be architecture agnostic with priority values. 310 * 311 * Usage: 312 * new_prio = sl_interrupt_manager_increase_irq_priority_from_default(IRQn, 1); 313 * 314 * This will increase the priority of IRQn by 1. 315 * 316 * @param[in] irqn 317 * The irq to change the priority. 318 * 319 * @param[in] diff 320 * The relative difference. 321 ******************************************************************************/ 322 void sl_interrupt_manager_increase_irq_priority_from_default(int32_t irqn, uint32_t diff); 323 324 /***************************************************************************//** 325 * @brief 326 * Decrease the interrupt preemption priority of an interrupt source 327 * relative to the default priority. 328 * 329 * @details 330 * This function is useful to be architecture agnostic with priority values. 331 * 332 * Usage: 333 * new_prio = sl_interrupt_manager_decrease_irq_priority_from_default(IRQn, 1); 334 * 335 * This will decrease the priority of IRQn by 1. 336 * 337 * @param[in] irqn 338 * The irq to change the priority. 339 * 340 * @param[in] diff 341 * The relative difference. 342 ******************************************************************************/ 343 void sl_interrupt_manager_decrease_irq_priority_from_default(int32_t irqn, uint32_t diff); 344 345 /***************************************************************************//** 346 * @brief 347 * Get the default interrupt preemption priority value. 348 * 349 * @return 350 * The default priority. 351 ******************************************************************************/ 352 uint32_t sl_interrupt_manager_get_default_priority(void); 353 354 /***************************************************************************//** 355 * @brief 356 * Get the highest interrupt preemption priority value. 357 * 358 * @return 359 * The highest priority value. 360 ******************************************************************************/ 361 uint32_t sl_interrupt_manager_get_highest_priority(void); 362 363 /***************************************************************************//** 364 * @brief 365 * Get the lowest interrupt preemption priority value. 366 * 367 * @return 368 * The lowest priority value. 369 ******************************************************************************/ 370 uint32_t sl_interrupt_manager_get_lowest_priority(void); 371 372 /***************************************************************************//** 373 * @brief 374 * Get the interrupt active status. 375 * 376 * @param[in] irqn 377 * The interrupt number of the interrupt source. 378 * 379 * @return 380 * The interrupt active status. 381 ******************************************************************************/ 382 uint32_t sl_interrupt_manager_get_active_irq(int32_t irqn); 383 384 /***************************************************************************//** 385 * @brief 386 * Get the current ISR table. 387 * 388 * @details 389 * Depending on the configuration of the Interrupt Manager, this table of 390 * ISRs may be in RAM or in FLASH, and each ISR may or may not be wrapped by 391 * enter/exit hooks. 392 * 393 * @return 394 * The current ISR table. 395 ******************************************************************************/ 396 sl_interrupt_manager_irq_handler_t* sl_interrupt_manager_get_isr_table(void); 397 398 /** @} (end addtogroup interrupt_manager) */ 399 400 #ifdef __cplusplus 401 } 402 #endif 403 404 #endif /* SL_INTERRUPT_MANAGER_H */ 405