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)55 Z_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