/* * Copyright (c) 2013-2014 Wind River Systems, Inc. * Copyright (c) 2020 Stephanos Ioannidis * Copyright (c) 2023 Arm Limited * * SPDX-License-Identifier: Apache-2.0 */ /** * @file * @brief ARM Cortex-M wrapper for ISRs with parameter * * Wrapper installed in vector table for handling dynamic interrupts that accept * a parameter. */ #include #include #include #include /** * * @brief Wrapper around ISRs when inserted in software ISR table * * When inserted in the vector table, _isr_wrapper() demuxes the ISR table * using the running interrupt number as the index, and invokes the registered * ISR with its corresponding argument. When returning from the ISR, it * determines if a context switch needs to happen (see documentation for * z_arm_pendsv()) and pends the PendSV exception if so: the latter will * perform the context switch itself. * */ void _isr_wrapper(void) { #ifdef CONFIG_TRACING_ISR sys_trace_isr_enter(); #endif /* CONFIG_TRACING_ISR */ #ifdef CONFIG_PM /* * All interrupts are disabled when handling idle wakeup. For tickless * idle, this ensures that the calculation and programming of the * device for the next timer deadline is not interrupted. For * non-tickless idle, this ensures that the clearing of the kernel idle * state is not interrupted. In each case, pm_system_resume * is called with interrupts disabled. */ /* * Disable interrupts to prevent nesting while exiting idle state. This * is only necessary for the Cortex-M because it is the only ARM * architecture variant that automatically enables interrupts when * entering an ISR. */ __disable_irq(); /* is this a wakeup from idle ? */ /* requested idle duration, in ticks */ if (_kernel.idle != 0) { /* clear kernel idle state */ _kernel.idle = 0; pm_system_resume(); } /* re-enable interrupts */ __enable_irq(); #endif /* CONFIG_PM */ #if defined(CONFIG_ARM_CUSTOM_INTERRUPT_CONTROLLER) int32_t irq_number = z_soc_irq_get_active(); #else /* _sw_isr_table does not map the exceptions, only the interrupts. */ int32_t irq_number = __get_IPSR(); #endif irq_number -= 16; struct _isr_table_entry *entry = &_sw_isr_table[irq_number]; (entry->isr)(entry->arg); #if defined(CONFIG_ARM_CUSTOM_INTERRUPT_CONTROLLER) z_soc_irq_eoi(irq_number); #endif #ifdef CONFIG_TRACING_ISR sys_trace_isr_exit(); #endif /* CONFIG_TRACING_ISR */ z_arm_exc_exit(); }