]> git.donarmstrong.com Git - kiibohd-controller.git/blobdiff - Lib/mk20dx.c
Adding 72 MHz clock support for mk20dx256vlh7
[kiibohd-controller.git] / Lib / mk20dx.c
index 5217b01916888ac5ea21fdbb3b225a46effa60a0..1fa3e1510719b8a7c5740bc12ef08c8a8f129ab1 100644 (file)
@@ -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
  * SOFTWARE.
  */
 
+// ----- Includes -----
+
 // Local Includes
 #include "mk20dx.h"
-#include <print.h>
 
 
 
@@ -45,11 +46,13 @@ 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 -----
 
-extern int main ();
+extern int main();
 void ResetHandler();
 
 
@@ -245,7 +248,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,8 +357,98 @@ 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, 0xFF, // Program Flash Protection Bytes FPROT0-3 // XXX TODO PROTECT
+
+       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 -----
@@ -363,14 +456,48 @@ const uint8_t flashconfigbytes[16] = {
 __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;
@@ -397,11 +524,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 +536,18 @@ 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
+       SCB_VTOR = 0;   // use vector table in flash
 
        // 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 +572,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 +598,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 +608,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 +617,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...