]> git.donarmstrong.com Git - kiibohd-controller.git/blob - Lib/mk20dx.c
McHCK USB WORKS!!
[kiibohd-controller.git] / Lib / mk20dx.c
1 /* Teensyduino Core Library
2  * http://www.pjrc.com/teensy/
3  * Copyright (c) 2013 PJRC.COM, LLC.
4  * Modifications by Jacob Alexander 2014
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining
7  * a copy of this software and associated documentation files (the
8  * "Software"), to deal in the Software without restriction, including
9  * without limitation the rights to use, copy, modify, merge, publish,
10  * distribute, sublicense, and/or sell copies of the Software, and to
11  * permit persons to whom the Software is furnished to do so, subject to
12  * the following conditions:
13  *
14  * 1. The above copyright notice and this permission notice shall be
15  * included in all copies or substantial portions of the Software.
16  *
17  * 2. If the Software is incorporated into a build system that allows
18  * selection among a list of target devices, then similar target
19  * devices manufactured by PJRC.COM must be included in the list of
20  * target devices and selectable in the same manner.
21  *
22  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
26  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
27  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
28  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
29  * SOFTWARE.
30  */
31
32 // Local Includes
33 #include "mk20dx.h"
34 #include <print.h>
35
36
37
38 // ----- Variables -----
39
40 extern unsigned long _stext;
41 extern unsigned long _etext;
42 extern unsigned long _sdata;
43 extern unsigned long _edata;
44 extern unsigned long _sbss;
45 extern unsigned long _ebss;
46 extern unsigned long _estack;
47
48
49
50 // ----- Function Declarations -----
51
52 extern int main ();
53 void ResetHandler();
54
55
56
57 // ----- Interrupts -----
58
59 // NVIC - Default ISR
60 void fault_isr()
61 {
62         while ( 1 )
63         {
64                 // keep polling some communication while in fault
65                 // mode, so we don't completely die.
66                 if ( SIM_SCGC4 & SIM_SCGC4_USBOTG ) usb_isr();
67                 if ( SIM_SCGC4 & SIM_SCGC4_UART0 )  uart0_status_isr();
68                 if ( SIM_SCGC4 & SIM_SCGC4_UART1 )  uart1_status_isr();
69                 if ( SIM_SCGC4 & SIM_SCGC4_UART2 )  uart2_status_isr();
70         }
71 }
72
73 void unused_isr()
74 {
75         fault_isr();
76 }
77
78
79 // NVIC - SysTick ISR
80 extern volatile uint32_t systick_millis_count;
81 void systick_default_isr()
82 {
83         systick_millis_count++;
84 }
85
86
87 // NVIC - Default ISR/Vector Linking
88 void nmi_isr()              __attribute__ ((weak, alias("unused_isr")));
89 void hard_fault_isr()       __attribute__ ((weak, alias("unused_isr")));
90 void memmanage_fault_isr()  __attribute__ ((weak, alias("unused_isr")));
91 void bus_fault_isr()        __attribute__ ((weak, alias("unused_isr")));
92 void usage_fault_isr()      __attribute__ ((weak, alias("unused_isr")));
93 void svcall_isr()           __attribute__ ((weak, alias("unused_isr")));
94 void debugmonitor_isr()     __attribute__ ((weak, alias("unused_isr")));
95 void pendablesrvreq_isr()   __attribute__ ((weak, alias("unused_isr")));
96 void systick_isr()          __attribute__ ((weak, alias("systick_default_isr")));
97
98 void dma_ch0_isr()          __attribute__ ((weak, alias("unused_isr")));
99 void dma_ch1_isr()          __attribute__ ((weak, alias("unused_isr")));
100 void dma_ch2_isr()          __attribute__ ((weak, alias("unused_isr")));
101 void dma_ch3_isr()          __attribute__ ((weak, alias("unused_isr")));
102 void dma_ch4_isr()          __attribute__ ((weak, alias("unused_isr")));
103 void dma_ch5_isr()          __attribute__ ((weak, alias("unused_isr")));
104 void dma_ch6_isr()          __attribute__ ((weak, alias("unused_isr")));
105 void dma_ch7_isr()          __attribute__ ((weak, alias("unused_isr")));
106 void dma_ch8_isr()          __attribute__ ((weak, alias("unused_isr")));
107 void dma_ch9_isr()          __attribute__ ((weak, alias("unused_isr")));
108 void dma_ch10_isr()         __attribute__ ((weak, alias("unused_isr")));
109 void dma_ch11_isr()         __attribute__ ((weak, alias("unused_isr")));
110 void dma_ch12_isr()         __attribute__ ((weak, alias("unused_isr")));
111 void dma_ch13_isr()         __attribute__ ((weak, alias("unused_isr")));
112 void dma_ch14_isr()         __attribute__ ((weak, alias("unused_isr")));
113 void dma_ch15_isr()         __attribute__ ((weak, alias("unused_isr")));
114 void dma_error_isr()        __attribute__ ((weak, alias("unused_isr")));
115 void mcm_isr()              __attribute__ ((weak, alias("unused_isr")));
116 void flash_cmd_isr()        __attribute__ ((weak, alias("unused_isr")));
117 void flash_error_isr()      __attribute__ ((weak, alias("unused_isr")));
118 void low_voltage_isr()      __attribute__ ((weak, alias("unused_isr")));
119 void wakeup_isr()           __attribute__ ((weak, alias("unused_isr")));
120 void watchdog_isr()         __attribute__ ((weak, alias("unused_isr")));
121 void i2c0_isr()             __attribute__ ((weak, alias("unused_isr")));
122 void i2c1_isr()             __attribute__ ((weak, alias("unused_isr")));
123 void i2c2_isr()             __attribute__ ((weak, alias("unused_isr")));
124 void spi0_isr()             __attribute__ ((weak, alias("unused_isr")));
125 void spi1_isr()             __attribute__ ((weak, alias("unused_isr")));
126 void spi2_isr()             __attribute__ ((weak, alias("unused_isr")));
127 void sdhc_isr()             __attribute__ ((weak, alias("unused_isr")));
128 void can0_message_isr()     __attribute__ ((weak, alias("unused_isr")));
129 void can0_bus_off_isr()     __attribute__ ((weak, alias("unused_isr")));
130 void can0_error_isr()       __attribute__ ((weak, alias("unused_isr")));
131 void can0_tx_warn_isr()     __attribute__ ((weak, alias("unused_isr")));
132 void can0_rx_warn_isr()     __attribute__ ((weak, alias("unused_isr")));
133 void can0_wakeup_isr()      __attribute__ ((weak, alias("unused_isr")));
134 void i2s0_tx_isr()          __attribute__ ((weak, alias("unused_isr")));
135 void i2s0_rx_isr()          __attribute__ ((weak, alias("unused_isr")));
136 void uart0_lon_isr()        __attribute__ ((weak, alias("unused_isr")));
137 void uart0_status_isr()     __attribute__ ((weak, alias("unused_isr")));
138 void uart0_error_isr()      __attribute__ ((weak, alias("unused_isr")));
139 void uart1_status_isr()     __attribute__ ((weak, alias("unused_isr")));
140 void uart1_error_isr()      __attribute__ ((weak, alias("unused_isr")));
141 void uart2_status_isr()     __attribute__ ((weak, alias("unused_isr")));
142 void uart2_error_isr()      __attribute__ ((weak, alias("unused_isr")));
143 void uart3_status_isr()     __attribute__ ((weak, alias("unused_isr")));
144 void uart3_error_isr()      __attribute__ ((weak, alias("unused_isr")));
145 void uart4_status_isr()     __attribute__ ((weak, alias("unused_isr")));
146 void uart4_error_isr()      __attribute__ ((weak, alias("unused_isr")));
147 void uart5_status_isr()     __attribute__ ((weak, alias("unused_isr")));
148 void uart5_error_isr()      __attribute__ ((weak, alias("unused_isr")));
149 void adc0_isr()             __attribute__ ((weak, alias("unused_isr")));
150 void adc1_isr()             __attribute__ ((weak, alias("unused_isr")));
151 void cmp0_isr()             __attribute__ ((weak, alias("unused_isr")));
152 void cmp1_isr()             __attribute__ ((weak, alias("unused_isr")));
153 void cmp2_isr()             __attribute__ ((weak, alias("unused_isr")));
154 void ftm0_isr()             __attribute__ ((weak, alias("unused_isr")));
155 void ftm1_isr()             __attribute__ ((weak, alias("unused_isr")));
156 void ftm2_isr()             __attribute__ ((weak, alias("unused_isr")));
157 void ftm3_isr()             __attribute__ ((weak, alias("unused_isr")));
158 void cmt_isr()              __attribute__ ((weak, alias("unused_isr")));
159 void rtc_alarm_isr()        __attribute__ ((weak, alias("unused_isr")));
160 void rtc_seconds_isr()      __attribute__ ((weak, alias("unused_isr")));
161 void pit0_isr()             __attribute__ ((weak, alias("unused_isr")));
162 void pit1_isr()             __attribute__ ((weak, alias("unused_isr")));
163 void pit2_isr()             __attribute__ ((weak, alias("unused_isr")));
164 void pit3_isr()             __attribute__ ((weak, alias("unused_isr")));
165 void pdb_isr()              __attribute__ ((weak, alias("unused_isr")));
166 void usb_isr()              __attribute__ ((weak, alias("unused_isr")));
167 void usb_charge_isr()       __attribute__ ((weak, alias("unused_isr")));
168 void dac0_isr()             __attribute__ ((weak, alias("unused_isr")));
169 void dac1_isr()             __attribute__ ((weak, alias("unused_isr")));
170 void tsi0_isr()             __attribute__ ((weak, alias("unused_isr")));
171 void mcg_isr()              __attribute__ ((weak, alias("unused_isr")));
172 void lptmr_isr()            __attribute__ ((weak, alias("unused_isr")));
173 void porta_isr()            __attribute__ ((weak, alias("unused_isr")));
174 void portb_isr()            __attribute__ ((weak, alias("unused_isr")));
175 void portc_isr()            __attribute__ ((weak, alias("unused_isr")));
176 void portd_isr()            __attribute__ ((weak, alias("unused_isr")));
177 void porte_isr()            __attribute__ ((weak, alias("unused_isr")));
178 void software_isr()         __attribute__ ((weak, alias("unused_isr")));
179
180
181 // NVIC - Interrupt Vector Table
182 __attribute__ ((section(".vectors"), used))
183 void (* const gVectors[])() =
184 {
185         (void (*)(void))((unsigned long)&_estack),      //  0 ARM: Initial Stack Pointer
186         ResetHandler,                                   //  1 ARM: Initial Program Counter
187         nmi_isr,                                        //  2 ARM: Non-maskable Interrupt (NMI)
188         hard_fault_isr,                                 //  3 ARM: Hard Fault
189         memmanage_fault_isr,                            //  4 ARM: MemManage Fault
190         bus_fault_isr,                                  //  5 ARM: Bus Fault
191         usage_fault_isr,                                //  6 ARM: Usage Fault
192         fault_isr,                                      //  7 --
193         fault_isr,                                      //  8 --
194         fault_isr,                                      //  9 --
195         fault_isr,                                      // 10 --
196         svcall_isr,                                     // 11 ARM: Supervisor call (SVCall)
197         debugmonitor_isr,                               // 12 ARM: Debug Monitor
198         fault_isr,                                      // 13 --
199         pendablesrvreq_isr,                             // 14 ARM: Pendable req serv(PendableSrvReq)
200         systick_isr,                                    // 15 ARM: System tick timer (SysTick)
201 #if defined(_mk20dx128_) || defined(_mk20dx128vlf5_)
202         dma_ch0_isr,                                    // 16 DMA channel 0 transfer complete
203         dma_ch1_isr,                                    // 17 DMA channel 1 transfer complete
204         dma_ch2_isr,                                    // 18 DMA channel 2 transfer complete
205         dma_ch3_isr,                                    // 19 DMA channel 3 transfer complete
206         dma_error_isr,                                  // 20 DMA error interrupt channel
207         unused_isr,                                     // 21 DMA --
208         flash_cmd_isr,                                  // 22 Flash Memory Command complete
209         flash_error_isr,                                // 23 Flash Read collision
210         low_voltage_isr,                                // 24 Low-voltage detect/warning
211         wakeup_isr,                                     // 25 Low Leakage Wakeup
212         watchdog_isr,                                   // 26 Both EWM and WDOG interrupt
213         i2c0_isr,                                       // 27 I2C0
214         spi0_isr,                                       // 28 SPI0
215         i2s0_tx_isr,                                    // 29 I2S0 Transmit
216         i2s0_rx_isr,                                    // 30 I2S0 Receive
217         uart0_lon_isr,                                  // 31 UART0 CEA709.1-B (LON) status
218         uart0_status_isr,                               // 32 UART0 status
219         uart0_error_isr,                                // 33 UART0 error
220         uart1_status_isr,                               // 34 UART1 status
221         uart1_error_isr,                                // 35 UART1 error
222         uart2_status_isr,                               // 36 UART2 status
223         uart2_error_isr,                                // 37 UART2 error
224         adc0_isr,                                       // 38 ADC0
225         cmp0_isr,                                       // 39 CMP0
226         cmp1_isr,                                       // 40 CMP1
227         ftm0_isr,                                       // 41 FTM0
228         ftm1_isr,                                       // 42 FTM1
229         cmt_isr,                                        // 43 CMT
230         rtc_alarm_isr,                                  // 44 RTC Alarm interrupt
231         rtc_seconds_isr,                                // 45 RTC Seconds interrupt
232         pit0_isr,                                       // 46 PIT Channel 0
233         pit1_isr,                                       // 47 PIT Channel 1
234         pit2_isr,                                       // 48 PIT Channel 2
235         pit3_isr,                                       // 49 PIT Channel 3
236         pdb_isr,                                        // 50 PDB Programmable Delay Block
237         usb_isr,                                        // 51 USB OTG
238         usb_charge_isr,                                 // 52 USB Charger Detect
239         tsi0_isr,                                       // 53 TSI0
240         mcg_isr,                                        // 54 MCG
241         lptmr_isr,                                      // 55 Low Power Timer
242         porta_isr,                                      // 56 Pin detect (Port A)
243         portb_isr,                                      // 57 Pin detect (Port B)
244         portc_isr,                                      // 58 Pin detect (Port C)
245         portd_isr,                                      // 59 Pin detect (Port D)
246         porte_isr,                                      // 60 Pin detect (Port E)
247         software_isr,                                   // 61 Software interrupt
248 #elif defined(_mk20dx256_)
249         dma_ch0_isr,                                    // 16 DMA channel 0 transfer complete
250         dma_ch1_isr,                                    // 17 DMA channel 1 transfer complete
251         dma_ch2_isr,                                    // 18 DMA channel 2 transfer complete
252         dma_ch3_isr,                                    // 19 DMA channel 3 transfer complete
253         dma_ch4_isr,                                    // 20 DMA channel 4 transfer complete
254         dma_ch5_isr,                                    // 21 DMA channel 5 transfer complete
255         dma_ch6_isr,                                    // 22 DMA channel 6 transfer complete
256         dma_ch7_isr,                                    // 23 DMA channel 7 transfer complete
257         dma_ch8_isr,                                    // 24 DMA channel 8 transfer complete
258         dma_ch9_isr,                                    // 25 DMA channel 9 transfer complete
259         dma_ch10_isr,                                   // 26 DMA channel 10 transfer complete
260         dma_ch11_isr,                                   // 27 DMA channel 10 transfer complete
261         dma_ch12_isr,                                   // 28 DMA channel 10 transfer complete
262         dma_ch13_isr,                                   // 29 DMA channel 10 transfer complete
263         dma_ch14_isr,                                   // 30 DMA channel 10 transfer complete
264         dma_ch15_isr,                                   // 31 DMA channel 10 transfer complete
265         dma_error_isr,                                  // 32 DMA error interrupt channel
266         unused_isr,                                     // 33 --
267         flash_cmd_isr,                                  // 34 Flash Memory Command complete
268         flash_error_isr,                                // 35 Flash Read collision
269         low_voltage_isr,                                // 36 Low-voltage detect/warning
270         wakeup_isr,                                     // 37 Low Leakage Wakeup
271         watchdog_isr,                                   // 38 Both EWM and WDOG interrupt
272         unused_isr,                                     // 39 --
273         i2c0_isr,                                       // 40 I2C0
274         i2c1_isr,                                       // 41 I2C1
275         spi0_isr,                                       // 42 SPI0
276         spi1_isr,                                       // 43 SPI1
277         unused_isr,                                     // 44 --
278         can0_message_isr,                               // 45 CAN OR'ed Message buffer (0-15)
279         can0_bus_off_isr,                               // 46 CAN Bus Off
280         can0_error_isr,                                 // 47 CAN Error
281         can0_tx_warn_isr,                               // 48 CAN Transmit Warning
282         can0_rx_warn_isr,                               // 49 CAN Receive Warning
283         can0_wakeup_isr,                                // 50 CAN Wake Up
284         i2s0_tx_isr,                                    // 51 I2S0 Transmit
285         i2s0_rx_isr,                                    // 52 I2S0 Receive
286         unused_isr,                                     // 53 --
287         unused_isr,                                     // 54 --
288         unused_isr,                                     // 55 --
289         unused_isr,                                     // 56 --
290         unused_isr,                                     // 57 --
291         unused_isr,                                     // 58 --
292         unused_isr,                                     // 59 --
293         uart0_lon_isr,                                  // 60 UART0 CEA709.1-B (LON) status
294         uart0_status_isr,                               // 61 UART0 status
295         uart0_error_isr,                                // 62 UART0 error
296         uart1_status_isr,                               // 63 UART1 status
297         uart1_error_isr,                                // 64 UART1 error
298         uart2_status_isr,                               // 65 UART2 status
299         uart2_error_isr,                                // 66 UART2 error
300         unused_isr,                                     // 67 --
301         unused_isr,                                     // 68 --
302         unused_isr,                                     // 69 --
303         unused_isr,                                     // 70 --
304         unused_isr,                                     // 71 --
305         unused_isr,                                     // 72 --
306         adc0_isr,                                       // 73 ADC0
307         adc1_isr,                                       // 74 ADC1
308         cmp0_isr,                                       // 75 CMP0
309         cmp1_isr,                                       // 76 CMP1
310         cmp2_isr,                                       // 77 CMP2
311         ftm0_isr,                                       // 78 FTM0
312         ftm1_isr,                                       // 79 FTM1
313         ftm2_isr,                                       // 80 FTM2
314         cmt_isr,                                        // 81 CMT
315         rtc_alarm_isr,                                  // 82 RTC Alarm interrupt
316         rtc_seconds_isr,                                // 83 RTC Seconds interrupt
317         pit0_isr,                                       // 84 PIT Channel 0
318         pit1_isr,                                       // 85 PIT Channel 1
319         pit2_isr,                                       // 86 PIT Channel 2
320         pit3_isr,                                       // 87 PIT Channel 3
321         pdb_isr,                                        // 88 PDB Programmable Delay Block
322         usb_isr,                                        // 89 USB OTG
323         usb_charge_isr,                                 // 90 USB Charger Detect
324         unused_isr,                                     // 91 --
325         unused_isr,                                     // 92 --
326         unused_isr,                                     // 93 --
327         unused_isr,                                     // 94 --
328         unused_isr,                                     // 95 --
329         unused_isr,                                     // 96 --
330         dac0_isr,                                       // 97 DAC0
331         unused_isr,                                     // 98 --
332         tsi0_isr,                                       // 99 TSI0
333         mcg_isr,                                        // 100 MCG
334         lptmr_isr,                                      // 101 Low Power Timer
335         unused_isr,                                     // 102 --
336         porta_isr,                                      // 103 Pin detect (Port A)
337         portb_isr,                                      // 104 Pin detect (Port B)
338         portc_isr,                                      // 105 Pin detect (Port C)
339         portd_isr,                                      // 106 Pin detect (Port D)
340         porte_isr,                                      // 107 Pin detect (Port E)
341         unused_isr,                                     // 108 --
342         unused_isr,                                     // 109 --
343         software_isr,                                   // 110 Software interrupt
344 #endif
345 };
346
347
348 // ----- Flash Configuration -----
349
350 // Only necessary for Teensy 3s, MCHCK uses the Bootloader to handle this
351 #if defined(_mk20dx128_) || defined(_mk20dx256_)
352 __attribute__ ((section(".flashconfig"), used))
353 const uint8_t flashconfigbytes[16] = {
354         0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
355         0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF
356 };
357 #endif
358
359
360
361 // ----- Chip Entry Point -----
362
363 __attribute__ ((section(".startup")))
364 void ResetHandler()
365 {
366         uint32_t *src = &_etext;
367         uint32_t *dest = &_sdata;
368
369         // Disable Watchdog
370         WDOG_UNLOCK = WDOG_UNLOCK_SEQ1;
371         WDOG_UNLOCK = WDOG_UNLOCK_SEQ2;
372         WDOG_STCTRLH = WDOG_STCTRLH_ALLOWUPDATE;
373
374         // Enable clocks to always-used peripherals
375         SIM_SCGC5 = 0x00043F82; // Clocks active to all GPIO
376         SIM_SCGC6 = SIM_SCGC6_FTM0 | SIM_SCGC6_FTM1 | SIM_SCGC6_ADC0 | SIM_SCGC6_FTFL;
377 #if defined(_mk20dx128_)
378         SIM_SCGC6 |= SIM_SCGC6_RTC;
379 #elif defined(_mk20dx256_)
380         SIM_SCGC3 = SIM_SCGC3_ADC1 | SIM_SCGC3_FTM2;
381         SIM_SCGC6 |= SIM_SCGC6_RTC;
382 #endif
383
384 #if defined(_mk20dx128_) || defined(_mk20dx256_) // Teensy 3s
385         // if the RTC oscillator isn't enabled, get it started early
386         if ( !(RTC_CR & RTC_CR_OSCE) )
387         {
388                 RTC_SR = 0;
389                 RTC_CR = RTC_CR_SC16P | RTC_CR_SC4P | RTC_CR_OSCE;
390         }
391 #endif
392
393         // release I/O pins hold, if we woke up from VLLS mode
394         if ( PMC_REGSC & PMC_REGSC_ACKISO )
395         {
396                 PMC_REGSC |= PMC_REGSC_ACKISO;
397         }
398
399         // Prepare RAM
400         while ( dest < &_edata ) *dest++ = *src++;
401         dest = &_sbss;
402         while ( dest < &_ebss ) *dest++ = 0;
403
404 // MCHCK
405 #if defined(_mk20dx128vlf5_)
406         // Default all interrupts to medium priority level
407         for ( unsigned int i = 0; i < NVIC_NUM_INTERRUPTS; i++ )
408         {
409                 NVIC_SET_PRIORITY( i, 128 );
410         }
411
412         // FLL at 48MHz
413         MCG_C4 = MCG_C4_DMX32 | MCG_C4_DRST_DRS( 1 );
414
415         // USB Clock and FLL select
416         SIM_SOPT2 = SIM_SOPT2_USBSRC | SIM_SOPT2_TRACECLKSEL;
417
418 // Teensy 3.0 and 3.1
419 #else
420         unsigned int i;
421
422         SCB_VTOR = 0;   // use vector table in flash
423
424         // default all interrupts to medium priority level
425         for ( i = 0; i < NVIC_NUM_INTERRUPTS; i++ )
426         {
427                 NVIC_SET_PRIORITY( i, 128 );
428         }
429
430         // start in FEI mode
431         // enable capacitors for crystal
432         OSC0_CR = OSC_SC8P | OSC_SC2P;
433
434         // enable osc, 8-32 MHz range, low power mode
435         MCG_C2 = MCG_C2_RANGE0( 2 ) | MCG_C2_EREFS;
436
437         // switch to crystal as clock source, FLL input = 16 MHz / 512
438         MCG_C1 =  MCG_C1_CLKS( 2 ) | MCG_C1_FRDIV( 4 );
439
440         // wait for crystal oscillator to begin
441         while ( (MCG_S & MCG_S_OSCINIT0) == 0 );
442
443         // wait for FLL to use oscillator
444         while ( (MCG_S & MCG_S_IREFST) != 0 );
445
446         // wait for MCGOUT to use oscillator
447         while ( (MCG_S & MCG_S_CLKST_MASK) != MCG_S_CLKST( 2 ) );
448
449         // now we're in FBE mode
450         // config PLL input for 16 MHz Crystal / 4 = 4 MHz
451         MCG_C5 = MCG_C5_PRDIV0( 3 );
452
453         // config PLL for 96 MHz output
454         MCG_C6 = MCG_C6_PLLS | MCG_C6_VDIV0( 0 );
455
456         // wait for PLL to start using xtal as its input
457         while ( !(MCG_S & MCG_S_PLLST) );
458
459         // wait for PLL to lock
460         while ( !(MCG_S & MCG_S_LOCK0) );
461
462         // now we're in PBE mode
463 #if F_CPU == 96000000
464         // config divisors: 96 MHz core, 48 MHz bus, 24 MHz flash
465         SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1( 0 ) | SIM_CLKDIV1_OUTDIV2( 1 ) | SIM_CLKDIV1_OUTDIV4( 3 );
466 #elif F_CPU == 48000000
467         // config divisors: 48 MHz core, 48 MHz bus, 24 MHz flash
468         SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1( 1 ) | SIM_CLKDIV1_OUTDIV2( 1 ) | SIM_CLKDIV1_OUTDIV4( 3 );
469 #elif F_CPU == 24000000
470         // config divisors: 24 MHz core, 24 MHz bus, 24 MHz flash
471         SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1( 3 ) | SIM_CLKDIV1_OUTDIV2( 3 ) | SIM_CLKDIV1_OUTDIV4( 3 );
472 #else
473 #error "Error, F_CPU must be 96000000, 48000000, or 24000000"
474 #endif
475         // switch to PLL as clock source, FLL input = 16 MHz / 512
476         MCG_C1 = MCG_C1_CLKS( 0 ) | MCG_C1_FRDIV( 4 );
477
478         // wait for PLL clock to be used
479         while ( (MCG_S & MCG_S_CLKST_MASK) != MCG_S_CLKST( 3 ) );
480
481         // now we're in PEE mode
482         // configure USB for 48 MHz clock
483         SIM_CLKDIV2 = SIM_CLKDIV2_USBDIV( 1 ); // USB = 96 MHz PLL / 2
484
485         // USB uses PLL clock, trace is CPU clock, CLKOUT=OSCERCLK0
486         SIM_SOPT2 = SIM_SOPT2_USBSRC | SIM_SOPT2_PLLFLLSEL | SIM_SOPT2_TRACECLKSEL | SIM_SOPT2_CLKOUTSEL( 6 );
487
488 #endif
489         // Initialize the SysTick counter
490         SYST_RVR = (F_CPU / 1000) - 1;
491         SYST_CSR = SYST_CSR_CLKSOURCE | SYST_CSR_TICKINT | SYST_CSR_ENABLE;
492
493         __enable_irq();
494
495         main();
496         while ( 1 ); // Shouldn't get here...
497 }
498
499
500
501 // ----- RAM Setup -----
502
503 char *__brkval = (char *)&_ebss;
504
505 void * _sbrk( int incr )
506 {
507         char *prev = __brkval;
508         __brkval += incr;
509         return prev;
510 }
511
512
513
514 // ----- Interrupt Execution Priority -----
515
516 int nvic_execution_priority()
517 {
518         int priority = 256;
519         uint32_t primask, faultmask, basepri, ipsr;
520
521         // full algorithm in ARM DDI0403D, page B1-639
522         // this isn't quite complete, but hopefully good enough
523         asm volatile( "mrs %0, faultmask\n" : "=r" (faultmask):: );
524         if ( faultmask )
525         {
526                 return -1;
527         }
528
529         asm volatile( "mrs %0, primask\n" : "=r" (primask):: );
530         if ( primask )
531         {
532                 return 0;
533         }
534
535         asm volatile( "mrs %0, ipsr\n" : "=r" (ipsr):: );
536         if ( ipsr )
537         {
538                 if ( ipsr < 16)
539                 {
540                         priority = 0; // could be non-zero
541                 }
542                 else
543                 {
544                         priority = NVIC_GET_PRIORITY( ipsr - 16 );
545                 }
546         }
547
548         asm volatile( "mrs %0, basepri\n" : "=r" (basepri):: );
549         if ( basepri > 0 && basepri < priority )
550         {
551                 priority = basepri;
552         }
553
554         return priority;
555 }
556