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 <sys/cdefs.h>
37 #include <stdint.h>
38
39 #if __ARM_ARCH_PROFILE == 'M'
40
41 #define STRINGIFY(x) #x
42
43 /* Interrupt functions */
44
45 void arm_halt_isr(void);
46
arm_halt_isr(void)47 void arm_halt_isr(void)
48 {
49 for(;;);
50 }
51
52 void arm_ignore_isr(void);
arm_ignore_isr(void)53 void arm_ignore_isr(void)
54 {
55 }
56
57 #define isr(name) \
58 void arm_ ## name ## _isr(void) __attribute__ ((weak, alias("arm_ignore_isr")));
59
60 #define isr_halt(name) \
61 void arm_ ## name ## _isr(void) __attribute__ ((weak, alias("arm_halt_isr")));
62
63 isr(nmi);
64 isr_halt(hardfault);
65 isr_halt(memmanage);
66 isr_halt(busfault);
67 isr_halt(usagefault);
68 isr(svc);
69 isr(debugmon);
70 isr(pendsv);
71 isr(systick);
72
73 void _start(void);
74 extern uint8_t __stack[];
75
76 #define i(addr,name) [(addr)/4] = (void(*)(void)) arm_ ## name ## _isr
77
78 __section(".data.init.enter")
79 void (* const __weak_interrupt_vector[])(void) __attribute((aligned(128))) = {
80 [0] = (void(*)(void))__stack,
81 [1] = _start,
82 i(0x08, nmi),
83 i(0x0c, hardfault),
84 i(0x10, memmanage),
85 i(0x14, busfault),
86 i(0x18, usagefault),
87 i(0x2c, svc),
88 i(0x30, debugmon),
89 i(0x38, pendsv),
90 i(0x3c, systick),
91 };
92 __weak_reference(__weak_interrupt_vector, __interrupt_vector);
93
94 #else
95
96 void arm_halt_isr(void);
97
98 void __attribute__((naked)) __section(".init")
arm_halt_vector(void)99 arm_halt_vector(void)
100 {
101 /* Loop forever. */
102 __asm__("1: b 1b");
103 }
104
105 void arm_ignore_isr(void);
106
107 void __attribute__((naked)) __section(".init")
arm_ignore_vector(void)108 arm_ignore_vector(void)
109 {
110 /* Ignore the interrupt by returning */
111 __asm__("bx lr");
112 }
113
114 #define vector(name) \
115 void arm_ ## name ## _vector(void) __attribute__ ((weak, alias("arm_ignore_vector")))
116
117 #define vector_halt(name) \
118 void arm_ ## name ## _vector(void) __attribute__ ((weak, alias("arm_halt_vector")))
119
120 vector_halt(undef);
121 vector_halt(svc);
122 vector_halt(prefetch_abort);
123 vector_halt(data_abort);
124 vector(not_used);
125 vector(irq);
126 vector(fiq);
127
128 void __attribute__((naked)) __section(".text.init.enter")
__weak_vector_table(void)129 __weak_vector_table(void)
130 {
131 /*
132 * Exception vector that lives at the
133 * start of program text (usually 0x0)
134 */
135 #if __thumb2__
136 /* Thumb 2 processors start in thumb mode */
137 __asm__(".thumb");
138 __asm__(".syntax unified");
139 __asm__("b.w _start");
140 __asm__("b.w arm_undef_vector");
141 __asm__("b.w arm_svc_vector");
142 __asm__("b.w arm_prefetch_abort_vector");
143 __asm__("b.w arm_data_abort_vector");
144 __asm__("b.w arm_not_used_vector");
145 __asm__("b.w arm_irq_vector");
146 __asm__("b.w arm_fiq_vector");
147 #else
148 /* Thumb 1 and arm processors start in arm mode */
149 __asm__(".arm");
150 __asm__("b _start");
151 __asm__("b arm_undef_vector");
152 __asm__("b arm_svc_vector");
153 __asm__("b arm_prefetch_abort_vector");
154 __asm__("b arm_data_abort_vector");
155 __asm__("b arm_not_used_vector");
156 __asm__("b arm_irq_vector");
157 __asm__("b arm_fiq_vector");
158 #endif
159 }
160
161 __weak_reference(__weak_vector_table, __vector_table);
162
163 #endif
164