| 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 | |
| 31 | #include "kinetis.h" |
| 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); |
| 43 | |
| 44 | |
| 45 | |
| 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 | |
| 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); |
| 173 | |
| 174 | __attribute__ ((section(".vectors"), used)) |
| 175 | void (* const _VectorsFlash[NVIC_NUM_INTERRUPTS+16])(void) = |
| 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; |
| 370 | #if F_CPU <= 2000000 |
| 371 | volatile int n; |
| 372 | #endif |
| 373 | |
| 374 | WDOG_UNLOCK = WDOG_UNLOCK_SEQ1; |
| 375 | WDOG_UNLOCK = WDOG_UNLOCK_SEQ2; |
| 376 | __asm__ volatile ("nop"); |
| 377 | __asm__ volatile ("nop"); |
| 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 |
| 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 | |
| 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 | |
| 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; |
| 408 | |
| 409 | // default all interrupts to medium priority level |
| 410 | for (i=0; i < NVIC_NUM_INTERRUPTS + 16; i++) _VectorsRam[i] = _VectorsFlash[i]; |
| 411 | for (i=0; i < NVIC_NUM_INTERRUPTS; i++) NVIC_SET_PRIORITY(i, 128); |
| 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 |
| 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)) ; |
| 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 |
| 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 |
| 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 |
| 506 | SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(0) | SIM_CLKDIV1_OUTDIV2(1) | SIM_CLKDIV1_OUTDIV4(3); |
| 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; |
| 512 | #elif F_CPU == 48000000 |
| 513 | // config divisors: 48 MHz core, 48 MHz bus, 24 MHz flash, USB = 96 / 2 |
| 514 | SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(1) | SIM_CLKDIV1_OUTDIV2(1) | SIM_CLKDIV1_OUTDIV4(3); |
| 515 | SIM_CLKDIV2 = SIM_CLKDIV2_USBDIV(1); |
| 516 | #elif F_CPU == 24000000 |
| 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 |
| 532 | SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(3) | SIM_CLKDIV1_OUTDIV2(3) | SIM_CLKDIV1_OUTDIV4(3); |
| 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); |
| 539 | #else |
| 540 | #error "Error, F_CPU must be 168, 144, 120, 96, 72, 48, 24, 16, 8, 4, or 2 MHz" |
| 541 | #endif |
| 542 | |
| 543 | #if F_CPU > 16000000 |
| 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 |
| 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); |
| 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 |
| 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_(); |
| 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 | } |
| 573 | |
| 574 | __libc_init_array(); |
| 575 | |
| 576 | startup_late_hook(); |
| 577 | main(); |
| 578 | while (1) ; |
| 579 | } |
| 580 | |
| 581 | char *__brkval = (char *)&_ebss; |
| 582 | |
| 583 | void * _sbrk(int incr) |
| 584 | { |
| 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 | |
| 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 |
| 654 | __asm__ volatile("mrs %0, faultmask\n" : "=r" (faultmask)::); |
| 655 | if (faultmask) return -1; |
| 656 | __asm__ volatile("mrs %0, primask\n" : "=r" (primask)::); |
| 657 | if (primask) return 0; |
| 658 | __asm__ volatile("mrs %0, ipsr\n" : "=r" (ipsr)::); |
| 659 | if (ipsr) { |
| 660 | if (ipsr < 16) priority = 0; // could be non-zero |
| 661 | else priority = NVIC_GET_PRIORITY(ipsr - 16); |
| 662 | } |
| 663 | __asm__ volatile("mrs %0, basepri\n" : "=r" (basepri)::); |
| 664 | if (basepri > 0 && basepri < priority) priority = basepri; |
| 665 | return priority; |
| 666 | } |
| 667 | |