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