1 /* 2 * Copyright (c) 2013-2014 Wind River Systems, Inc. 3 * Copyright (c) 2020 Stephanos Ioannidis <root@stephanos.io> 4 * Copyright (c) 2023 Arm Limited 5 * 6 * SPDX-License-Identifier: Apache-2.0 7 */ 8 9 /** 10 * @file 11 * @brief ARM Cortex-M wrapper for ISRs with parameter 12 * 13 * Wrapper installed in vector table for handling dynamic interrupts that accept 14 * a parameter. 15 */ 16 #include <zephyr/kernel.h> 17 #include <zephyr/irq.h> 18 #include <zephyr/pm/pm.h> 19 #include <cmsis_core.h> 20 21 /** 22 * 23 * @brief Wrapper around ISRs when inserted in software ISR table 24 * 25 * When inserted in the vector table, _isr_wrapper() demuxes the ISR table 26 * using the running interrupt number as the index, and invokes the registered 27 * ISR with its corresponding argument. When returning from the ISR, it 28 * determines if a context switch needs to happen (see documentation for 29 * z_arm_pendsv()) and pends the PendSV exception if so: the latter will 30 * perform the context switch itself. 31 * 32 */ _isr_wrapper(void)33void _isr_wrapper(void) 34 { 35 #ifdef CONFIG_TRACING_ISR 36 sys_trace_isr_enter(); 37 #endif /* CONFIG_TRACING_ISR */ 38 39 #ifdef CONFIG_PM 40 /* 41 * All interrupts are disabled when handling idle wakeup. For tickless 42 * idle, this ensures that the calculation and programming of the 43 * device for the next timer deadline is not interrupted. For 44 * non-tickless idle, this ensures that the clearing of the kernel idle 45 * state is not interrupted. In each case, pm_system_resume 46 * is called with interrupts disabled. 47 */ 48 49 /* 50 * Disable interrupts to prevent nesting while exiting idle state. This 51 * is only necessary for the Cortex-M because it is the only ARM 52 * architecture variant that automatically enables interrupts when 53 * entering an ISR. 54 */ 55 __disable_irq(); 56 57 /* is this a wakeup from idle ? */ 58 /* requested idle duration, in ticks */ 59 if (_kernel.idle != 0) { 60 /* clear kernel idle state */ 61 _kernel.idle = 0; 62 pm_system_resume(); 63 } 64 /* re-enable interrupts */ 65 __enable_irq(); 66 #endif /* CONFIG_PM */ 67 68 #if defined(CONFIG_ARM_CUSTOM_INTERRUPT_CONTROLLER) 69 int32_t irq_number = z_soc_irq_get_active(); 70 #else 71 /* _sw_isr_table does not map the expections, only the interrupts. */ 72 int32_t irq_number = __get_IPSR(); 73 #endif 74 irq_number -= 16; 75 76 struct _isr_table_entry *entry = &_sw_isr_table[irq_number]; 77 (entry->isr)(entry->arg); 78 79 #if defined(CONFIG_ARM_CUSTOM_INTERRUPT_CONTROLLER) 80 z_soc_irq_eoi(irq_number); 81 #endif 82 83 #ifdef CONFIG_TRACING_ISR 84 sys_trace_isr_exit(); 85 #endif /* CONFIG_TRACING_ISR */ 86 87 z_arm_exc_exit(); 88 } 89