summaryrefslogtreecommitdiff
path: root/core/cortex-m0/vecttable.c
blob: 3871a30055bb76013d36bce7a94259a69d6ce863 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
/* Copyright 2018 The ChromiumOS Authors
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 *
 * Cortex-M CPU vector table
 */

#ifndef ___INIT
#define ___INIT
#include <stddef.h>
#include <stdint.h>

#include "config.h"
#include "panic-internal.h"
#include "task.h"
#endif /* __INIT */

typedef void (*func)(void);

#ifndef PASS
#define PASS 1
#endif

#if PASS == 1

void __attribute__((naked)) default_handler(void)
{
	/*
	 * An (enforced) long tail call to preserve exn_return in lr without
	 * restricting the relative placement of default_handler and
	 * exception_panic.
	 */
	asm volatile("bx %0\n" : : "r"(exception_panic));
}

#define table(x) x

/* Note: the alias target must be defined in this translation unit */
#define weak_with_default __attribute__((used, weak, alias("default_handler")))

#define vec(name) extern void weak_with_default name##_handler(void);
#define irq(num) vec(irq_##num)

#define item(name) extern void name(void);
#define null

extern void stack_end(void); /* not technically correct, it's just a pointer */
extern void reset(void);

#endif /* PASS 1 */

#if PASS == 2
#undef table
#undef vec
#undef irq
#undef item
#undef null

/* number of elements before the first irq vector */
#define IRQ_OFFSET 16
/* element in the table that is null: extra IRQs are routed there,
 * then finally overwritten
 */
#define IRQ_UNUSED_OFFSET 8

/* Disable warning that "initializer overrides prior initialization of this
 * subobject", since we are explicitly doing this to handle the unused IRQs.
 */
#ifdef __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Winitializer-overrides"
#endif /* __clang__ */

#define table(x)                             \
	const func vectors[] __attribute__(( \
		section(".text.vecttable"))) = { x[IRQ_UNUSED_OFFSET] = null }

#define vec(name) name##_handler,
#define irq(num)                                                          \
	[num < CONFIG_IRQ_COUNT ? num + IRQ_OFFSET : IRQ_UNUSED_OFFSET] = \
		vec(irq_##num)

#define item(name) name,
#define null (void *)0,
#endif /* PASS 2 */

table(item(stack_end) item(reset) vec(nmi) vec(hard_fault) vec(mpu_fault) vec(
	bus_fault) vec(usage_fault) null null null null vec(svc) vec(debug)
	      null vec(pendsv) vec(sys_tick) irq(0) irq(1) irq(2) irq(3) irq(4)
		      irq(5) irq(6) irq(7) irq(8) irq(9) irq(10) irq(11) irq(12)
			      irq(13) irq(14) irq(15) irq(16) irq(17) irq(18)
				      irq(19) irq(20) irq(21) irq(22) irq(23)
					      irq(24) irq(25) irq(26) irq(27)
						      irq(28) irq(29) irq(30)
							      irq(31));

#if PASS == 2
#ifdef __clang__
#pragma clang diagnostic pop
#endif /* __clang__ */
#endif

#if PASS == 1
#undef PASS
#define PASS 2
#include "vecttable.c"
#endif