35f00b6c |
1 | /* Teensyduino Core Library |
2 | * http://www.pjrc.com/teensy/ |
3 | * Copyright (c) 2013 PJRC.COM, LLC. |
4 | * |
5 | * Permission is hereby granted, free of charge, to any person obtaining |
6 | * a copy of this software and associated documentation files (the |
7 | * "Software"), to deal in the Software without restriction, including |
8 | * without limitation the rights to use, copy, modify, merge, publish, |
9 | * distribute, sublicense, and/or sell copies of the Software, and to |
10 | * permit persons to whom the Software is furnished to do so, subject to |
11 | * the following conditions: |
12 | * |
13 | * 1. The above copyright notice and this permission notice shall be |
14 | * included in all copies or substantial portions of the Software. |
15 | * |
16 | * 2. If the Software is incorporated into a build system that allows |
17 | * selection among a list of target devices, then similar target |
18 | * devices manufactured by PJRC.COM must be included in the list of |
19 | * target devices and selectable in the same manner. |
20 | * |
21 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
22 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
23 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
24 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS |
25 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN |
26 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN |
27 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
28 | * SOFTWARE. |
29 | */ |
30 | |
a773ac06 |
31 | #include "kinetis.h" |
35f00b6c |
32 | |
33 | |
34 | extern unsigned long _stext; |
35 | extern unsigned long _etext; |
36 | extern unsigned long _sdata; |
37 | extern unsigned long _edata; |
38 | extern unsigned long _sbss; |
39 | extern unsigned long _ebss; |
40 | extern unsigned long _estack; |
41 | //extern void __init_array_start(void); |
42 | //extern void __init_array_end(void); |
a773ac06 |
43 | |
44 | |
45 | |
35f00b6c |
46 | extern int main (void); |
47 | void ResetHandler(void); |
48 | void _init_Teensyduino_internal_(void); |
49 | void __libc_init_array(void); |
50 | |
51 | |
52 | void fault_isr(void) |
53 | { |
54 | while (1) { |
55 | // keep polling some communication while in fault |
56 | // mode, so we don't completely die. |
57 | if (SIM_SCGC4 & SIM_SCGC4_USBOTG) usb_isr(); |
58 | if (SIM_SCGC4 & SIM_SCGC4_UART0) uart0_status_isr(); |
59 | if (SIM_SCGC4 & SIM_SCGC4_UART1) uart1_status_isr(); |
60 | if (SIM_SCGC4 & SIM_SCGC4_UART2) uart2_status_isr(); |
61 | } |
62 | } |
63 | |
64 | void unused_isr(void) |
65 | { |
66 | fault_isr(); |
67 | } |
68 | |
69 | extern volatile uint32_t systick_millis_count; |
70 | void systick_default_isr(void) |
71 | { |
72 | systick_millis_count++; |
73 | } |
74 | |
75 | void nmi_isr(void) __attribute__ ((weak, alias("unused_isr"))); |
76 | void hard_fault_isr(void) __attribute__ ((weak, alias("unused_isr"))); |
77 | void memmanage_fault_isr(void) __attribute__ ((weak, alias("unused_isr"))); |
78 | void bus_fault_isr(void) __attribute__ ((weak, alias("unused_isr"))); |
79 | void usage_fault_isr(void) __attribute__ ((weak, alias("unused_isr"))); |
80 | void svcall_isr(void) __attribute__ ((weak, alias("unused_isr"))); |
81 | void debugmonitor_isr(void) __attribute__ ((weak, alias("unused_isr"))); |
82 | void pendablesrvreq_isr(void) __attribute__ ((weak, alias("unused_isr"))); |
83 | void systick_isr(void) __attribute__ ((weak, alias("systick_default_isr"))); |
84 | |
85 | void dma_ch0_isr(void) __attribute__ ((weak, alias("unused_isr"))); |
86 | void dma_ch1_isr(void) __attribute__ ((weak, alias("unused_isr"))); |
87 | void dma_ch2_isr(void) __attribute__ ((weak, alias("unused_isr"))); |
88 | void dma_ch3_isr(void) __attribute__ ((weak, alias("unused_isr"))); |
89 | void dma_ch4_isr(void) __attribute__ ((weak, alias("unused_isr"))); |
90 | void dma_ch5_isr(void) __attribute__ ((weak, alias("unused_isr"))); |
91 | void dma_ch6_isr(void) __attribute__ ((weak, alias("unused_isr"))); |
92 | void dma_ch7_isr(void) __attribute__ ((weak, alias("unused_isr"))); |
93 | void dma_ch8_isr(void) __attribute__ ((weak, alias("unused_isr"))); |
94 | void dma_ch9_isr(void) __attribute__ ((weak, alias("unused_isr"))); |
95 | void dma_ch10_isr(void) __attribute__ ((weak, alias("unused_isr"))); |
96 | void dma_ch11_isr(void) __attribute__ ((weak, alias("unused_isr"))); |
97 | void dma_ch12_isr(void) __attribute__ ((weak, alias("unused_isr"))); |
98 | void dma_ch13_isr(void) __attribute__ ((weak, alias("unused_isr"))); |
99 | void dma_ch14_isr(void) __attribute__ ((weak, alias("unused_isr"))); |
100 | void dma_ch15_isr(void) __attribute__ ((weak, alias("unused_isr"))); |
101 | void dma_error_isr(void) __attribute__ ((weak, alias("unused_isr"))); |
102 | void mcm_isr(void) __attribute__ ((weak, alias("unused_isr"))); |
103 | void flash_cmd_isr(void) __attribute__ ((weak, alias("unused_isr"))); |
104 | void flash_error_isr(void) __attribute__ ((weak, alias("unused_isr"))); |
105 | void low_voltage_isr(void) __attribute__ ((weak, alias("unused_isr"))); |
106 | void wakeup_isr(void) __attribute__ ((weak, alias("unused_isr"))); |
107 | void watchdog_isr(void) __attribute__ ((weak, alias("unused_isr"))); |
108 | void i2c0_isr(void) __attribute__ ((weak, alias("unused_isr"))); |
109 | void i2c1_isr(void) __attribute__ ((weak, alias("unused_isr"))); |
110 | void i2c2_isr(void) __attribute__ ((weak, alias("unused_isr"))); |
111 | void spi0_isr(void) __attribute__ ((weak, alias("unused_isr"))); |
112 | void spi1_isr(void) __attribute__ ((weak, alias("unused_isr"))); |
113 | void spi2_isr(void) __attribute__ ((weak, alias("unused_isr"))); |
114 | void sdhc_isr(void) __attribute__ ((weak, alias("unused_isr"))); |
115 | void can0_message_isr(void) __attribute__ ((weak, alias("unused_isr"))); |
116 | void can0_bus_off_isr(void) __attribute__ ((weak, alias("unused_isr"))); |
117 | void can0_error_isr(void) __attribute__ ((weak, alias("unused_isr"))); |
118 | void can0_tx_warn_isr(void) __attribute__ ((weak, alias("unused_isr"))); |
119 | void can0_rx_warn_isr(void) __attribute__ ((weak, alias("unused_isr"))); |
120 | void can0_wakeup_isr(void) __attribute__ ((weak, alias("unused_isr"))); |
121 | void i2s0_tx_isr(void) __attribute__ ((weak, alias("unused_isr"))); |
122 | void i2s0_rx_isr(void) __attribute__ ((weak, alias("unused_isr"))); |
123 | void uart0_lon_isr(void) __attribute__ ((weak, alias("unused_isr"))); |
124 | void uart0_status_isr(void) __attribute__ ((weak, alias("unused_isr"))); |
125 | void uart0_error_isr(void) __attribute__ ((weak, alias("unused_isr"))); |
126 | void uart1_status_isr(void) __attribute__ ((weak, alias("unused_isr"))); |
127 | void uart1_error_isr(void) __attribute__ ((weak, alias("unused_isr"))); |
128 | void uart2_status_isr(void) __attribute__ ((weak, alias("unused_isr"))); |
129 | void uart2_error_isr(void) __attribute__ ((weak, alias("unused_isr"))); |
130 | void uart3_status_isr(void) __attribute__ ((weak, alias("unused_isr"))); |
131 | void uart3_error_isr(void) __attribute__ ((weak, alias("unused_isr"))); |
132 | void uart4_status_isr(void) __attribute__ ((weak, alias("unused_isr"))); |
133 | void uart4_error_isr(void) __attribute__ ((weak, alias("unused_isr"))); |
134 | void uart5_status_isr(void) __attribute__ ((weak, alias("unused_isr"))); |
135 | void uart5_error_isr(void) __attribute__ ((weak, alias("unused_isr"))); |
136 | void adc0_isr(void) __attribute__ ((weak, alias("unused_isr"))); |
137 | void adc1_isr(void) __attribute__ ((weak, alias("unused_isr"))); |
138 | void cmp0_isr(void) __attribute__ ((weak, alias("unused_isr"))); |
139 | void cmp1_isr(void) __attribute__ ((weak, alias("unused_isr"))); |
140 | void cmp2_isr(void) __attribute__ ((weak, alias("unused_isr"))); |
141 | void ftm0_isr(void) __attribute__ ((weak, alias("unused_isr"))); |
142 | void ftm1_isr(void) __attribute__ ((weak, alias("unused_isr"))); |
143 | void ftm2_isr(void) __attribute__ ((weak, alias("unused_isr"))); |
144 | void ftm3_isr(void) __attribute__ ((weak, alias("unused_isr"))); |
145 | void cmt_isr(void) __attribute__ ((weak, alias("unused_isr"))); |
146 | void rtc_alarm_isr(void) __attribute__ ((weak, alias("unused_isr"))); |
147 | void rtc_seconds_isr(void) __attribute__ ((weak, alias("unused_isr"))); |
148 | void pit0_isr(void) __attribute__ ((weak, alias("unused_isr"))); |
149 | void pit1_isr(void) __attribute__ ((weak, alias("unused_isr"))); |
150 | void pit2_isr(void) __attribute__ ((weak, alias("unused_isr"))); |
151 | void pit3_isr(void) __attribute__ ((weak, alias("unused_isr"))); |
152 | void pdb_isr(void) __attribute__ ((weak, alias("unused_isr"))); |
153 | void usb_isr(void) __attribute__ ((weak, alias("unused_isr"))); |
154 | void usb_charge_isr(void) __attribute__ ((weak, alias("unused_isr"))); |
155 | void dac0_isr(void) __attribute__ ((weak, alias("unused_isr"))); |
156 | void dac1_isr(void) __attribute__ ((weak, alias("unused_isr"))); |
157 | void tsi0_isr(void) __attribute__ ((weak, alias("unused_isr"))); |
158 | void mcg_isr(void) __attribute__ ((weak, alias("unused_isr"))); |
159 | void lptmr_isr(void) __attribute__ ((weak, alias("unused_isr"))); |
160 | void porta_isr(void) __attribute__ ((weak, alias("unused_isr"))); |
161 | void portb_isr(void) __attribute__ ((weak, alias("unused_isr"))); |
162 | void portc_isr(void) __attribute__ ((weak, alias("unused_isr"))); |
163 | void portd_isr(void) __attribute__ ((weak, alias("unused_isr"))); |
164 | void porte_isr(void) __attribute__ ((weak, alias("unused_isr"))); |
165 | void software_isr(void) __attribute__ ((weak, alias("unused_isr"))); |
166 | |
a773ac06 |
167 | #if defined(__MK20DX128__) |
168 | __attribute__ ((section(".dmabuffers"), used, aligned(256))) |
169 | #else |
170 | __attribute__ ((section(".dmabuffers"), used, aligned(512))) |
171 | #endif |
172 | void (* _VectorsRam[NVIC_NUM_INTERRUPTS+16])(void); |
35f00b6c |
173 | |
35f00b6c |
174 | __attribute__ ((section(".vectors"), used)) |
a773ac06 |
175 | void (* const _VectorsFlash[NVIC_NUM_INTERRUPTS+16])(void) = |
35f00b6c |
176 | { |
177 | (void (*)(void))((unsigned long)&_estack), // 0 ARM: Initial Stack Pointer |
178 | ResetHandler, // 1 ARM: Initial Program Counter |
179 | nmi_isr, // 2 ARM: Non-maskable Interrupt (NMI) |
180 | hard_fault_isr, // 3 ARM: Hard Fault |
181 | memmanage_fault_isr, // 4 ARM: MemManage Fault |
182 | bus_fault_isr, // 5 ARM: Bus Fault |
183 | usage_fault_isr, // 6 ARM: Usage Fault |
184 | fault_isr, // 7 -- |
185 | fault_isr, // 8 -- |
186 | fault_isr, // 9 -- |
187 | fault_isr, // 10 -- |
188 | svcall_isr, // 11 ARM: Supervisor call (SVCall) |
189 | debugmonitor_isr, // 12 ARM: Debug Monitor |
190 | fault_isr, // 13 -- |
191 | pendablesrvreq_isr, // 14 ARM: Pendable req serv(PendableSrvReq) |
192 | systick_isr, // 15 ARM: System tick timer (SysTick) |
193 | #if defined(__MK20DX128__) |
194 | dma_ch0_isr, // 16 DMA channel 0 transfer complete |
195 | dma_ch1_isr, // 17 DMA channel 1 transfer complete |
196 | dma_ch2_isr, // 18 DMA channel 2 transfer complete |
197 | dma_ch3_isr, // 19 DMA channel 3 transfer complete |
198 | dma_error_isr, // 20 DMA error interrupt channel |
199 | unused_isr, // 21 DMA -- |
200 | flash_cmd_isr, // 22 Flash Memory Command complete |
201 | flash_error_isr, // 23 Flash Read collision |
202 | low_voltage_isr, // 24 Low-voltage detect/warning |
203 | wakeup_isr, // 25 Low Leakage Wakeup |
204 | watchdog_isr, // 26 Both EWM and WDOG interrupt |
205 | i2c0_isr, // 27 I2C0 |
206 | spi0_isr, // 28 SPI0 |
207 | i2s0_tx_isr, // 29 I2S0 Transmit |
208 | i2s0_rx_isr, // 30 I2S0 Receive |
209 | uart0_lon_isr, // 31 UART0 CEA709.1-B (LON) status |
210 | uart0_status_isr, // 32 UART0 status |
211 | uart0_error_isr, // 33 UART0 error |
212 | uart1_status_isr, // 34 UART1 status |
213 | uart1_error_isr, // 35 UART1 error |
214 | uart2_status_isr, // 36 UART2 status |
215 | uart2_error_isr, // 37 UART2 error |
216 | adc0_isr, // 38 ADC0 |
217 | cmp0_isr, // 39 CMP0 |
218 | cmp1_isr, // 40 CMP1 |
219 | ftm0_isr, // 41 FTM0 |
220 | ftm1_isr, // 42 FTM1 |
221 | cmt_isr, // 43 CMT |
222 | rtc_alarm_isr, // 44 RTC Alarm interrupt |
223 | rtc_seconds_isr, // 45 RTC Seconds interrupt |
224 | pit0_isr, // 46 PIT Channel 0 |
225 | pit1_isr, // 47 PIT Channel 1 |
226 | pit2_isr, // 48 PIT Channel 2 |
227 | pit3_isr, // 49 PIT Channel 3 |
228 | pdb_isr, // 50 PDB Programmable Delay Block |
229 | usb_isr, // 51 USB OTG |
230 | usb_charge_isr, // 52 USB Charger Detect |
231 | tsi0_isr, // 53 TSI0 |
232 | mcg_isr, // 54 MCG |
233 | lptmr_isr, // 55 Low Power Timer |
234 | porta_isr, // 56 Pin detect (Port A) |
235 | portb_isr, // 57 Pin detect (Port B) |
236 | portc_isr, // 58 Pin detect (Port C) |
237 | portd_isr, // 59 Pin detect (Port D) |
238 | porte_isr, // 60 Pin detect (Port E) |
239 | software_isr, // 61 Software interrupt |
240 | #elif defined(__MK20DX256__) |
241 | dma_ch0_isr, // 16 DMA channel 0 transfer complete |
242 | dma_ch1_isr, // 17 DMA channel 1 transfer complete |
243 | dma_ch2_isr, // 18 DMA channel 2 transfer complete |
244 | dma_ch3_isr, // 19 DMA channel 3 transfer complete |
245 | dma_ch4_isr, // 20 DMA channel 4 transfer complete |
246 | dma_ch5_isr, // 21 DMA channel 5 transfer complete |
247 | dma_ch6_isr, // 22 DMA channel 6 transfer complete |
248 | dma_ch7_isr, // 23 DMA channel 7 transfer complete |
249 | dma_ch8_isr, // 24 DMA channel 8 transfer complete |
250 | dma_ch9_isr, // 25 DMA channel 9 transfer complete |
251 | dma_ch10_isr, // 26 DMA channel 10 transfer complete |
252 | dma_ch11_isr, // 27 DMA channel 10 transfer complete |
253 | dma_ch12_isr, // 28 DMA channel 10 transfer complete |
254 | dma_ch13_isr, // 29 DMA channel 10 transfer complete |
255 | dma_ch14_isr, // 30 DMA channel 10 transfer complete |
256 | dma_ch15_isr, // 31 DMA channel 10 transfer complete |
257 | dma_error_isr, // 32 DMA error interrupt channel |
258 | unused_isr, // 33 -- |
259 | flash_cmd_isr, // 34 Flash Memory Command complete |
260 | flash_error_isr, // 35 Flash Read collision |
261 | low_voltage_isr, // 36 Low-voltage detect/warning |
262 | wakeup_isr, // 37 Low Leakage Wakeup |
263 | watchdog_isr, // 38 Both EWM and WDOG interrupt |
264 | unused_isr, // 39 -- |
265 | i2c0_isr, // 40 I2C0 |
266 | i2c1_isr, // 41 I2C1 |
267 | spi0_isr, // 42 SPI0 |
268 | spi1_isr, // 43 SPI1 |
269 | unused_isr, // 44 -- |
270 | can0_message_isr, // 45 CAN OR'ed Message buffer (0-15) |
271 | can0_bus_off_isr, // 46 CAN Bus Off |
272 | can0_error_isr, // 47 CAN Error |
273 | can0_tx_warn_isr, // 48 CAN Transmit Warning |
274 | can0_rx_warn_isr, // 49 CAN Receive Warning |
275 | can0_wakeup_isr, // 50 CAN Wake Up |
276 | i2s0_tx_isr, // 51 I2S0 Transmit |
277 | i2s0_rx_isr, // 52 I2S0 Receive |
278 | unused_isr, // 53 -- |
279 | unused_isr, // 54 -- |
280 | unused_isr, // 55 -- |
281 | unused_isr, // 56 -- |
282 | unused_isr, // 57 -- |
283 | unused_isr, // 58 -- |
284 | unused_isr, // 59 -- |
285 | uart0_lon_isr, // 60 UART0 CEA709.1-B (LON) status |
286 | uart0_status_isr, // 61 UART0 status |
287 | uart0_error_isr, // 62 UART0 error |
288 | uart1_status_isr, // 63 UART1 status |
289 | uart1_error_isr, // 64 UART1 error |
290 | uart2_status_isr, // 65 UART2 status |
291 | uart2_error_isr, // 66 UART2 error |
292 | unused_isr, // 67 -- |
293 | unused_isr, // 68 -- |
294 | unused_isr, // 69 -- |
295 | unused_isr, // 70 -- |
296 | unused_isr, // 71 -- |
297 | unused_isr, // 72 -- |
298 | adc0_isr, // 73 ADC0 |
299 | adc1_isr, // 74 ADC1 |
300 | cmp0_isr, // 75 CMP0 |
301 | cmp1_isr, // 76 CMP1 |
302 | cmp2_isr, // 77 CMP2 |
303 | ftm0_isr, // 78 FTM0 |
304 | ftm1_isr, // 79 FTM1 |
305 | ftm2_isr, // 80 FTM2 |
306 | cmt_isr, // 81 CMT |
307 | rtc_alarm_isr, // 82 RTC Alarm interrupt |
308 | rtc_seconds_isr, // 83 RTC Seconds interrupt |
309 | pit0_isr, // 84 PIT Channel 0 |
310 | pit1_isr, // 85 PIT Channel 1 |
311 | pit2_isr, // 86 PIT Channel 2 |
312 | pit3_isr, // 87 PIT Channel 3 |
313 | pdb_isr, // 88 PDB Programmable Delay Block |
314 | usb_isr, // 89 USB OTG |
315 | usb_charge_isr, // 90 USB Charger Detect |
316 | unused_isr, // 91 -- |
317 | unused_isr, // 92 -- |
318 | unused_isr, // 93 -- |
319 | unused_isr, // 94 -- |
320 | unused_isr, // 95 -- |
321 | unused_isr, // 96 -- |
322 | dac0_isr, // 97 DAC0 |
323 | unused_isr, // 98 -- |
324 | tsi0_isr, // 99 TSI0 |
325 | mcg_isr, // 100 MCG |
326 | lptmr_isr, // 101 Low Power Timer |
327 | unused_isr, // 102 -- |
328 | porta_isr, // 103 Pin detect (Port A) |
329 | portb_isr, // 104 Pin detect (Port B) |
330 | portc_isr, // 105 Pin detect (Port C) |
331 | portd_isr, // 106 Pin detect (Port D) |
332 | porte_isr, // 107 Pin detect (Port E) |
333 | unused_isr, // 108 -- |
334 | unused_isr, // 109 -- |
335 | software_isr, // 110 Software interrupt |
336 | #endif |
337 | }; |
338 | |
339 | //void usb_isr(void) |
340 | //{ |
341 | //} |
342 | |
343 | __attribute__ ((section(".flashconfig"), used)) |
344 | const uint8_t flashconfigbytes[16] = { |
345 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, |
346 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF |
347 | }; |
348 | |
349 | |
350 | // Automatically initialize the RTC. When the build defines the compile |
351 | // time, and the user has added a crystal, the RTC will automatically |
352 | // begin at the time of the first upload. |
353 | #ifndef TIME_T |
354 | #define TIME_T 1349049600 // default 1 Oct 2012 (never used, Arduino sets this) |
355 | #endif |
356 | extern void rtc_set(unsigned long t); |
357 | |
358 | |
359 | static void startup_default_early_hook(void) { WDOG_STCTRLH = WDOG_STCTRLH_ALLOWUPDATE; } |
360 | static void startup_default_late_hook(void) {} |
361 | void startup_early_hook(void) __attribute__ ((weak, alias("startup_default_early_hook"))); |
362 | void startup_late_hook(void) __attribute__ ((weak, alias("startup_default_late_hook"))); |
363 | |
364 | __attribute__ ((section(".startup"))) |
365 | void ResetHandler(void) |
366 | { |
367 | uint32_t *src = &_etext; |
368 | uint32_t *dest = &_sdata; |
369 | unsigned int i; |
a773ac06 |
370 | #if F_CPU <= 2000000 |
371 | volatile int n; |
372 | #endif |
35f00b6c |
373 | |
374 | WDOG_UNLOCK = WDOG_UNLOCK_SEQ1; |
375 | WDOG_UNLOCK = WDOG_UNLOCK_SEQ2; |
a773ac06 |
376 | __asm__ volatile ("nop"); |
377 | __asm__ volatile ("nop"); |
35f00b6c |
378 | // programs using the watchdog timer or needing to initialize hardware as |
379 | // early as possible can implement startup_early_hook() |
380 | startup_early_hook(); |
381 | |
382 | // enable clocks to always-used peripherals |
383 | #if defined(__MK20DX128__) |
384 | SIM_SCGC5 = 0x00043F82; // clocks active to all GPIO |
385 | SIM_SCGC6 = SIM_SCGC6_RTC | SIM_SCGC6_FTM0 | SIM_SCGC6_FTM1 | SIM_SCGC6_ADC0 | SIM_SCGC6_FTFL; |
386 | #elif defined(__MK20DX256__) |
387 | SIM_SCGC3 = SIM_SCGC3_ADC1 | SIM_SCGC3_FTM2; |
388 | SIM_SCGC5 = 0x00043F82; // clocks active to all GPIO |
389 | SIM_SCGC6 = SIM_SCGC6_RTC | SIM_SCGC6_FTM0 | SIM_SCGC6_FTM1 | SIM_SCGC6_ADC0 | SIM_SCGC6_FTFL; |
390 | #endif |
35f00b6c |
391 | // if the RTC oscillator isn't enabled, get it started early |
392 | if (!(RTC_CR & RTC_CR_OSCE)) { |
393 | RTC_SR = 0; |
394 | RTC_CR = RTC_CR_SC16P | RTC_CR_SC4P | RTC_CR_OSCE; |
395 | } |
396 | |
397 | // release I/O pins hold, if we woke up from VLLS mode |
398 | if (PMC_REGSC & PMC_REGSC_ACKISO) PMC_REGSC |= PMC_REGSC_ACKISO; |
399 | |
a773ac06 |
400 | // since this is a write once register, make it visible to all F_CPU's |
401 | // so we can into other sleep modes in the future at any speed |
402 | SMC_PMPROT = SMC_PMPROT_AVLP | SMC_PMPROT_ALLS | SMC_PMPROT_AVLLS; |
403 | |
35f00b6c |
404 | // TODO: do this while the PLL is waiting to lock.... |
405 | while (dest < &_edata) *dest++ = *src++; |
406 | dest = &_sbss; |
407 | while (dest < &_ebss) *dest++ = 0; |
35f00b6c |
408 | |
409 | // default all interrupts to medium priority level |
a773ac06 |
410 | for (i=0; i < NVIC_NUM_INTERRUPTS + 16; i++) _VectorsRam[i] = _VectorsFlash[i]; |
35f00b6c |
411 | for (i=0; i < NVIC_NUM_INTERRUPTS; i++) NVIC_SET_PRIORITY(i, 128); |
a773ac06 |
412 | SCB_VTOR = (uint32_t)_VectorsRam; // use vector table in RAM |
413 | |
414 | // hardware always starts in FEI mode |
415 | // C1[CLKS] bits are written to 00 |
416 | // C1[IREFS] bit is written to 1 |
417 | // C6[PLLS] bit is written to 0 |
418 | // MCG_SC[FCDIV] defaults to divide by two for internal ref clock |
419 | // I tried changing MSG_SC to divide by 1, it didn't work for me |
420 | #if F_CPU <= 2000000 |
421 | // use the internal oscillator |
422 | MCG_C1 = MCG_C1_CLKS(1) | MCG_C1_IREFS; |
423 | // wait for MCGOUT to use oscillator |
424 | while ((MCG_S & MCG_S_CLKST_MASK) != MCG_S_CLKST(1)) ; |
425 | for (n=0; n<10; n++) ; // TODO: why do we get 2 mA extra without this delay? |
426 | MCG_C2 = MCG_C2_IRCS; |
427 | while (!(MCG_S & MCG_S_IRCST)) ; |
428 | // now in FBI mode: |
429 | // C1[CLKS] bits are written to 01 |
430 | // C1[IREFS] bit is written to 1 |
431 | // C6[PLLS] is written to 0 |
432 | // C2[LP] is written to 0 |
433 | MCG_C2 = MCG_C2_IRCS | MCG_C2_LP; |
434 | // now in BLPI mode: |
435 | // C1[CLKS] bits are written to 01 |
436 | // C1[IREFS] bit is written to 1 |
437 | // C6[PLLS] bit is written to 0 |
438 | // C2[LP] bit is written to 1 |
439 | #else |
35f00b6c |
440 | // enable capacitors for crystal |
441 | OSC0_CR = OSC_SC8P | OSC_SC2P; |
442 | // enable osc, 8-32 MHz range, low power mode |
443 | MCG_C2 = MCG_C2_RANGE0(2) | MCG_C2_EREFS; |
444 | // switch to crystal as clock source, FLL input = 16 MHz / 512 |
445 | MCG_C1 = MCG_C1_CLKS(2) | MCG_C1_FRDIV(4); |
446 | // wait for crystal oscillator to begin |
447 | while ((MCG_S & MCG_S_OSCINIT0) == 0) ; |
448 | // wait for FLL to use oscillator |
449 | while ((MCG_S & MCG_S_IREFST) != 0) ; |
450 | // wait for MCGOUT to use oscillator |
451 | while ((MCG_S & MCG_S_CLKST_MASK) != MCG_S_CLKST(2)) ; |
a773ac06 |
452 | // now in FBE mode |
453 | // C1[CLKS] bits are written to 10 |
454 | // C1[IREFS] bit is written to 0 |
455 | // C1[FRDIV] must be written to divide xtal to 31.25-39 kHz |
456 | // C6[PLLS] bit is written to 0 |
457 | // C2[LP] is written to 0 |
458 | #if F_CPU <= 16000000 |
459 | // if the crystal is fast enough, use it directly (no FLL or PLL) |
460 | MCG_C2 = MCG_C2_RANGE0(2) | MCG_C2_EREFS | MCG_C2_LP; |
461 | // BLPE mode: |
462 | // C1[CLKS] bits are written to 10 |
463 | // C1[IREFS] bit is written to 0 |
464 | // C2[LP] bit is written to 1 |
465 | #else |
466 | // if we need faster than the crystal, turn on the PLL |
467 | #if F_CPU == 72000000 |
468 | MCG_C5 = MCG_C5_PRDIV0(5); // config PLL input for 16 MHz Crystal / 6 = 2.667 Hz |
469 | #else |
470 | MCG_C5 = MCG_C5_PRDIV0(3); // config PLL input for 16 MHz Crystal / 4 = 4 MHz |
471 | #endif |
472 | #if F_CPU == 168000000 |
473 | MCG_C6 = MCG_C6_PLLS | MCG_C6_VDIV0(18); // config PLL for 168 MHz output |
474 | #elif F_CPU == 144000000 |
475 | MCG_C6 = MCG_C6_PLLS | MCG_C6_VDIV0(12); // config PLL for 144 MHz output |
476 | #elif F_CPU == 120000000 |
477 | MCG_C6 = MCG_C6_PLLS | MCG_C6_VDIV0(6); // config PLL for 120 MHz output |
478 | #elif F_CPU == 72000000 |
479 | MCG_C6 = MCG_C6_PLLS | MCG_C6_VDIV0(3); // config PLL for 72 MHz output |
480 | #else |
481 | MCG_C6 = MCG_C6_PLLS | MCG_C6_VDIV0(0); // config PLL for 96 MHz output |
482 | #endif |
35f00b6c |
483 | // wait for PLL to start using xtal as its input |
484 | while (!(MCG_S & MCG_S_PLLST)) ; |
485 | // wait for PLL to lock |
486 | while (!(MCG_S & MCG_S_LOCK0)) ; |
487 | // now we're in PBE mode |
a773ac06 |
488 | #endif |
489 | #endif |
490 | |
491 | // now program the clock dividers |
492 | #if F_CPU == 168000000 |
493 | // config divisors: 168 MHz core, 56 MHz bus, 33.6 MHz flash, USB = 168 * 2 / 7 |
494 | SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(0) | SIM_CLKDIV1_OUTDIV2(2) | SIM_CLKDIV1_OUTDIV4(4); |
495 | SIM_CLKDIV2 = SIM_CLKDIV2_USBDIV(6) | SIM_CLKDIV2_USBFRAC; |
496 | #elif F_CPU == 144000000 |
497 | // config divisors: 144 MHz core, 48 MHz bus, 28.8 MHz flash, USB = 144 / 3 |
498 | SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(0) | SIM_CLKDIV1_OUTDIV2(2) | SIM_CLKDIV1_OUTDIV4(4); |
499 | SIM_CLKDIV2 = SIM_CLKDIV2_USBDIV(2); |
500 | #elif F_CPU == 120000000 |
501 | // config divisors: 120 MHz core, 60 MHz bus, 24 MHz flash, USB = 128 * 2 / 5 |
502 | SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(0) | SIM_CLKDIV1_OUTDIV2(1) | SIM_CLKDIV1_OUTDIV4(4); |
503 | SIM_CLKDIV2 = SIM_CLKDIV2_USBDIV(4) | SIM_CLKDIV2_USBFRAC; |
504 | #elif F_CPU == 96000000 |
505 | // config divisors: 96 MHz core, 48 MHz bus, 24 MHz flash, USB = 96 / 2 |
35f00b6c |
506 | SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(0) | SIM_CLKDIV1_OUTDIV2(1) | SIM_CLKDIV1_OUTDIV4(3); |
a773ac06 |
507 | SIM_CLKDIV2 = SIM_CLKDIV2_USBDIV(1); |
508 | #elif F_CPU == 72000000 |
509 | // config divisors: 72 MHz core, 36 MHz bus, 24 MHz flash, USB = 72 * 2 / 3 |
510 | SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(0) | SIM_CLKDIV1_OUTDIV2(1) | SIM_CLKDIV1_OUTDIV4(2); |
511 | SIM_CLKDIV2 = SIM_CLKDIV2_USBDIV(2) | SIM_CLKDIV2_USBFRAC; |
35f00b6c |
512 | #elif F_CPU == 48000000 |
a773ac06 |
513 | // config divisors: 48 MHz core, 48 MHz bus, 24 MHz flash, USB = 96 / 2 |
35f00b6c |
514 | SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(1) | SIM_CLKDIV1_OUTDIV2(1) | SIM_CLKDIV1_OUTDIV4(3); |
a773ac06 |
515 | SIM_CLKDIV2 = SIM_CLKDIV2_USBDIV(1); |
35f00b6c |
516 | #elif F_CPU == 24000000 |
a773ac06 |
517 | // config divisors: 24 MHz core, 24 MHz bus, 24 MHz flash, USB = 96 / 2 |
518 | SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(3) | SIM_CLKDIV1_OUTDIV2(3) | SIM_CLKDIV1_OUTDIV4(3); |
519 | SIM_CLKDIV2 = SIM_CLKDIV2_USBDIV(1); |
520 | #elif F_CPU == 16000000 |
521 | // config divisors: 16 MHz core, 16 MHz bus, 16 MHz flash |
522 | SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(0) | SIM_CLKDIV1_OUTDIV2(0) | SIM_CLKDIV1_OUTDIV4(0); |
523 | #elif F_CPU == 8000000 |
524 | // config divisors: 8 MHz core, 8 MHz bus, 8 MHz flash |
525 | SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(1) | SIM_CLKDIV1_OUTDIV2(1) | SIM_CLKDIV1_OUTDIV4(1); |
526 | #elif F_CPU == 4000000 |
527 | // config divisors: 4 MHz core, 4 MHz bus, 2 MHz flash |
528 | // since we are running from external clock 16MHz |
529 | // fix outdiv too -> cpu 16/4, bus 16/4, flash 16/4 |
530 | // here we can go into vlpr? |
531 | // config divisors: 4 MHz core, 4 MHz bus, 4 MHz flash |
35f00b6c |
532 | SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(3) | SIM_CLKDIV1_OUTDIV2(3) | SIM_CLKDIV1_OUTDIV4(3); |
a773ac06 |
533 | #elif F_CPU == 2000000 |
534 | // since we are running from the fast internal reference clock 4MHz |
535 | // but is divided down by 2 so we actually have a 2MHz, MCG_SC[FCDIV] default is 2 |
536 | // fix outdiv -> cpu 2/1, bus 2/1, flash 2/2 |
537 | // config divisors: 2 MHz core, 2 MHz bus, 1 MHz flash |
538 | SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(0) | SIM_CLKDIV1_OUTDIV2(0) | SIM_CLKDIV1_OUTDIV4(1); |
35f00b6c |
539 | #else |
a773ac06 |
540 | #error "Error, F_CPU must be 168, 144, 120, 96, 72, 48, 24, 16, 8, 4, or 2 MHz" |
35f00b6c |
541 | #endif |
a773ac06 |
542 | |
543 | #if F_CPU > 16000000 |
35f00b6c |
544 | // switch to PLL as clock source, FLL input = 16 MHz / 512 |
545 | MCG_C1 = MCG_C1_CLKS(0) | MCG_C1_FRDIV(4); |
546 | // wait for PLL clock to be used |
547 | while ((MCG_S & MCG_S_CLKST_MASK) != MCG_S_CLKST(3)) ; |
548 | // now we're in PEE mode |
35f00b6c |
549 | // USB uses PLL clock, trace is CPU clock, CLKOUT=OSCERCLK0 |
550 | SIM_SOPT2 = SIM_SOPT2_USBSRC | SIM_SOPT2_PLLFLLSEL | SIM_SOPT2_TRACECLKSEL | SIM_SOPT2_CLKOUTSEL(6); |
a773ac06 |
551 | #else |
552 | SIM_SOPT2 = SIM_SOPT2_TRACECLKSEL | SIM_SOPT2_CLKOUTSEL(3); |
553 | #endif |
554 | |
555 | #if F_CPU <= 2000000 |
556 | // since we are not going into "stop mode" i removed it |
557 | SMC_PMCTRL = SMC_PMCTRL_RUNM(2); // VLPR mode :-) |
558 | #endif |
35f00b6c |
559 | |
560 | // initialize the SysTick counter |
561 | SYST_RVR = (F_CPU / 1000) - 1; |
562 | SYST_CSR = SYST_CSR_CLKSOURCE | SYST_CSR_TICKINT | SYST_CSR_ENABLE; |
563 | |
564 | //init_pins(); |
565 | __enable_irq(); |
566 | |
567 | _init_Teensyduino_internal_(); |
a773ac06 |
568 | if (RTC_SR & RTC_SR_TIF) { |
569 | // TODO: this should probably set the time more agressively, if |
570 | // we could reliably detect the first reboot after programming. |
571 | rtc_set(TIME_T); |
572 | } |
35f00b6c |
573 | |
574 | __libc_init_array(); |
575 | |
35f00b6c |
576 | startup_late_hook(); |
577 | main(); |
578 | while (1) ; |
579 | } |
580 | |
35f00b6c |
581 | char *__brkval = (char *)&_ebss; |
582 | |
583 | void * _sbrk(int incr) |
584 | { |
35f00b6c |
585 | char *prev = __brkval; |
586 | __brkval += incr; |
587 | return prev; |
588 | } |
589 | |
590 | __attribute__((weak)) |
591 | int _read(int file, char *ptr, int len) |
592 | { |
593 | return 0; |
594 | } |
595 | |
35f00b6c |
596 | __attribute__((weak)) |
597 | int _close(int fd) |
598 | { |
599 | return -1; |
600 | } |
601 | |
602 | #include <sys/stat.h> |
603 | |
604 | __attribute__((weak)) |
605 | int _fstat(int fd, struct stat *st) |
606 | { |
607 | st->st_mode = S_IFCHR; |
608 | return 0; |
609 | } |
610 | |
611 | __attribute__((weak)) |
612 | int _isatty(int fd) |
613 | { |
614 | return 1; |
615 | } |
616 | |
617 | __attribute__((weak)) |
618 | int _lseek(int fd, long long offset, int whence) |
619 | { |
620 | return -1; |
621 | } |
622 | |
623 | __attribute__((weak)) |
624 | void _exit(int status) |
625 | { |
626 | while (1); |
627 | } |
628 | |
629 | __attribute__((weak)) |
630 | void __cxa_pure_virtual() |
631 | { |
632 | while (1); |
633 | } |
634 | |
635 | __attribute__((weak)) |
636 | int __cxa_guard_acquire (char *g) |
637 | { |
638 | return !(*g); |
639 | } |
640 | |
641 | __attribute__((weak)) |
642 | void __cxa_guard_release(char *g) |
643 | { |
644 | *g = 1; |
645 | } |
646 | |
647 | int nvic_execution_priority(void) |
648 | { |
649 | int priority=256; |
650 | uint32_t primask, faultmask, basepri, ipsr; |
651 | |
652 | // full algorithm in ARM DDI0403D, page B1-639 |
653 | // this isn't quite complete, but hopefully good enough |
a773ac06 |
654 | __asm__ volatile("mrs %0, faultmask\n" : "=r" (faultmask)::); |
35f00b6c |
655 | if (faultmask) return -1; |
a773ac06 |
656 | __asm__ volatile("mrs %0, primask\n" : "=r" (primask)::); |
35f00b6c |
657 | if (primask) return 0; |
a773ac06 |
658 | __asm__ volatile("mrs %0, ipsr\n" : "=r" (ipsr)::); |
35f00b6c |
659 | if (ipsr) { |
660 | if (ipsr < 16) priority = 0; // could be non-zero |
661 | else priority = NVIC_GET_PRIORITY(ipsr - 16); |
662 | } |
a773ac06 |
663 | __asm__ volatile("mrs %0, basepri\n" : "=r" (basepri)::); |
35f00b6c |
664 | if (basepri > 0 && basepri < priority) priority = basepri; |
665 | return priority; |
666 | } |
667 | |