altos: Add program flash function
[fw/altos] / src / stm / ao_interrupt.c
1 /*
2  * Copyright © 2012 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; version 2 of the License.
7  *
8  * This program is distributed in the hope that it will be useful, but
9  * WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11  * General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License along
14  * with this program; if not, write to the Free Software Foundation, Inc.,
15  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
16  */
17
18 #include <ao.h>
19 #include "stm32l.h"
20 #include <string.h>
21
22 extern void main(void);
23 extern char __stack__;
24 extern char __text_start__, __text_end__;
25 extern char __data_start__, __data_end__;
26 extern char __bss_start__, __bss_end__;
27
28 /* Interrupt functions */
29
30 void stm_halt_isr(void)
31 {
32         ao_panic(AO_PANIC_CRASH);
33 }
34
35 void stm_ignore_isr(void)
36 {
37 }
38
39 const void *stm_interrupt_vector[];
40
41 #define BOOT_FETCH(o)   (*((uint32_t *) (AO_BOOT_APPLICATION_BASE + (o))))
42
43 #ifdef AO_BOOT_APPLICATION_PIN
44 #include <ao_exti.h>
45
46 #define AO_BOOT_APPLICATION             0x5a5aa5a5
47 #define AO_BOOT_APPLICATION_CHECK       0xc3c33c3c
48
49 static uint32_t ao_boot_application;
50 static uint32_t ao_boot_application_check;
51
52 static void
53 ao_boot_chain(void) {
54         uint32_t        sp;
55         uint32_t        pc;
56
57         sp = BOOT_FETCH(0);
58         pc = BOOT_FETCH(4);
59         asm ("mov sp, %0" : : "r" (sp));
60         asm ("mov lr, %0" : : "r" (pc));
61         asm ("bx lr");
62 }
63
64 void
65 ao_reboot_application(void)
66 {
67         ao_boot_application = AO_BOOT_APPLICATION;
68         ao_boot_application_check = AO_BOOT_APPLICATION_CHECK;
69         ao_arch_reboot();
70 }
71
72 #endif
73
74 void start(void) {
75 #ifdef AO_BOOT_APPLICATION_PIN
76         uint16_t v;
77
78         if (ao_boot_application == AO_BOOT_APPLICATION &&
79             ao_boot_application_check == AO_BOOT_APPLICATION_CHECK) {
80                 ao_boot_application = 0;
81                 ao_boot_application_check = 0;
82                 ao_boot_chain();
83         }
84         /* Enable power interface clock */
85         stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_PWREN);
86         
87         /* Enable the input pin */
88         ao_enable_input(&AO_BOOT_APPLICATION_GPIO, AO_BOOT_APPLICATION_PIN,
89                         AO_BOOT_APPLICATION_MODE);
90
91         /* Read the value */
92         v = stm_gpio_get(&AO_BOOT_APPLICATION_GPIO, AO_BOOT_APPLICATION_PIN);
93
94         /* Reset the chip to turn off the port and the power interface clock */
95         ao_gpio_set_mode(&AO_BOOT_APPLICATION_GPIO, AO_BOOT_APPLICATION_PIN, 0);
96         ao_disable_port(&AO_BOOT_APPLICATION_GPIO);
97         stm_rcc.apb1enr &= ~(1 << STM_RCC_APB1ENR_PWREN);
98         if (v == AO_BOOT_APPLICATION_VALUE)
99                 ao_boot_chain();
100 #endif
101
102         /* Set interrupt vector table offset */
103         stm_nvic.vto = (uint32_t) &stm_interrupt_vector;
104         memcpy(&__data_start__, &__text_end__, &__data_end__ - &__data_start__);
105         memset(&__bss_start__, '\0', &__bss_end__ - &__bss_start__);
106         main();
107 }
108
109 #define STRINGIFY(x) #x
110
111 #define isr(name) \
112         void __attribute__ ((weak)) stm_ ## name ## _isr(void); \
113         _Pragma(STRINGIFY(weak stm_ ## name ## _isr = stm_ignore_isr))
114
115 #define isr_halt(name) \
116         void __attribute__ ((weak)) stm_ ## name ## _isr(void); \
117         _Pragma(STRINGIFY(weak stm_ ## name ## _isr = stm_halt_isr))
118
119 isr(nmi)
120 isr_halt(hardfault)
121 isr_halt(memmanage)
122 isr_halt(busfault)
123 isr_halt(usagefault)
124 isr(svc)
125 isr(debugmon)
126 isr(pendsv)
127 isr(systick)
128 isr(wwdg)
129 isr(pvd)
130 isr(tamper_stamp)
131 isr(rtc_wkup)
132 isr(flash)
133 isr(rcc)
134 isr(exti0)
135 isr(exti1)
136 isr(exti2)
137 isr(exti3)
138 isr(exti4)
139 isr(dma1_channel1)
140 isr(dma1_channel2)
141 isr(dma1_channel3)
142 isr(dma1_channel4)
143 isr(dma1_channel5)
144 isr(dma1_channel6)
145 isr(dma1_channel7)
146 isr(adc1)
147 isr(usb_hp)
148 isr(usb_lp)
149 isr(dac)
150 isr(comp)
151 isr(exti9_5)
152 isr(lcd)
153 isr(tim9)
154 isr(tim10)
155 isr(tim11)
156 isr(tim2)
157 isr(tim3)
158 isr(tim4)
159 isr(i2c1_ev)
160 isr(i2c1_er)
161 isr(i2c2_ev)
162 isr(i2c2_er)
163 isr(spi1)
164 isr(spi2)
165 isr(usart1)
166 isr(usart2)
167 isr(usart3)
168 isr(exti15_10)
169 isr(rtc_alarm)
170 isr(usb_fs_wkup)
171 isr(tim6)
172 isr(tim7)
173
174 #define i(addr,name)    [(addr)/4] = stm_ ## name ## _isr
175
176 __attribute__ ((section(".interrupt")))
177 const void *stm_interrupt_vector[] = {
178         [0] = &__stack__,
179         [1] = start,
180         i(0x08, nmi),
181         i(0x0c, hardfault),
182         i(0x10, memmanage),
183         i(0x14, busfault),
184         i(0x18, usagefault),
185         i(0x2c, svc),
186         i(0x30, debugmon),
187         i(0x38, pendsv),
188         i(0x3c, systick),
189         i(0x40, wwdg),
190         i(0x44, pvd),
191         i(0x48, tamper_stamp),
192         i(0x4c, rtc_wkup),
193         i(0x50, flash),
194         i(0x54, rcc),
195         i(0x58, exti0),
196         i(0x5c, exti1),
197         i(0x60, exti2),
198         i(0x64, exti3),
199         i(0x68, exti4),
200         i(0x6c, dma1_channel1),
201         i(0x70, dma1_channel2),
202         i(0x74, dma1_channel3),
203         i(0x78, dma1_channel4),
204         i(0x7c, dma1_channel5),
205         i(0x80, dma1_channel6),
206         i(0x84, dma1_channel7),
207         i(0x88, adc1),
208         i(0x8c, usb_hp),
209         i(0x90, usb_lp),
210         i(0x94, dac),
211         i(0x98, comp),
212         i(0x9c, exti9_5),
213         i(0xa0, lcd),
214         i(0xa4, tim9),
215         i(0xa8, tim10),
216         i(0xac, tim11),
217         i(0xb0, tim2),
218         i(0xb4, tim3),
219         i(0xb8, tim4),
220         i(0xbc, i2c1_ev),
221         i(0xc0, i2c1_er),
222         i(0xc4, i2c2_ev),
223         i(0xc8, i2c2_er),
224         i(0xcc, spi1),
225         i(0xd0, spi2),
226         i(0xd4, usart1),
227         i(0xd8, usart2),
228         i(0xdc, usart3),
229         i(0xe0, exti15_10),
230         i(0xe4, rtc_alarm),
231         i(0xe8, usb_fs_wkup),
232         i(0xec, tim6),
233         i(0xf0, tim7),
234 };