1 /*
2 * SPDX-License-Identifier: BSD-3-Clause
3 *
4 * Copyright © 2019 Keith Packard
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 *
13 * 2. Redistributions in binary form must reproduce the above
14 * copyright notice, this list of conditions and the following
15 * disclaimer in the documentation and/or other materials provided
16 * with the distribution.
17 *
18 * 3. Neither the name of the copyright holder nor the names of its
19 * contributors may be used to endorse or promote products derived
20 * from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
27 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
29 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
31 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
33 * OF THE POSSIBILITY OF SUCH DAMAGE.
34 */
35
36 #include <stdint.h>
37
38 #if __ARM_ARCH_PROFILE == 'M'
39
40 #define STRINGIFY(x) #x
41
42 /* Interrupt functions */
43
44 void arm_halt_isr(void);
45
arm_halt_isr(void)46 void arm_halt_isr(void)
47 {
48 for(;;);
49 }
50
51 void arm_ignore_isr(void);
arm_ignore_isr(void)52 void arm_ignore_isr(void)
53 {
54 }
55
56 #define isr(name) \
57 void arm_ ## name ## _isr(void) __attribute__ ((weak, alias("arm_ignore_isr")));
58
59 #define isr_halt(name) \
60 void arm_ ## name ## _isr(void) __attribute__ ((weak, alias("arm_halt_isr")));
61
62 isr(nmi);
63 isr_halt(hardfault);
64 isr_halt(memmanage);
65 isr_halt(busfault);
66 isr_halt(usagefault);
67 isr(svc);
68 isr(debugmon);
69 isr(pendsv);
70 isr(systick);
71
72 void _start(void);
73 extern uint8_t __stack[];
74
75 #define i(addr,name) [(addr)/4] = (void(*)(void)) arm_ ## name ## _isr
76
77 __section(".data.init.enter")
78 void (* const __weak_interrupt_vector[])(void) __attribute((aligned(128))) = {
79 [0] = (void(*)(void))__stack,
80 [1] = _start,
81 i(0x08, nmi),
82 i(0x0c, hardfault),
83 i(0x10, memmanage),
84 i(0x14, busfault),
85 i(0x18, usagefault),
86 i(0x2c, svc),
87 i(0x30, debugmon),
88 i(0x38, pendsv),
89 i(0x3c, systick),
90 };
91 __weak_reference(__weak_interrupt_vector, __interrupt_vector);
92
93 #else
94
95 void arm_halt_vector(void);
96
97 void __attribute__((naked)) __section(".init")
arm_halt_vector(void)98 arm_halt_vector(void)
99 {
100 /* Loop forever. */
101 __asm__("1: b 1b");
102 }
103
104 void arm_ignore_vector(void);
105
106 void __attribute__((naked)) __section(".init")
arm_ignore_vector(void)107 arm_ignore_vector(void)
108 {
109 /* Ignore the interrupt by returning */
110 __asm__("bx lr");
111 }
112
113 #define vector(name) \
114 void arm_ ## name ## _vector(void) __attribute__ ((weak, alias("arm_ignore_vector")))
115
116 #define vector_halt(name) \
117 void arm_ ## name ## _vector(void) __attribute__ ((weak, alias("arm_halt_vector")))
118
119 vector_halt(undef);
120 vector_halt(svc);
121 vector_halt(prefetch_abort);
122 vector_halt(data_abort);
123 vector(not_used);
124 vector(irq);
125 vector(fiq);
126
127 void
128 __weak_vector_table(void);
129
130 void __attribute__((naked)) __section(".text.init.enter")
__weak_vector_table(void)131 __weak_vector_table(void)
132 {
133 /*
134 * Exception vector that lives at the
135 * start of program text (usually 0x0)
136 */
137 #if __thumb2__ && __ARM_ARCH_PROFILE != 'A'
138 /* Thumb 2 processors start in thumb mode */
139 __asm__(".thumb\n"
140 ".syntax unified\n"
141 "b.w _start\n"
142 "b.w arm_undef_vector\n"
143 "b.w arm_svc_vector\n"
144 "b.w arm_prefetch_abort_vector\n"
145 "b.w arm_data_abort_vector\n"
146 "b.w arm_not_used_vector\n"
147 "b.w arm_irq_vector\n"
148 "b.w arm_fiq_vector");
149 #else
150 /* Thumb 1 and arm processors start in arm mode */
151 __asm__(".arm\n"
152 "b _start\n"
153 "b arm_undef_vector\n"
154 "b arm_svc_vector\n"
155 "b arm_prefetch_abort_vector\n"
156 "b arm_data_abort_vector\n"
157 "b arm_not_used_vector\n"
158 "b arm_irq_vector\n"
159 "b arm_fiq_vector");
160 #endif
161 }
162
163 __weak_reference(__weak_vector_table, __vector_table);
164
165 #endif
166