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