1 /*
2  * Arm SCP/MCP Software
3  * Copyright (c) 2015-2022, Arm Limited and Contributors. All rights reserved.
4  *
5  * SPDX-License-Identifier: BSD-3-Clause
6  *
7  * Description:
8  *      ARM-M exception handlers.
9  */
10 
11 #include "arch_exceptions.h"
12 
13 #include <fwk_attributes.h>
14 
15 #include <fmw_cmsis.h>
16 
17 #include <stdint.h>
18 #include <string.h>
19 
20 #ifdef __NEWLIB__
21 /*
22  * This function overloads a weak definition provided by Newlib. It is called
23  * during initialization of the C runtime just after .bss has been zeroed.
24  */
software_init_hook(void)25 void software_init_hook(void)
26 {
27     extern char __data_load__;
28     extern char __data_start__;
29     extern char __data_end__;
30 
31     char *load = &__data_load__;
32     char *start = &__data_start__;
33     char *end = &__data_end__;
34 
35     if (load != start) {
36         (void)memcpy(start, load, (size_t)(end - start));
37     }
38 }
39 #endif
40 
41 #ifdef __ARMCC_VERSION
42 extern char Image$$ARM_LIB_STACKHEAP$$ZI$$Limit;
43 
44 #    define arch_exception_stack (&Image$$ARM_LIB_STACKHEAP$$ZI$$Limit)
45 #else
46 extern char __stackheap_end__;
47 
48 #    define arch_exception_stack (&__stackheap_end__)
49 #endif
50 
51 /*
52  * Set up the exception table. The structure below is added to the
53  * .exceptions section which will be explicitly placed at the beginning of the
54  * binary by the linker script.
55  */
56 
57 const struct {
58     uintptr_t stack;
59     uintptr_t exceptions[NVIC_USER_IRQ_OFFSET - 1];
60 } arch_exceptions FWK_SECTION(".exceptions") = {
61     .stack = (uintptr_t)(arch_exception_stack),
62     .exceptions = {
63         [NVIC_USER_IRQ_OFFSET + Reset_IRQn - 1] =
64             (uintptr_t)(arch_exception_reset),
65         [NonMaskableInt_IRQn +  (NVIC_USER_IRQ_OFFSET - 1)] =
66             (uintptr_t)(arch_exception_invalid),
67         [NVIC_USER_IRQ_OFFSET + HardFault_IRQn - 1] =
68             (uintptr_t)(arch_exception_invalid),
69         [NVIC_USER_IRQ_OFFSET + MemoryManagement_IRQn - 1] =
70             (uintptr_t)(arch_exception_invalid),
71         [NVIC_USER_IRQ_OFFSET + BusFault_IRQn - 1] =
72             (uintptr_t)(arch_exception_invalid),
73         [NVIC_USER_IRQ_OFFSET + UsageFault_IRQn - 1] =
74             (uintptr_t)(arch_exception_invalid),
75 #ifdef ARMV8M
76         [NVIC_USER_IRQ_OFFSET + SecureFault_IRQn - 1] =
77             (uintptr_t)(arch_exception_invalid),
78 #endif
79         [NVIC_USER_IRQ_OFFSET + DebugMonitor_IRQn - 1] =
80             (uintptr_t)(arch_exception_invalid),
81 
82         [NVIC_USER_IRQ_OFFSET + SVCall_IRQn - 1] =
83             (uintptr_t)(arch_exception_invalid),
84         [NVIC_USER_IRQ_OFFSET + PendSV_IRQn - 1] =
85             (uintptr_t)(arch_exception_invalid),
86         [NVIC_USER_IRQ_OFFSET + SysTick_IRQn - 1] =
87             (uintptr_t)(arch_exception_invalid),
88     },
89 };
90