Merge branch 'master'
[fw/altos] / src / samd21 / ao_interrupt.c
1 /*
2  * Copyright © 2019 Keith Packard <keithp@keithp.com>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * General Public License for more details.
13  */
14
15 #include <ao.h>
16 #include <ao_boot.h>
17
18 /* Interrupt functions */
19
20 void samd21_halt_isr(void)
21 {
22         ao_panic(AO_PANIC_CRASH);
23 }
24
25 void samd21_ignore_isr(void)
26 {
27 }
28
29 uint32_t
30 samd21_flash_size(void)
31 {
32         uint32_t        nvmp = (samd21_nvmctrl.param >> SAMD21_NVMCTRL_PARAM_NVMP) & SAMD21_NVMCTRL_PARAM_NVMP_MASK;
33         uint32_t        psz = (samd21_nvmctrl.param >> SAMD21_NVMCTRL_PARAM_PSZ) & SAMD21_NVMCTRL_PARAM_PSZ_MASK;
34
35         /* page size is 2**(3 + psz) */
36         return nvmp << (3 + psz);
37 }
38
39 #define STRINGIFY(x) #x
40
41 #define isr(name) \
42         void __attribute__ ((weak)) samd21_ ## name ## _isr(void); \
43         _Pragma(STRINGIFY(weak samd21_ ## name ## _isr = samd21_ignore_isr))
44
45 #define isr_halt(name) \
46         void __attribute__ ((weak)) samd21_ ## name ## _isr(void); \
47         _Pragma(STRINGIFY(weak samd21_ ## name ## _isr = samd21_halt_isr))
48
49 isr(nmi);
50 isr_halt(hardfault);
51 isr_halt(memmanage);
52 isr_halt(busfault);
53 isr_halt(usagefault);
54 isr(svc);
55 isr(debugmon);
56 isr(pendsv);
57 isr(systick);
58 isr(pm);                /* IRQ0 */
59 isr(sysctrl);
60 isr(wdt);
61 isr(rtc);
62 isr(eic);
63 isr(nvmctrl);
64 isr(dmac);
65 isr(usb);
66 isr(evsys);
67 isr(sercom0);
68 isr(sercom1);
69 isr(sercom2);
70 isr(sercom3);
71 isr(sercom4);
72 isr(sercom5);
73 isr(tcc0);
74 isr(tcc1);
75 isr(tcc2);
76 isr(tc3);
77 isr(tc4);
78 isr(tc5);
79 isr(tc6);
80 isr(tc7);
81 isr(adc);
82 isr(ac);
83 isr(dac);
84 isr(ptc);
85 isr(i2s);
86 isr(ac1);
87 isr(tcc3);
88
89 #undef isr
90 #undef isr_halt
91
92 #define i(addr,name)    [(addr)/4] = samd21_ ## name ## _isr
93
94 extern char __stack[];
95 void _start(void) __attribute__((__noreturn__));
96 void main(void) __attribute__((__noreturn__));
97
98 __attribute__ ((section(".init")))
99 void (*const __interrupt_vector[])(void) __attribute((aligned(128))) = {
100         [0] = (void *) __stack,
101         [1] = _start,
102         i(0x08, nmi),
103         i(0x0c, hardfault),
104         i(0x2c, svc),
105         i(0x30, debugmon),
106         i(0x38, pendsv),
107         i(0x3c, systick),
108
109         i(0x40, pm),            /* IRQ0 */
110         i(0x44, sysctrl),
111         i(0x48, wdt),
112         i(0x4c, rtc),
113         i(0x50, eic),
114         i(0x54, nvmctrl),
115         i(0x58, dmac),
116         i(0x5c, usb),
117         i(0x60, evsys),
118         i(0x64, sercom0),
119         i(0x68, sercom1),
120         i(0x6c, sercom2),
121         i(0x70, sercom3),
122         i(0x74, sercom4),
123         i(0x78, sercom5),
124         i(0x7c, tcc0),
125         i(0x80, tcc1),
126         i(0x84, tcc2),
127         i(0x88, tc3),
128         i(0x8c, tc4),
129         i(0x90, tc5),
130         i(0x94, tc6),
131         i(0x98, tc7),
132         i(0x9c, adc),
133         i(0xa0, ac),
134         i(0xa4, dac),
135         i(0xa8, ptc),
136         i(0xac, i2s),
137         i(0xb0, ac1),
138         i(0xb4, tcc3),
139 };
140
141 extern char __data_source[];
142 extern char __data_start[];
143 extern char __data_size[];
144 extern char __bss_start[];
145 extern char __bss_size[];
146
147 void _start(void)
148 {
149         memcpy(__data_start, __data_source, (uintptr_t) __data_size);
150         memset(__bss_start, '\0', (uintptr_t) __bss_size);
151
152 #if AO_BOOT_CHAIN
153         if (ao_boot_check_chain()) {
154 #if AO_BOOT_PIN
155                 if (ao_boot_check_pin())
156 #endif
157                 {
158                         ao_boot_chain(AO_BOOT_APPLICATION_BASE);
159                 }
160         }
161 #endif
162
163         /* Turn on sysctrl */
164         samd21_pm.apbamask |= (1 << SAMD21_PM_APBAMASK_SYSCTRL);
165         /* Set interrupt vector */
166         samd21_scb.vtor = (uint32_t) &__interrupt_vector;
167
168         main();
169 }