1 /*
2  * Copyright (c) 2013-2014 Wind River Systems, Inc.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 /**
8  * @file
9  * @brief ARM AArch32 Cortex-M public exception handling
10  */
11 
12 #ifndef ZEPHYR_INCLUDE_ARCH_ARM_CORTEX_M_EXCEPTION_H_
13 #define ZEPHYR_INCLUDE_ARCH_ARM_CORTEX_M_EXCEPTION_H_
14 
15 #include <zephyr/devicetree.h>
16 
17 #include <zephyr/arch/arm/cortex_m/nvic.h>
18 
19 /* for assembler, only works with constants */
20 #define Z_EXC_PRIO(pri) (((pri) << (8 - NUM_IRQ_PRIO_BITS)) & 0xff)
21 
22 /*
23  * In architecture variants with non-programmable fault exceptions
24  * (e.g. Cortex-M Baseline variants), hardware ensures processor faults
25  * are given the highest interrupt priority level. SVCalls are assigned
26  * the highest configurable priority level (level 0); note, however, that
27  * this interrupt level may be shared with HW interrupts.
28  *
29  * In Cortex variants with programmable fault exception priorities we
30  * assign the highest interrupt priority level (level 0) to processor faults
31  * with configurable priority.
32  * The highest priority level may be shared with either Zero-Latency IRQs (if
33  * support for the feature is enabled) or with SVCall priority level.
34  * Regular HW IRQs are always assigned priority levels lower than the priority
35  * levels for SVCalls, Zero-Latency IRQs and processor faults.
36  *
37  * PendSV IRQ (which is used in Cortex-M variants to implement thread
38  * context-switching) is assigned the lowest IRQ priority level.
39  */
40 #if defined(CONFIG_CPU_CORTEX_M_HAS_PROGRAMMABLE_FAULT_PRIOS)
41 #define _EXCEPTION_RESERVED_PRIO 1
42 #else
43 #define _EXCEPTION_RESERVED_PRIO 0
44 #endif
45 
46 #define _EXC_FAULT_PRIO 0
47 #define _EXC_ZERO_LATENCY_IRQS_PRIO 0
48 #define _EXC_SVC_PRIO COND_CODE_1(CONFIG_ZERO_LATENCY_IRQS,		\
49 				  (CONFIG_ZERO_LATENCY_LEVELS), (0))
50 #define _IRQ_PRIO_OFFSET (_EXCEPTION_RESERVED_PRIO + _EXC_SVC_PRIO)
51 #define IRQ_PRIO_LOWEST (BIT(NUM_IRQ_PRIO_BITS) - (_IRQ_PRIO_OFFSET) - 1)
52 
53 #define _EXC_IRQ_DEFAULT_PRIO Z_EXC_PRIO(_IRQ_PRIO_OFFSET)
54 
55 /* Use lowest possible priority level for PendSV */
56 #define _EXC_PENDSV_PRIO 0xff
57 #define _EXC_PENDSV_PRIO_MASK Z_EXC_PRIO(_EXC_PENDSV_PRIO)
58 
59 #ifdef _ASMLANGUAGE
60 GTEXT(z_arm_exc_exit);
61 #else
62 #include <zephyr/types.h>
63 
64 #ifdef __cplusplus
65 extern "C" {
66 #endif
67 
68 #if defined(CONFIG_FPU) && defined(CONFIG_FPU_SHARING)
69 
70 /* Registers s16-s31 (d8-d15, q4-q7) must be preserved across subroutine calls.
71  *
72  * Registers s0-s15 (d0-d7, q0-q3) do not have to be preserved (and can be used
73  * for passing arguments or returning results in standard procedure-call variants).
74  *
75  * Registers d16-d31 (q8-q15), do not have to be preserved.
76  */
77 struct __fpu_sf {
78 	uint32_t s[16]; /* s0~s15 (d0-d7) */
79 #ifdef CONFIG_VFP_FEATURE_REGS_S64_D32
80 	uint64_t d[16]; /* d16~d31 */
81 #endif
82 	uint32_t fpscr;
83 	uint32_t undefined;
84 };
85 #endif
86 
87 /* Additional register state that is not stacked by hardware on exception
88  * entry.
89  *
90  * These fields are ONLY valid in the ESF copy passed into z_arm_fatal_error().
91  * When information for a member is unavailable, the field is set to zero.
92  */
93 #if defined(CONFIG_EXTRA_EXCEPTION_INFO)
94 struct __extra_esf_info {
95 	_callee_saved_t *callee;
96 	uint32_t msp;
97 	uint32_t exc_return;
98 };
99 #endif /* CONFIG_EXTRA_EXCEPTION_INFO */
100 
101 struct arch_esf {
102 	struct __basic_sf {
103 		sys_define_gpr_with_alias(a1, r0);
104 		sys_define_gpr_with_alias(a2, r1);
105 		sys_define_gpr_with_alias(a3, r2);
106 		sys_define_gpr_with_alias(a4, r3);
107 		sys_define_gpr_with_alias(ip, r12);
108 		sys_define_gpr_with_alias(lr, r14);
109 		sys_define_gpr_with_alias(pc, r15);
110 		uint32_t xpsr;
111 	} basic;
112 #if defined(CONFIG_FPU) && defined(CONFIG_FPU_SHARING)
113 	struct __fpu_sf fpu;
114 #endif
115 #if defined(CONFIG_EXTRA_EXCEPTION_INFO)
116 	struct __extra_esf_info extra_info;
117 #endif
118 };
119 
120 extern uint32_t z_arm_coredump_fault_sp;
121 
122 extern void z_arm_exc_exit(void);
123 
124 #ifdef __cplusplus
125 }
126 #endif
127 
128 #endif /* _ASMLANGUAGE */
129 
130 #endif /* ZEPHYR_INCLUDE_ARCH_ARM_CORTEX_M_EXCEPTION_H_ */
131