1 /* 2 * Copyright (c) 2013-2014 Wind River Systems, Inc. 3 * Copyright (c) 2023 Arm Limited 4 * 5 * SPDX-License-Identifier: Apache-2.0 6 */ 7 8 /** 9 * @file 10 * @brief ARM Cortex-M exception/interrupt exit API 11 * 12 * Provides functions for performing kernel handling when exiting exceptions or 13 * interrupts that are installed directly in the vector table (i.e. that are not 14 * wrapped around by _isr_wrapper()). 15 */ 16 17 #include <zephyr/kernel.h> 18 #include <kswap.h> 19 #include <cmsis_core.h> 20 21 /** 22 * 23 * @brief Kernel housekeeping when exiting interrupt handler installed 24 * directly in vector table 25 * 26 * Kernel allows installing interrupt handlers (ISRs) directly into the vector 27 * table to get the lowest interrupt latency possible. This allows the ISR to 28 * be invoked directly without going through a software interrupt table. 29 * However, upon exiting the ISR, some kernel work must still be performed, 30 * namely possible context switching. While ISRs connected in the software 31 * interrupt table do this automatically via a wrapper, ISRs connected directly 32 * in the vector table must invoke z_arm_int_exit() as the *very last* action 33 * before returning. 34 * 35 * e.g. 36 * 37 * void myISR(void) 38 * { 39 * printk("in %s\n", __FUNCTION__); 40 * doStuff(); 41 * z_arm_int_exit(); 42 * } 43 * 44 */ 45 FUNC_ALIAS(z_arm_exc_exit, z_arm_int_exit, void); 46 47 /** 48 * 49 * @brief Kernel housekeeping when exiting exception handler installed 50 * directly in vector table 51 * 52 * See z_arm_int_exit(). 53 * 54 */ z_arm_exc_exit(void)55Z_GENERIC_SECTION(.text._HandlerModeExit) void z_arm_exc_exit(void) 56 { 57 #ifdef CONFIG_PREEMPT_ENABLED 58 /* If thread is preemptible */ 59 if (_kernel.cpus->current->base.prio >= 0) { 60 /* and cached thread is not current thread */ 61 if (_kernel.ready_q.cache != _kernel.cpus->current) { 62 /* trigger a context switch */ 63 SCB->ICSR |= SCB_ICSR_PENDSVSET_Msk; 64 } 65 } 66 #endif /* CONFIG_PREEMPT_ENABLED */ 67 68 #ifdef CONFIG_STACK_SENTINEL 69 z_check_stack_sentinel(); 70 #endif /* CONFIG_STACK_SENTINEL */ 71 } 72