X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=Lib%2Fmk20dx.c;h=ec6908c7ae0d043b7cc759027e1d81d81114851c;hb=20b62afb9a05a64b1f15c6329866600913775eea;hp=4913a759aa380a4dbf7052c492a242801324774f;hpb=8eba0ae3541c0d55ab0ee568dfab71a7042c0992;p=kiibohd-controller.git diff --git a/Lib/mk20dx.c b/Lib/mk20dx.c index 4913a75..ec6908c 100644 --- a/Lib/mk20dx.c +++ b/Lib/mk20dx.c @@ -1,7 +1,7 @@ /* Teensyduino Core Library * http://www.pjrc.com/teensy/ * Copyright (c) 2013 PJRC.COM, LLC. - * Modifications by Jacob Alexander 2014 + * Modifications by Jacob Alexander 2014-2015 * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the @@ -29,9 +29,18 @@ * SOFTWARE. */ +// ----- Includes ----- + +// Debug Includes +#if defined(_bootloader_) +#include +#include +#else +#include +#endif + // Local Includes #include "mk20dx.h" -#include @@ -45,6 +54,8 @@ extern unsigned long _sbss; extern unsigned long _ebss; extern unsigned long _estack; +const uint8_t sys_reset_to_loader_magic[22] = "\xff\x00\x7fRESET TO LOADER\x7f\x00\xff"; + // ----- Function Declarations ----- @@ -59,6 +70,7 @@ void ResetHandler(); // NVIC - Default ISR void fault_isr() { + print("Fault!" NL ); while ( 1 ) { // keep polling some communication while in fault @@ -84,12 +96,60 @@ void systick_default_isr() } +// NVIC - Non-Maskable Interrupt ISR +void nmi_default_isr() +{ + print("NMI!" NL ); +} + + +// NVIC - Hard Fault ISR +void hard_fault_default_isr() +{ + print("Hard Fault! SCB_HFSR: "); + printHex32( SCB_HFSR ); + print( NL ); + SOFTWARE_RESET(); +} + + +// NVIC - Memory Manager Fault ISR +void memmanage_fault_default_isr() +{ + print("Memory Manager Fault! SCB_CFSR: "); + printHex32( SCB_CFSR ); + print(" SCB_MMAR: "); + printHex32( SCB_MMAR ); + print( NL ); +} + + +// NVIC - Bus Fault ISR +void bus_fault_default_isr() +{ + print("Bus Fault! SCB_CFSR: "); + printHex32( SCB_CFSR ); + print(" SCB_BFAR: "); + printHex32( SCB_BFAR ); + print( NL ); +} + + +// NVIC - Usage Fault ISR +void usage_fault_default_isr() +{ + print("Usage Fault! SCB_CFSR: "); + printHex32( SCB_CFSR ); + print( NL ); +} + + // NVIC - Default ISR/Vector Linking -void nmi_isr() __attribute__ ((weak, alias("unused_isr"))); -void hard_fault_isr() __attribute__ ((weak, alias("unused_isr"))); -void memmanage_fault_isr() __attribute__ ((weak, alias("unused_isr"))); -void bus_fault_isr() __attribute__ ((weak, alias("unused_isr"))); -void usage_fault_isr() __attribute__ ((weak, alias("unused_isr"))); +void nmi_isr() __attribute__ ((weak, alias("nmi_default_isr"))); +void hard_fault_isr() __attribute__ ((weak, alias("hard_fault_default_isr"))); +void memmanage_fault_isr() __attribute__ ((weak, alias("memmanage_fault_default_isr"))); +void bus_fault_isr() __attribute__ ((weak, alias("bus_fault_default_isr"))); +void usage_fault_isr() __attribute__ ((weak, alias("usage_fault_default_isr"))); void svcall_isr() __attribute__ ((weak, alias("unused_isr"))); void debugmonitor_isr() __attribute__ ((weak, alias("unused_isr"))); void pendablesrvreq_isr() __attribute__ ((weak, alias("unused_isr"))); @@ -245,7 +305,7 @@ void (* const gVectors[])() = portd_isr, // 59 Pin detect (Port D) porte_isr, // 60 Pin detect (Port E) software_isr, // 61 Software interrupt -#elif defined(_mk20dx256_) +#elif defined(_mk20dx256_) || defined(_mk20dx256vlh7_) dma_ch0_isr, // 16 DMA channel 0 transfer complete dma_ch1_isr, // 17 DMA channel 1 transfer complete dma_ch2_isr, // 18 DMA channel 2 transfer complete @@ -354,29 +414,153 @@ const uint8_t flashconfigbytes[16] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF }; +#elif defined(_mk20dx128vlf5_) && defined(_bootloader_) +// XXX Byte labels may be in incorrect positions, double check before modifying +// FSEC is in correct location -Jacob +__attribute__ ((section(".flashconfig"), used)) +const uint8_t flashconfigbytes[16] = { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // Backdoor Verif Key 28.3.1 + + // + // Protecting the first 4k of Flash memory from being over-written while running (bootloader protection) + // Still possible to overwrite the bootloader using an external flashing device + // For more details see: + // http://cache.freescale.com/files/training/doc/dwf/AMF_ENT_T1031_Boston.pdf (page 8) + // http://cache.freescale.com/files/microcontrollers/doc/app_note/AN4507.pdf + // http://cache.freescale.com/files/32bit/doc/ref_manual/K20P48M50SF0RM.pdf (28.34.6) + // + 0xFF, 0xFF, 0xFF, 0xFE, // Program Flash Protection Bytes FPROT0-3 + + 0xBE, // Flash security byte FSEC + 0x03, // Flash nonvolatile option byte FOPT + 0xFF, // EEPROM Protection Byte FEPROT + 0xFF, // Data Flash Protection Byte FDPROT +}; +#elif defined(_mk20dx256vlh7_) && defined(_bootloader_) +// XXX Byte labels may be in incorrect positions, double check before modifying +// FSEC is in correct location -Jacob +__attribute__ ((section(".flashconfig"), used)) +const uint8_t flashconfigbytes[16] = { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // Backdoor Verif Key 28.3.1 + + // + // Protecting the first 8k of Flash memory from being over-written while running (bootloader protection) + // Still possible to overwrite the bootloader using an external flashing device + // For more details see: + // http://cache.freescale.com/files/training/doc/dwf/AMF_ENT_T1031_Boston.pdf (page 8) + // http://cache.freescale.com/files/microcontrollers/doc/app_note/AN4507.pdf + // http://cache.freescale.com/files/32bit/doc/ref_manual/K20P64M72SF1RM.pdf (28.34.6) + // + 0xFF, 0xFF, 0xFF, 0xFE, // Program Flash Protection Bytes FPROT0-3 + + 0xBE, // Flash security byte FSEC + 0x03, // Flash nonvolatile option byte FOPT + 0xFF, // EEPROM Protection Byte FEPROT + 0xFF, // Data Flash Protection Byte FDPROT +}; #endif +// ----- Functions ----- + +#if ( defined(_mk20dx128vlf5_) || defined(_mk20dx256vlh7_) ) && defined(_bootloader_) // Bootloader Section +__attribute__((noreturn)) +static inline void jump_to_app( uintptr_t addr ) +{ + // addr is in r0 + __asm__("ldr sp, [%[addr], #0]\n" + "ldr pc, [%[addr], #4]" + :: [addr] "r" (addr)); + // NOTREACHED + __builtin_unreachable(); +} +#endif + +void *memset( void *addr, int val, unsigned int len ) +{ + char *buf = addr; + + for (; len > 0; --len, ++buf) + *buf = val; + return (addr); +} + +int memcmp( const void *a, const void *b, unsigned int len ) +{ + const uint8_t *ap = a, *bp = b; + int val = 0; + + for (; len > 0 && (val = *ap - *bp) == 0; --len, ++ap, ++bp) + /* NOTHING */; + return (val); +} + +void *memcpy( void *dst, const void *src, unsigned int len ) +{ + char *dstbuf = dst; + const char *srcbuf = src; + + for (; len > 0; --len, ++dstbuf, ++srcbuf) + *dstbuf = *srcbuf; + return (dst); +} + + + // ----- Chip Entry Point ----- __attribute__ ((section(".startup"))) void ResetHandler() { - uint32_t *src = &_etext; - uint32_t *dest = &_sdata; - +#if ( defined(_mk20dx128vlf5_) || defined(_mk20dx256vlh7_) ) && defined(_bootloader_) // Bootloader Section + extern uint32_t _app_rom; + + // We treat _app_rom as pointer to directly read the stack + // pointer and check for valid app code. This is no fool + // proof method, but it should help for the first flash. + // + // Purposefully disabling the watchdog *after* the reset check this way + // if the chip goes into an odd state we'll reset to the bootloader (invalid firmware image) + // RCM_SRS0 & 0x20 + // + // Also checking for ARM lock-up signal (invalid firmware image) + // RCM_SRS1 & 0x02 + if ( // PIN (External Reset Pin/Switch) + RCM_SRS0 & 0x40 + // WDOG (Watchdog timeout) + || RCM_SRS0 & 0x20 + // LOCKUP (ARM Core LOCKUP event) + || RCM_SRS1 & 0x02 + // Blank flash check + || _app_rom == 0xffffffff + // Software reset + || memcmp( (uint8_t*)&VBAT, sys_reset_to_loader_magic, sizeof(sys_reset_to_loader_magic) ) == 0 + ) + { + memset( (uint8_t*)&VBAT, 0, sizeof(VBAT) ); + } + else + { + uint32_t addr = (uintptr_t)&_app_rom; + SCB_VTOR = addr; // relocate vector table + jump_to_app( addr ); + } +#endif // Disable Watchdog WDOG_UNLOCK = WDOG_UNLOCK_SEQ1; WDOG_UNLOCK = WDOG_UNLOCK_SEQ2; WDOG_STCTRLH = WDOG_STCTRLH_ALLOWUPDATE; + uint32_t *src = (uint32_t*)&_etext; + uint32_t *dest = (uint32_t*)&_sdata; + // Enable clocks to always-used peripherals SIM_SCGC5 = 0x00043F82; // Clocks active to all GPIO SIM_SCGC6 = SIM_SCGC6_FTM0 | SIM_SCGC6_FTM1 | SIM_SCGC6_ADC0 | SIM_SCGC6_FTFL; #if defined(_mk20dx128_) SIM_SCGC6 |= SIM_SCGC6_RTC; -#elif defined(_mk20dx256_) +#elif defined(_mk20dx256_) || defined(_mk20dx256vlh7_) SIM_SCGC3 = SIM_SCGC3_ADC1 | SIM_SCGC3_FTM2; SIM_SCGC6 |= SIM_SCGC6_RTC; #endif @@ -397,11 +581,11 @@ void ResetHandler() } // Prepare RAM - while ( dest < &_edata ) *dest++ = *src++; - dest = &_sbss; - while ( dest < &_ebss ) *dest++ = 0; + while ( dest < (uint32_t*)&_edata ) *dest++ = *src++; + dest = (uint32_t*)&_sbss; + while ( dest < (uint32_t*)&_ebss ) *dest++ = 0; -// MCHCK +// MCHCK / Kiibohd-dfu #if defined(_mk20dx128vlf5_) // Default all interrupts to medium priority level for ( unsigned int i = 0; i < NVIC_NUM_INTERRUPTS; i++ ) @@ -409,20 +593,21 @@ void ResetHandler() NVIC_SET_PRIORITY( i, 128 ); } - // FLL at 48MHz + // FLL at 48MHz MCG_C4 = MCG_C4_DMX32 | MCG_C4_DRST_DRS( 1 ); // USB Clock and FLL select SIM_SOPT2 = SIM_SOPT2_USBSRC | SIM_SOPT2_TRACECLKSEL; -// Teensy 3.0 and 3.1 +// Teensy 3.0 and 3.1 and Kiibohd-dfu (mk20dx256vlh7) #else - unsigned int i; - - SCB_VTOR = 0; // use vector table in flash +#if defined(_mk20dx128_) || defined(_mk20dx256_) + // use vector table in flash + SCB_VTOR = 0; +#endif // default all interrupts to medium priority level - for ( i = 0; i < NVIC_NUM_INTERRUPTS; i++ ) + for ( unsigned int i = 0; i < NVIC_NUM_INTERRUPTS; i++ ) { NVIC_SET_PRIORITY( i, 128 ); } @@ -447,11 +632,21 @@ void ResetHandler() while ( (MCG_S & MCG_S_CLKST_MASK) != MCG_S_CLKST( 2 ) ); // now we're in FBE mode +#if F_CPU == 72000000 + // config PLL input for 16 MHz Crystal / 8 = 2 MHz + MCG_C5 = MCG_C5_PRDIV0( 7 ); +#else // config PLL input for 16 MHz Crystal / 4 = 4 MHz MCG_C5 = MCG_C5_PRDIV0( 3 ); +#endif +#if F_CPU == 72000000 + // config PLL for 72 MHz output (36 * 2 MHz Ext PLL) + MCG_C6 = MCG_C6_PLLS | MCG_C6_VDIV0( 12 ); +#else // config PLL for 96 MHz output MCG_C6 = MCG_C6_PLLS | MCG_C6_VDIV0( 0 ); +#endif // wait for PLL to start using xtal as its input while ( !(MCG_S & MCG_S_PLLST) ); @@ -463,6 +658,9 @@ void ResetHandler() #if F_CPU == 96000000 // config divisors: 96 MHz core, 48 MHz bus, 24 MHz flash SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1( 0 ) | SIM_CLKDIV1_OUTDIV2( 1 ) | SIM_CLKDIV1_OUTDIV4( 3 ); +#elif F_CPU == 72000000 + // config divisors: 72 MHz core, 36 MHz bus, 24 MHz flash + SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1( 0 ) | SIM_CLKDIV1_OUTDIV2( 1 ) | SIM_CLKDIV1_OUTDIV4( 2 ); #elif F_CPU == 48000000 // config divisors: 48 MHz core, 48 MHz bus, 24 MHz flash SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1( 1 ) | SIM_CLKDIV1_OUTDIV2( 1 ) | SIM_CLKDIV1_OUTDIV4( 3 ); @@ -470,7 +668,7 @@ void ResetHandler() // config divisors: 24 MHz core, 24 MHz bus, 24 MHz flash SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1( 3 ) | SIM_CLKDIV1_OUTDIV2( 3 ) | SIM_CLKDIV1_OUTDIV4( 3 ); #else -#error "Error, F_CPU must be 96000000, 48000000, or 24000000" +#error "Error, F_CPU must be 96000000, 72000000, 48000000, or 24000000" #endif // switch to PLL as clock source, FLL input = 16 MHz / 512 MCG_C1 = MCG_C1_CLKS( 0 ) | MCG_C1_FRDIV( 4 ); @@ -479,18 +677,29 @@ void ResetHandler() while ( (MCG_S & MCG_S_CLKST_MASK) != MCG_S_CLKST( 3 ) ); // now we're in PEE mode +#if F_CPU == 72000000 + // configure USB for 48 MHz clock + SIM_CLKDIV2 = SIM_CLKDIV2_USBDIV( 2 ) | SIM_CLKDIV2_USBFRAC; // USB = 72 MHz PLL / 1.5 +#else // configure USB for 48 MHz clock SIM_CLKDIV2 = SIM_CLKDIV2_USBDIV( 1 ); // USB = 96 MHz PLL / 2 +#endif // USB uses PLL clock, trace is CPU clock, CLKOUT=OSCERCLK0 SIM_SOPT2 = SIM_SOPT2_USBSRC | SIM_SOPT2_PLLFLLSEL | SIM_SOPT2_TRACECLKSEL | SIM_SOPT2_CLKOUTSEL( 6 ); #endif + +#if !defined(_bootloader_) // Initialize the SysTick counter SYST_RVR = (F_CPU / 1000) - 1; SYST_CSR = SYST_CSR_CLKSOURCE | SYST_CSR_TICKINT | SYST_CSR_ENABLE; __enable_irq(); +#else + // Disable Watchdog for bootloader + WDOG_STCTRLH &= ~WDOG_STCTRLH_WDOGEN; +#endif main(); while ( 1 ); // Shouldn't get here...