1 | /****************************************************************************** |
---|
2 | * Copyright (c) 2015 - 2022 Xilinx, Inc. All rights reserved. |
---|
3 | * SPDX-License-Identifier: MIT |
---|
4 | ******************************************************************************/ |
---|
5 | |
---|
6 | /*****************************************************************************/ |
---|
7 | /** |
---|
8 | * |
---|
9 | * @file xil_exception.h |
---|
10 | * |
---|
11 | * This header file contains ARM Cortex A53,A9,R5 specific exception related APIs. |
---|
12 | * For exception related functions that can be used across all Xilinx supported |
---|
13 | * processors, please use xil_exception.h. |
---|
14 | * |
---|
15 | * @addtogroup arm_exception_apis ARM Processor Exception Handling |
---|
16 | * @{ |
---|
17 | * ARM processors specific exception related APIs for cortex A53,A9 and R5 can |
---|
18 | * utilized for enabling/disabling IRQ, registering/removing handler for |
---|
19 | * exceptions or initializing exception vector table with null handler. |
---|
20 | * |
---|
21 | * <pre> |
---|
22 | * MODIFICATION HISTORY: |
---|
23 | * |
---|
24 | * Ver Who Date Changes |
---|
25 | * ----- -------- -------- ----------------------------------------------- |
---|
26 | * 5.2 pkp 28/05/15 First release |
---|
27 | * 6.0 mus 27/07/16 Consolidated file for a53,a9 and r5 processors |
---|
28 | * 6.7 mna 26/04/18 Add API Xil_GetExceptionRegisterHandler. |
---|
29 | * 6.7 asa 18/05/18 Update signature of API Xil_GetExceptionRegisterHandler. |
---|
30 | * 7.0 mus 01/03/19 Tweak Xil_ExceptionEnableMask and |
---|
31 | * Xil_ExceptionDisableMask macros to support legacy |
---|
32 | * examples for Cortexa72 EL3 exception level. |
---|
33 | * 7.3 mus 04/15/20 Added Xil_EnableNestedInterrupts and |
---|
34 | * Xil_DisableNestedInterrupts macros for ARMv8. |
---|
35 | * For Cortexa72, these macro's would not be supported |
---|
36 | * at EL3, as Cortexa72 is using GIC-500(GICv3), which |
---|
37 | * triggeres only FIQ at EL3. Fix for CR#1062506 |
---|
38 | * 7.6 mus 09/17/21 Updated flag checking to fix warning reported with |
---|
39 | * -Wundef compiler option CR#1110261 |
---|
40 | * 7.7 mus 01/31/22 Few of the #defines in xil_exception.h in are treated |
---|
41 | * in different way based on "versal" flag. In existing |
---|
42 | * flow, this flag is defined only in xparameters.h and |
---|
43 | * BSP compiler flags, it is not defined in application |
---|
44 | * compiler flags. So, including xil_exception.h in |
---|
45 | * application source file, without including |
---|
46 | * xparameters.h results in incorrect behavior. |
---|
47 | * Including xparameters.h in xil_exception.h to avoid |
---|
48 | * such issues. It fixes CR#1120498. |
---|
49 | * 7.7 sk 03/02/22 Define XExc_VectorTableEntry structure to fix |
---|
50 | * misra_c_2012_rule_5_6 violation. |
---|
51 | * 7.7 sk 03/02/22 Add XExc_VectorTable as extern to fix misra_c_2012_ |
---|
52 | * rule_8_4 violation. |
---|
53 | * </pre> |
---|
54 | * |
---|
55 | ******************************************************************************/ |
---|
56 | |
---|
57 | /** |
---|
58 | *@cond nocomments |
---|
59 | */ |
---|
60 | |
---|
61 | #ifndef XIL_EXCEPTION_H /* prevent circular inclusions */ |
---|
62 | #define XIL_EXCEPTION_H /* by using protection macros */ |
---|
63 | |
---|
64 | /***************************** Include Files ********************************/ |
---|
65 | |
---|
66 | #include "xil_types.h" |
---|
67 | #include "xpseudo_asm.h" |
---|
68 | #include "bspconfig.h" |
---|
69 | #include "xparameters.h" |
---|
70 | |
---|
71 | #ifdef __cplusplus |
---|
72 | extern "C" { |
---|
73 | #endif |
---|
74 | |
---|
75 | /************************** Constant Definitions ****************************/ |
---|
76 | |
---|
77 | #define XIL_EXCEPTION_FIQ XREG_CPSR_FIQ_ENABLE |
---|
78 | #define XIL_EXCEPTION_IRQ XREG_CPSR_IRQ_ENABLE |
---|
79 | #define XIL_EXCEPTION_ALL (XREG_CPSR_FIQ_ENABLE | XREG_CPSR_IRQ_ENABLE) |
---|
80 | |
---|
81 | #define XIL_EXCEPTION_ID_FIRST 0U |
---|
82 | #if defined (__aarch64__) |
---|
83 | #define XIL_EXCEPTION_ID_SYNC_INT 1U |
---|
84 | #define XIL_EXCEPTION_ID_IRQ_INT 2U |
---|
85 | #define XIL_EXCEPTION_ID_FIQ_INT 3U |
---|
86 | #define XIL_EXCEPTION_ID_SERROR_ABORT_INT 4U |
---|
87 | #define XIL_EXCEPTION_ID_LAST 5U |
---|
88 | #else |
---|
89 | #define XIL_EXCEPTION_ID_RESET 0U |
---|
90 | #define XIL_EXCEPTION_ID_UNDEFINED_INT 1U |
---|
91 | #define XIL_EXCEPTION_ID_SWI_INT 2U |
---|
92 | #define XIL_EXCEPTION_ID_PREFETCH_ABORT_INT 3U |
---|
93 | #define XIL_EXCEPTION_ID_DATA_ABORT_INT 4U |
---|
94 | #define XIL_EXCEPTION_ID_IRQ_INT 5U |
---|
95 | #define XIL_EXCEPTION_ID_FIQ_INT 6U |
---|
96 | #define XIL_EXCEPTION_ID_LAST 6U |
---|
97 | #endif |
---|
98 | |
---|
99 | /* |
---|
100 | * XIL_EXCEPTION_ID_INT is defined for all Xilinx processors. |
---|
101 | */ |
---|
102 | #if defined (versal) && !defined(ARMR5) && EL3 |
---|
103 | #define XIL_EXCEPTION_ID_INT XIL_EXCEPTION_ID_FIQ_INT |
---|
104 | #else |
---|
105 | #define XIL_EXCEPTION_ID_INT XIL_EXCEPTION_ID_IRQ_INT |
---|
106 | #endif |
---|
107 | |
---|
108 | /**************************** Type Definitions ******************************/ |
---|
109 | |
---|
110 | /** |
---|
111 | * This typedef is the exception handler function. |
---|
112 | */ |
---|
113 | typedef void (*Xil_ExceptionHandler)(void *data); |
---|
114 | typedef void (*Xil_InterruptHandler)(void *data); |
---|
115 | |
---|
116 | typedef struct { |
---|
117 | Xil_ExceptionHandler Handler; |
---|
118 | void *Data; |
---|
119 | } XExc_VectorTableEntry; |
---|
120 | |
---|
121 | extern XExc_VectorTableEntry XExc_VectorTable[]; |
---|
122 | |
---|
123 | /** |
---|
124 | *@endcond |
---|
125 | */ |
---|
126 | |
---|
127 | /***************** Macros (Inline Functions) Definitions ********************/ |
---|
128 | |
---|
129 | /****************************************************************************/ |
---|
130 | /** |
---|
131 | * @brief Enable Exceptions. |
---|
132 | * |
---|
133 | * @param Mask: Value for enabling the exceptions. |
---|
134 | * |
---|
135 | * @return None. |
---|
136 | * |
---|
137 | * @note If bit is 0, exception is enabled. |
---|
138 | * C-Style signature: void Xil_ExceptionEnableMask(Mask) |
---|
139 | * |
---|
140 | ******************************************************************************/ |
---|
141 | #if defined (versal) && !defined(ARMR5) && EL3 |
---|
142 | /* |
---|
143 | * Cortexa72 processor in versal is coupled with GIC-500, and GIC-500 supports |
---|
144 | * only FIQ at EL3. Hence, tweaking this macro to always enable FIQ |
---|
145 | * ignoring argument passed by user. |
---|
146 | */ |
---|
147 | #define Xil_ExceptionEnableMask(Mask) \ |
---|
148 | mtcpsr(mfcpsr() & ~ ((XIL_EXCEPTION_FIQ) & XIL_EXCEPTION_ALL)) |
---|
149 | #elif defined (__GNUC__) || defined (__ICCARM__) |
---|
150 | #define Xil_ExceptionEnableMask(Mask) \ |
---|
151 | mtcpsr(mfcpsr() & ~ ((Mask) & XIL_EXCEPTION_ALL)) |
---|
152 | #else |
---|
153 | #define Xil_ExceptionEnableMask(Mask) \ |
---|
154 | { \ |
---|
155 | register u32 Reg __asm("cpsr"); \ |
---|
156 | mtcpsr((Reg) & (~((Mask) & XIL_EXCEPTION_ALL))); \ |
---|
157 | } |
---|
158 | #endif |
---|
159 | /****************************************************************************/ |
---|
160 | /** |
---|
161 | * @brief Enable the IRQ exception. |
---|
162 | * |
---|
163 | * @return None. |
---|
164 | * |
---|
165 | * @note None. |
---|
166 | * |
---|
167 | ******************************************************************************/ |
---|
168 | #if defined (versal) && !defined(ARMR5) && EL3 |
---|
169 | #define Xil_ExceptionEnable() \ |
---|
170 | Xil_ExceptionEnableMask(XIL_EXCEPTION_FIQ) |
---|
171 | #else |
---|
172 | #define Xil_ExceptionEnable() \ |
---|
173 | Xil_ExceptionEnableMask(XIL_EXCEPTION_IRQ) |
---|
174 | #endif |
---|
175 | |
---|
176 | /****************************************************************************/ |
---|
177 | /** |
---|
178 | * @brief Disable Exceptions. |
---|
179 | * |
---|
180 | * @param Mask: Value for disabling the exceptions. |
---|
181 | * |
---|
182 | * @return None. |
---|
183 | * |
---|
184 | * @note If bit is 1, exception is disabled. |
---|
185 | * C-Style signature: Xil_ExceptionDisableMask(Mask) |
---|
186 | * |
---|
187 | ******************************************************************************/ |
---|
188 | #if defined (versal) && !defined(ARMR5) && EL3 |
---|
189 | /* |
---|
190 | * Cortexa72 processor in versal is coupled with GIC-500, and GIC-500 supports |
---|
191 | * only FIQ at EL3. Hence, tweaking this macro to always disable FIQ |
---|
192 | * ignoring argument passed by user. |
---|
193 | */ |
---|
194 | #define Xil_ExceptionDisableMask(Mask) \ |
---|
195 | mtcpsr(mfcpsr() | ((XIL_EXCEPTION_FIQ) & XIL_EXCEPTION_ALL)) |
---|
196 | #elif defined (__GNUC__) || defined (__ICCARM__) |
---|
197 | #define Xil_ExceptionDisableMask(Mask) \ |
---|
198 | mtcpsr(mfcpsr() | ((Mask) & XIL_EXCEPTION_ALL)) |
---|
199 | #else |
---|
200 | #define Xil_ExceptionDisableMask(Mask) \ |
---|
201 | { \ |
---|
202 | register u32 Reg __asm("cpsr"); \ |
---|
203 | mtcpsr((Reg) | ((Mask) & XIL_EXCEPTION_ALL)); \ |
---|
204 | } |
---|
205 | #endif |
---|
206 | /****************************************************************************/ |
---|
207 | /** |
---|
208 | * Disable the IRQ exception. |
---|
209 | * |
---|
210 | * @return None. |
---|
211 | * |
---|
212 | * @note None. |
---|
213 | * |
---|
214 | ******************************************************************************/ |
---|
215 | #define Xil_ExceptionDisable() \ |
---|
216 | Xil_ExceptionDisableMask(XIL_EXCEPTION_IRQ) |
---|
217 | |
---|
218 | #if ( defined (PLATFORM_ZYNQMP) && defined (EL3) && (EL3==1) ) |
---|
219 | /****************************************************************************/ |
---|
220 | /** |
---|
221 | * @brief Enable nested interrupts by clearing the I bit in DAIF.This |
---|
222 | * macro is defined for Cortex-A53 64 bit mode BSP configured to run |
---|
223 | * at EL3.. However,it is not defined for Versal Cortex-A72 BSP |
---|
224 | * configured to run at EL3. Reason is, Cortex-A72 is coupled |
---|
225 | * with GIC-500(GICv3 specifications) and it triggers only FIQ at EL3. |
---|
226 | * |
---|
227 | * @return None. |
---|
228 | * |
---|
229 | * @note This macro is supposed to be used from interrupt handlers. In the |
---|
230 | * interrupt handler the interrupts are disabled by default (I bit |
---|
231 | * is set as 1). To allow nesting of interrupts, this macro should be |
---|
232 | * used. It clears the I bit. Once that bit is cleared and provided the |
---|
233 | * preemption of interrupt conditions are met in the GIC, nesting of |
---|
234 | * interrupts will start happening. |
---|
235 | * Caution: This macro must be used with caution. Before calling this |
---|
236 | * macro, the user must ensure that the source of the current IRQ |
---|
237 | * is appropriately cleared. Otherwise, as soon as we clear the I |
---|
238 | * bit, there can be an infinite loop of interrupts with an |
---|
239 | * eventual crash (all the stack space getting consumed). |
---|
240 | ******************************************************************************/ |
---|
241 | #define Xil_EnableNestedInterrupts() \ |
---|
242 | __asm__ __volatile__ ("mrs X1, ELR_EL3"); \ |
---|
243 | __asm__ __volatile__ ("mrs X2, SPSR_EL3"); \ |
---|
244 | __asm__ __volatile__ ("stp X1,X2, [sp,#-0x10]!"); \ |
---|
245 | __asm__ __volatile__ ("mrs X1, DAIF"); \ |
---|
246 | __asm__ __volatile__ ("bic X1,X1,#(0x1<<7)"); \ |
---|
247 | __asm__ __volatile__ ("msr DAIF, X1"); \ |
---|
248 | |
---|
249 | /****************************************************************************/ |
---|
250 | /** |
---|
251 | * @brief Disable the nested interrupts by setting the I bit in DAIF. This |
---|
252 | * macro is defined for Cortex-A53 64 bit mode BSP configured to run |
---|
253 | * at EL3. |
---|
254 | * |
---|
255 | * @return None. |
---|
256 | * |
---|
257 | * @note This macro is meant to be called in the interrupt service routines. |
---|
258 | * This macro cannot be used independently. It can only be used when |
---|
259 | * nesting of interrupts have been enabled by using the macro |
---|
260 | * Xil_EnableNestedInterrupts(). In a typical flow, the user first |
---|
261 | * calls the Xil_EnableNestedInterrupts in the ISR at the appropriate |
---|
262 | * point. The user then must call this macro before exiting the interrupt |
---|
263 | * service routine. This macro puts the ARM back in IRQ mode and |
---|
264 | * hence sets back the I bit. |
---|
265 | ******************************************************************************/ |
---|
266 | #define Xil_DisableNestedInterrupts() \ |
---|
267 | __asm__ __volatile__ ("ldp X1,X2, [sp,#0x10]!"); \ |
---|
268 | __asm__ __volatile__ ("msr ELR_EL3, X1"); \ |
---|
269 | __asm__ __volatile__ ("msr SPSR_EL3, X2"); \ |
---|
270 | __asm__ __volatile__ ("mrs X1, DAIF"); \ |
---|
271 | __asm__ __volatile__ ("orr X1, X1, #(0x1<<7)"); \ |
---|
272 | __asm__ __volatile__ ("msr DAIF, X1"); \ |
---|
273 | |
---|
274 | #elif (defined (EL1_NONSECURE) && (EL1_NONSECURE==1)) |
---|
275 | /****************************************************************************/ |
---|
276 | /** |
---|
277 | * @brief Enable nested interrupts by clearing the I bit in DAIF.This |
---|
278 | * macro is defined for Cortex-A53 64 bit mode and Cortex-A72 64 bit |
---|
279 | * BSP configured to run at EL1 NON SECURE |
---|
280 | * |
---|
281 | * @return None. |
---|
282 | * |
---|
283 | * @note This macro is supposed to be used from interrupt handlers. In the |
---|
284 | * interrupt handler the interrupts are disabled by default (I bit |
---|
285 | * is set as 1). To allow nesting of interrupts, this macro should be |
---|
286 | * used. It clears the I bit. Once that bit is cleared and provided the |
---|
287 | * preemption of interrupt conditions are met in the GIC, nesting of |
---|
288 | * interrupts will start happening. |
---|
289 | * Caution: This macro must be used with caution. Before calling this |
---|
290 | * macro, the user must ensure that the source of the current IRQ |
---|
291 | * is appropriately cleared. Otherwise, as soon as we clear the I |
---|
292 | * bit, there can be an infinite loop of interrupts with an |
---|
293 | * eventual crash (all the stack space getting consumed). |
---|
294 | ******************************************************************************/ |
---|
295 | #define Xil_EnableNestedInterrupts() \ |
---|
296 | __asm__ __volatile__ ("mrs X1, ELR_EL1"); \ |
---|
297 | __asm__ __volatile__ ("mrs X2, SPSR_EL1"); \ |
---|
298 | __asm__ __volatile__ ("stp X1,X2, [sp,#-0x10]!"); \ |
---|
299 | __asm__ __volatile__ ("mrs X1, DAIF"); \ |
---|
300 | __asm__ __volatile__ ("bic X1,X1,#(0x1<<7)"); \ |
---|
301 | __asm__ __volatile__ ("msr DAIF, X1"); \ |
---|
302 | |
---|
303 | /****************************************************************************/ |
---|
304 | /** |
---|
305 | * @brief Disable the nested interrupts by setting the I bit in DAIF. This |
---|
306 | * macro is defined for Cortex-A53 64 bit mode and Cortex-A72 64 bit |
---|
307 | * BSP configured to run at EL1 NON SECURE |
---|
308 | * |
---|
309 | * @return None. |
---|
310 | * |
---|
311 | * @note This macro is meant to be called in the interrupt service routines. |
---|
312 | * This macro cannot be used independently. It can only be used when |
---|
313 | * nesting of interrupts have been enabled by using the macro |
---|
314 | * Xil_EnableNestedInterrupts(). In a typical flow, the user first |
---|
315 | * calls the Xil_EnableNestedInterrupts in the ISR at the appropriate |
---|
316 | * point. The user then must call this macro before exiting the interrupt |
---|
317 | * service routine. This macro puts the ARM back in IRQ mode and |
---|
318 | * hence sets back the I bit. |
---|
319 | ******************************************************************************/ |
---|
320 | #define Xil_DisableNestedInterrupts() \ |
---|
321 | __asm__ __volatile__ ("ldp X1,X2, [sp,#0x10]!"); \ |
---|
322 | __asm__ __volatile__ ("msr ELR_EL1, X1"); \ |
---|
323 | __asm__ __volatile__ ("msr SPSR_EL1, X2"); \ |
---|
324 | __asm__ __volatile__ ("mrs X1, DAIF"); \ |
---|
325 | __asm__ __volatile__ ("orr X1, X1, #(0x1<<7)"); \ |
---|
326 | __asm__ __volatile__ ("msr DAIF, X1"); \ |
---|
327 | |
---|
328 | #elif (!defined (__aarch64__) && !defined (ARMA53_32)) |
---|
329 | /****************************************************************************/ |
---|
330 | /** |
---|
331 | * @brief Enable nested interrupts by clearing the I and F bits in CPSR. This |
---|
332 | * API is defined for cortex-a9 and cortex-r5. |
---|
333 | * |
---|
334 | * @return None. |
---|
335 | * |
---|
336 | * @note This macro is supposed to be used from interrupt handlers. In the |
---|
337 | * interrupt handler the interrupts are disabled by default (I and F |
---|
338 | * are 1). To allow nesting of interrupts, this macro should be |
---|
339 | * used. It clears the I and F bits by changing the ARM mode to |
---|
340 | * system mode. Once these bits are cleared and provided the |
---|
341 | * preemption of interrupt conditions are met in the GIC, nesting of |
---|
342 | * interrupts will start happening. |
---|
343 | * Caution: This macro must be used with caution. Before calling this |
---|
344 | * macro, the user must ensure that the source of the current IRQ |
---|
345 | * is appropriately cleared. Otherwise, as soon as we clear the I and |
---|
346 | * F bits, there can be an infinite loop of interrupts with an |
---|
347 | * eventual crash (all the stack space getting consumed). |
---|
348 | ******************************************************************************/ |
---|
349 | #define Xil_EnableNestedInterrupts() \ |
---|
350 | __asm__ __volatile__ ("stmfd sp!, {lr}"); \ |
---|
351 | __asm__ __volatile__ ("mrs lr, spsr"); \ |
---|
352 | __asm__ __volatile__ ("stmfd sp!, {lr}"); \ |
---|
353 | __asm__ __volatile__ ("msr cpsr_c, #0x1F"); \ |
---|
354 | __asm__ __volatile__ ("stmfd sp!, {lr}"); |
---|
355 | /****************************************************************************/ |
---|
356 | /** |
---|
357 | * @brief Disable the nested interrupts by setting the I and F bits. This API |
---|
358 | * is defined for cortex-a9 and cortex-r5. |
---|
359 | * |
---|
360 | * @return None. |
---|
361 | * |
---|
362 | * @note This macro is meant to be called in the interrupt service routines. |
---|
363 | * This macro cannot be used independently. It can only be used when |
---|
364 | * nesting of interrupts have been enabled by using the macro |
---|
365 | * Xil_EnableNestedInterrupts(). In a typical flow, the user first |
---|
366 | * calls the Xil_EnableNestedInterrupts in the ISR at the appropriate |
---|
367 | * point. The user then must call this macro before exiting the interrupt |
---|
368 | * service routine. This macro puts the ARM back in IRQ/FIQ mode and |
---|
369 | * hence sets back the I and F bits. |
---|
370 | ******************************************************************************/ |
---|
371 | #define Xil_DisableNestedInterrupts() \ |
---|
372 | __asm__ __volatile__ ("ldmfd sp!, {lr}"); \ |
---|
373 | __asm__ __volatile__ ("msr cpsr_c, #0x92"); \ |
---|
374 | __asm__ __volatile__ ("ldmfd sp!, {lr}"); \ |
---|
375 | __asm__ __volatile__ ("msr spsr_cxsf, lr"); \ |
---|
376 | __asm__ __volatile__ ("ldmfd sp!, {lr}"); \ |
---|
377 | |
---|
378 | #endif |
---|
379 | /************************** Variable Definitions ****************************/ |
---|
380 | |
---|
381 | /************************** Function Prototypes *****************************/ |
---|
382 | |
---|
383 | extern void Xil_ExceptionRegisterHandler(u32 Exception_id, |
---|
384 | Xil_ExceptionHandler Handler, |
---|
385 | void *Data); |
---|
386 | |
---|
387 | extern void Xil_ExceptionRemoveHandler(u32 Exception_id); |
---|
388 | extern void Xil_GetExceptionRegisterHandler(u32 Exception_id, |
---|
389 | Xil_ExceptionHandler *Handler, void **Data); |
---|
390 | |
---|
391 | extern void Xil_ExceptionInit(void); |
---|
392 | #if defined (__aarch64__) |
---|
393 | void Xil_SyncAbortHandler(void *CallBackRef); |
---|
394 | void Xil_SErrorAbortHandler(void *CallBackRef); |
---|
395 | #else |
---|
396 | extern void Xil_DataAbortHandler(void *CallBackRef); |
---|
397 | extern void Xil_PrefetchAbortHandler(void *CallBackRef); |
---|
398 | extern void Xil_UndefinedExceptionHandler(void *CallBackRef); |
---|
399 | #endif |
---|
400 | |
---|
401 | #ifdef __cplusplus |
---|
402 | } |
---|
403 | #endif /* __cplusplus */ |
---|
404 | |
---|
405 | #endif /* XIL_EXCEPTION_H */ |
---|
406 | /** |
---|
407 | * @} End of "addtogroup arm_exception_apis". |
---|
408 | */ |
---|