mbed library sources. Supersedes mbed-src.
Dependents: Nucleo_Hello_Encoder BLE_iBeaconScan AM1805_DEMO DISCO-F429ZI_ExportTemplate1 ... more
targets/TARGET_Freescale/TARGET_KLXX/TARGET_KL26Z/device/system_MKL26Z4.c
- Committer:
- AnnaBridge
- Date:
- 2019-02-20
- Revision:
- 189:f392fc9709a3
- Parent:
- 149:156823d33999
File content as of revision 189:f392fc9709a3:
/* ** ################################################################### ** Processors: MKL26Z128CAL4 ** MKL26Z128VFM4 ** MKL26Z64VFM4 ** MKL26Z32VM4 ** MKL26Z128VFT4 ** MKL26Z64VFT4 ** MKL26Z32VFT4 ** MKL26Z128VLH4 ** MKL26Z64VLH4 ** MKL26Z32VLH4 ** MKL26Z256VLH4 ** MKL26Z256VLL4 ** MKL26Z128VLL4 ** MKL26Z256VMC4 ** MKL26Z128VMC4 ** MKL26Z256VMP4 ** ** Compilers: Keil ARM C/C++ Compiler ** Freescale C/C++ for Embedded ARM ** GNU C Compiler ** GNU C Compiler - CodeSourcery Sourcery G++ ** IAR ANSI C/C++ Compiler for ARM ** ** Reference manuals: KL26P121M48SF4RM Rev. 3.2, October 2013 ** KL26P121M48SF4RM, Rev.2, Dec 2012 ** ** Version: rev. 1.7, 2015-01-13 ** Build: b150129 ** ** Abstract: ** Provides a system configuration function and a global variable that ** contains the system frequency. It configures the device and initializes ** the oscillator (PLL) that is part of the microcontroller device. ** ** Copyright (c) 2015 Freescale Semiconductor, Inc. ** All rights reserved. ** ** Redistribution and use in source and binary forms, with or without modification, ** are permitted provided that the following conditions are met: ** ** o Redistributions of source code must retain the above copyright notice, this list ** of conditions and the following disclaimer. ** ** o Redistributions in binary form must reproduce the above copyright notice, this ** list of conditions and the following disclaimer in the documentation and/or ** other materials provided with the distribution. ** ** o Neither the name of Freescale Semiconductor, Inc. nor the names of its ** contributors may be used to endorse or promote products derived from this ** software without specific prior written permission. ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ** DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ** ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ** ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ** ** http: www.freescale.com ** mail: support@freescale.com ** ** Revisions: ** - rev. 1.0 (2012-12-12) ** Initial version. ** - rev. 1.1 (2013-04-05) ** Changed start of doxygen comment. ** - rev. 1.2 (2013-04-12) ** SystemInit function fixed for clock configuration 1. ** Name of the interrupt num. 31 updated to reflect proper function. ** - rev. 1.3 (2014-05-27) ** Updated to Kinetis SDK support standard. ** MCG OSC clock select supported (MCG_C7[OSCSEL]). ** - rev. 1.4 (2014-07-25) ** System initialization updated: ** - Prefix added to the system initialization parameterization constants to avoid name conflicts.. ** - VLLSx wake-up recovery added. ** - Delay of 1 ms added to SystemInit() to ensure stable FLL output in FEI and FEE MCG modes. ** - rev. 1.5 (2014-08-28) ** Update of system files - default clock configuration changed, fix of OSC initialization. ** Update of startup files - possibility to override DefaultISR added. ** - rev. 1.6 (2014-10-14) ** Renamed interrupt vector LPTimer to LPTMR0 ** - rev. 1.7 (2015-01-13) ** Update of the copyright. ** ** ################################################################### */ /*! * @file MKL26Z4 * @version 1.7 * @date 2015-01-13 * @brief Device specific configuration file for MKL26Z4 (implementation file) * * Provides a system configuration function and a global variable that contains * the system frequency. It configures the device and initializes the oscillator * (PLL) that is part of the microcontroller device. */ #include <stdint.h> #include "MKL26Z4.h" /* ---------------------------------------------------------------------------- -- Core clock ---------------------------------------------------------------------------- */ uint32_t SystemCoreClock = DEFAULT_SYSTEM_CLOCK; /* ---------------------------------------------------------------------------- -- SystemInit() ---------------------------------------------------------------------------- */ void SystemInit (void) { #if (ACK_ISOLATION) if(PMC->REGSC & PMC_REGSC_ACKISO_MASK) { PMC->REGSC |= PMC_REGSC_ACKISO_MASK; /* VLLSx recovery */ } #endif /* Watchdog disable */ #if (DISABLE_WDOG) /* SIM_COPC: COPT=0,COPCLKS=0,COPW=0 */ SIM->COPC = (uint32_t)0x00u; #endif /* (DISABLE_WDOG) */ #ifdef CLOCK_SETUP /* RTC_CLKIN route */ #if (RTC_CLKIN_USED) /* SIM_SCGC5: PORTC=1 */ SIM->SCGC5 |= SIM_SCGC5_PORTC_MASK; /* PORTC_PCR1: ISF=0,MUX=1 */ PORTC->PCR[1] = (uint32_t)((PORTC->PCR[1] & (uint32_t)~(uint32_t)( PORT_PCR_ISF_MASK | PORT_PCR_MUX(0x06) )) | (uint32_t)( PORT_PCR_MUX(0x01) )); #endif /* (RTC_CLKIN_USED) */ /* Wake-up from VLLSx? */ if((RCM->SRS0 & RCM_SRS0_WAKEUP_MASK) != 0x00U) { /* VLLSx recovery */ if((PMC->REGSC & PMC_REGSC_ACKISO_MASK) != 0x00U) { PMC->REGSC |= PMC_REGSC_ACKISO_MASK; /* Release hold with ACKISO: Only has an effect if recovering from VLLSx.*/ } } /* Power mode protection initialization */ #ifdef SYSTEM_SMC_PMPROT_VALUE SMC->PMPROT = SYSTEM_SMC_PMPROT_VALUE; #endif /* System clock initialization */ /* Internal reference clock trim initialization */ #if defined(SLOW_TRIM_ADDRESS) if ( *((uint8_t*)SLOW_TRIM_ADDRESS) != 0xFFU) { /* Skip if non-volatile flash memory is erased */ MCG->C3 = *((uint8_t*)SLOW_TRIM_ADDRESS); #endif /* defined(SLOW_TRIM_ADDRESS) */ #if defined(SLOW_FINE_TRIM_ADDRESS) MCG->C4 = (MCG->C4 & ~(MCG_C4_SCFTRIM_MASK)) | ((*((uint8_t*) SLOW_FINE_TRIM_ADDRESS)) & MCG_C4_SCFTRIM_MASK); #endif #if defined(FAST_TRIM_ADDRESS) MCG->C4 = (MCG->C4 & ~(MCG_C4_FCTRIM_MASK)) |((*((uint8_t*) FAST_TRIM_ADDRESS)) & MCG_C4_FCTRIM_MASK); #endif #if defined(FAST_FINE_TRIM_ADDRESS) MCG->C2 = (MCG->C2 & ~(MCG_C2_FCFTRIM_MASK)) | ((*((uint8_t*)FAST_TRIM_ADDRESS)) & MCG_C2_FCFTRIM_MASK); #endif /* defined(FAST_FINE_TRIM_ADDRESS) */ #if defined(SLOW_TRIM_ADDRESS) } #endif /* defined(SLOW_TRIM_ADDRESS) */ /* Set system prescalers and clock sources */ SIM->CLKDIV1 = SYSTEM_SIM_CLKDIV1_VALUE; /* Set system prescalers */ SIM->SOPT1 = ((SIM->SOPT1) & (uint32_t)(~(SIM_SOPT1_OSC32KSEL_MASK))) | ((SYSTEM_SIM_SOPT1_VALUE) & (SIM_SOPT1_OSC32KSEL_MASK)); /* Set 32 kHz clock source (ERCLK32K) */ SIM->SOPT2 = ((SIM->SOPT2) & (uint32_t)(~( SIM_SOPT2_TPMSRC_MASK | SIM_SOPT2_UART0SRC_MASK | SIM_SOPT2_PLLFLLSEL_MASK | SIM_SOPT2_USBSRC_MASK ))) | ((SYSTEM_SIM_SOPT2_VALUE) & ( SIM_SOPT2_TPMSRC_MASK | SIM_SOPT2_UART0SRC_MASK | SIM_SOPT2_PLLFLLSEL_MASK | SIM_SOPT2_USBSRC_MASK )); /* Select TPM, LPUARTs, USB clock sources. */ #if ((MCG_MODE == MCG_MODE_FEI) || (MCG_MODE == MCG_MODE_FBI) || (MCG_MODE == MCG_MODE_BLPI)) /* Set MCG and OSC */ #if ((((SYSTEM_OSC0_CR_VALUE) & OSC_CR_ERCLKEN_MASK) != 0x00U) || (((SYSTEM_MCG_C5_VALUE) & MCG_C5_PLLCLKEN0_MASK) != 0x00U)) /* SIM_SCGC5: PORTA=1 */ SIM->SCGC5 |= SIM_SCGC5_PORTA_MASK; /* PORTA_PCR18: ISF=0,MUX=0 */ PORTA->PCR[18] &= (uint32_t)~(uint32_t)((PORT_PCR_ISF_MASK | PORT_PCR_MUX(0x07))); if (((SYSTEM_MCG_C2_VALUE) & MCG_C2_EREFS0_MASK) != 0x00U) { /* PORTA_PCR19: ISF=0,MUX=0 */ PORTA->PCR[19] &= (uint32_t)~(uint32_t)((PORT_PCR_ISF_MASK | PORT_PCR_MUX(0x07))); } #endif MCG->SC = SYSTEM_MCG_SC_VALUE; /* Set SC (fast clock internal reference divider) */ MCG->C1 = SYSTEM_MCG_C1_VALUE; /* Set C1 (clock source selection, FLL ext. reference divider, int. reference enable etc.) */ /* Check that the source of the FLL reference clock is the requested one. */ if (((SYSTEM_MCG_C1_VALUE) & MCG_C1_IREFS_MASK) != 0x00U) { while((MCG->S & MCG_S_IREFST_MASK) == 0x00U) { } } else { while((MCG->S & MCG_S_IREFST_MASK) != 0x00U) { } } MCG->C2 = (MCG->C2 & (uint8_t)(~(MCG_C2_FCFTRIM_MASK))) | (SYSTEM_MCG_C2_VALUE & (uint8_t)(~(MCG_C2_LP_MASK))); /* Set C2 (freq. range, ext. and int. reference selection etc. excluding trim bits; low power bit is set later) */ MCG->C4 = ((SYSTEM_MCG_C4_VALUE) & (uint8_t)(~(MCG_C4_FCTRIM_MASK | MCG_C4_SCFTRIM_MASK))) | (MCG->C4 & (MCG_C4_FCTRIM_MASK | MCG_C4_SCFTRIM_MASK)); /* Set C4 (FLL output; trim values not changed) */ OSC0->CR = SYSTEM_OSC0_CR_VALUE; /* Set OSC_CR (OSCERCLK enable, oscillator capacitor load) */ #else /* MCG_MODE */ /* Set MCG and OSC */ /* SIM_SCGC5: PORTA=1 */ SIM->SCGC5 |= SIM_SCGC5_PORTA_MASK; /* PORTA_PCR18: ISF=0,MUX=0 */ PORTA->PCR[18] &= (uint32_t)~(uint32_t)((PORT_PCR_ISF_MASK | PORT_PCR_MUX(0x07))); if (((SYSTEM_MCG_C2_VALUE) & MCG_C2_EREFS0_MASK) != 0x00U) { /* PORTA_PCR19: ISF=0,MUX=0 */ PORTA->PCR[19] &= (uint32_t)~(uint32_t)((PORT_PCR_ISF_MASK | PORT_PCR_MUX(0x07))); } MCG->SC = SYSTEM_MCG_SC_VALUE; /* Set SC (fast clock internal reference divider) */ MCG->C2 = (MCG->C2 & (uint8_t)(~(MCG_C2_FCFTRIM_MASK))) | (SYSTEM_MCG_C2_VALUE & (uint8_t)(~(MCG_C2_LP_MASK))); /* Set C2 (freq. range, ext. and int. reference selection etc. excluding trim bits; low power bit is set later) */ OSC0->CR = SYSTEM_OSC0_CR_VALUE; /* Set OSC_CR (OSCERCLK enable, oscillator capacitor load) */ #if (MCG_MODE == MCG_MODE_PEE) MCG->C1 = (SYSTEM_MCG_C1_VALUE) | MCG_C1_CLKS(0x02); /* Set C1 (clock source selection, FLL ext. reference divider, int. reference enable etc.) - PBE mode*/ #else MCG->C1 = SYSTEM_MCG_C1_VALUE; /* Set C1 (clock source selection, FLL ext. reference divider, int. reference enable etc.) */ #endif if (((SYSTEM_MCG_C2_VALUE) & MCG_C2_EREFS0_MASK) != 0x00U) { while((MCG->S & MCG_S_OSCINIT0_MASK) == 0x00U) { /* Check that the oscillator is running */ } } /* Check that the source of the FLL reference clock is the requested one. */ if (((SYSTEM_MCG_C1_VALUE) & MCG_C1_IREFS_MASK) != 0x00U) { while((MCG->S & MCG_S_IREFST_MASK) == 0x00U) { } } else { while((MCG->S & MCG_S_IREFST_MASK) != 0x00U) { } } MCG->C4 = ((SYSTEM_MCG_C4_VALUE) & (uint8_t)(~(MCG_C4_FCTRIM_MASK | MCG_C4_SCFTRIM_MASK))) | (MCG->C4 & (MCG_C4_FCTRIM_MASK | MCG_C4_SCFTRIM_MASK)); /* Set C4 (FLL output; trim values not changed) */ #endif /* MCG_MODE */ /* Common for all MCG modes */ /* PLL clock can be used to generate clock for some devices regardless of clock generator (MCGOUTCLK) mode. */ MCG->C5 = (SYSTEM_MCG_C5_VALUE) & (uint8_t)(~(MCG_C5_PLLCLKEN0_MASK)); /* Set C5 (PLL settings, PLL reference divider etc.) */ MCG->C6 = (SYSTEM_MCG_C6_VALUE) & (uint8_t)~(MCG_C6_PLLS_MASK); /* Set C6 (PLL select, VCO divider etc.) */ if ((SYSTEM_MCG_C5_VALUE) & MCG_C5_PLLCLKEN0_MASK) { MCG->C5 |= MCG_C5_PLLCLKEN0_MASK; /* PLL clock enable in mode other than PEE or PBE */ } /* BLPI and BLPE MCG mode specific */ #if ((MCG_MODE == MCG_MODE_BLPI) || (MCG_MODE == MCG_MODE_BLPE)) MCG->C2 |= (MCG_C2_LP_MASK); /* Disable FLL and PLL in bypass mode */ /* PEE and PBE MCG mode specific */ #elif ((MCG_MODE == MCG_MODE_PBE) || (MCG_MODE == MCG_MODE_PEE)) MCG->C6 |= (MCG_C6_PLLS_MASK); /* Set C6 (PLL select, VCO divider etc.) */ while((MCG->S & MCG_S_LOCK0_MASK) == 0x00U) { /* Wait until PLL is locked*/ } #if (MCG_MODE == MCG_MODE_PEE) MCG->C1 &= (uint8_t)~(MCG_C1_CLKS_MASK); #endif #endif /* Clock mode status check */ #if ((MCG_MODE == MCG_MODE_FEI) || (MCG_MODE == MCG_MODE_FEE)) while((MCG->S & MCG_S_CLKST_MASK) != 0x00U) { /* Wait until output of the FLL is selected */ } /* Use LPTMR to wait for 1ms for FLL clock stabilization */ SIM->SCGC5 |= SIM_SCGC5_LPTMR_MASK; /* Allow software control of LPMTR */ LPTMR0->CMR = LPTMR_CMR_COMPARE(0); /* Default 1 LPO tick */ LPTMR0->CSR = (LPTMR_CSR_TCF_MASK | LPTMR_CSR_TPS(0x00)); LPTMR0->PSR = (LPTMR_PSR_PCS(0x01) | LPTMR_PSR_PBYP_MASK); /* Clock source: LPO, Prescaler bypass enable */ LPTMR0->CSR = LPTMR_CSR_TEN_MASK; /* LPMTR enable */ while((LPTMR0->CSR & LPTMR_CSR_TCF_MASK) == 0u) { } LPTMR0->CSR = 0x00; /* Disable LPTMR */ SIM->SCGC5 &= (uint32_t)~(uint32_t)SIM_SCGC5_LPTMR_MASK; #elif ((MCG_MODE == MCG_MODE_FBI) || (MCG_MODE == MCG_MODE_BLPI)) while((MCG->S & MCG_S_CLKST_MASK) != 0x04U) { /* Wait until internal reference clock is selected as MCG output */ } #elif ((MCG_MODE == MCG_MODE_FBE) || (MCG_MODE == MCG_MODE_PBE) || (MCG_MODE == MCG_MODE_BLPE)) while((MCG->S & MCG_S_CLKST_MASK) != 0x08U) { /* Wait until external reference clock is selected as MCG output */ } #elif (MCG_MODE == MCG_MODE_PEE) while((MCG->S & MCG_S_CLKST_MASK) != 0x0CU) { /* Wait until output of the PLL is selected */ } #endif /* Very-low-power run mode enable */ #if (((SYSTEM_SMC_PMCTRL_VALUE) & SMC_PMCTRL_RUNM_MASK) == (0x02U << SMC_PMCTRL_RUNM_SHIFT)) SMC->PMCTRL = (uint8_t)((SYSTEM_SMC_PMCTRL_VALUE) & (SMC_PMCTRL_RUNM_MASK)); /* Enable VLPR mode */ while(SMC->PMSTAT != 0x04U) { /* Wait until the system is in VLPR mode */ } #endif /* PLL loss of lock interrupt request initialization */ if (((SYSTEM_MCG_C6_VALUE) & MCG_C6_LOLIE0_MASK) != 0U) { NVIC_EnableIRQ(MCG_IRQn); /* Enable PLL loss of lock interrupt request */ } #endif //#ifdef CLOCK_SETUP } /* ---------------------------------------------------------------------------- -- SystemCoreClockUpdate() ---------------------------------------------------------------------------- */ void SystemCoreClockUpdate (void) { uint32_t MCGOUTClock; /* Variable to store output clock frequency of the MCG module */ uint16_t Divider; if ((MCG->C1 & MCG_C1_CLKS_MASK) == 0x00U) { /* Output of FLL or PLL is selected */ if ((MCG->C6 & MCG_C6_PLLS_MASK) == 0x00U) { /* FLL is selected */ if ((MCG->C1 & MCG_C1_IREFS_MASK) == 0x00U) { /* External reference clock is selected */ MCGOUTClock = CPU_XTAL_CLK_HZ; /* System oscillator drives MCG clock */ if ((MCG->C2 & MCG_C2_RANGE0_MASK) != 0x00U) { switch (MCG->C1 & MCG_C1_FRDIV_MASK) { case 0x38U: Divider = 1536U; break; case 0x30U: Divider = 1280U; break; default: Divider = (uint16_t)(32LU << ((MCG->C1 & MCG_C1_FRDIV_MASK) >> MCG_C1_FRDIV_SHIFT)); break; } } else {/* ((MCG->C2 & MCG_C2_RANGE_MASK) != 0x00U) */ Divider = (uint16_t)(1LU << ((MCG->C1 & MCG_C1_FRDIV_MASK) >> MCG_C1_FRDIV_SHIFT)); } MCGOUTClock = (MCGOUTClock / Divider); /* Calculate the divided FLL reference clock */ } else { /* (!((MCG->C1 & MCG_C1_IREFS_MASK) == 0x00U)) */ MCGOUTClock = CPU_INT_SLOW_CLK_HZ; /* The slow internal reference clock is selected */ } /* (!((MCG->C1 & MCG_C1_IREFS_MASK) == 0x00U)) */ /* Select correct multiplier to calculate the MCG output clock */ switch (MCG->C4 & (MCG_C4_DMX32_MASK | MCG_C4_DRST_DRS_MASK)) { case 0x00U: MCGOUTClock *= 640U; break; case 0x20U: MCGOUTClock *= 1280U; break; case 0x40U: MCGOUTClock *= 1920U; break; case 0x60U: MCGOUTClock *= 2560U; break; case 0x80U: MCGOUTClock *= 732U; break; case 0xA0U: MCGOUTClock *= 1464U; break; case 0xC0U: MCGOUTClock *= 2197U; break; case 0xE0U: MCGOUTClock *= 2929U; break; default: break; } } else { /* (!((MCG->C6 & MCG_C6_PLLS_MASK) == 0x00U)) */ /* PLL is selected */ Divider = (((uint16_t)MCG->C5 & MCG_C5_PRDIV0_MASK) + 0x01U); MCGOUTClock = (uint32_t)(CPU_XTAL_CLK_HZ / Divider); /* Calculate the PLL reference clock */ Divider = (((uint16_t)MCG->C6 & MCG_C6_VDIV0_MASK) + 24U); MCGOUTClock *= Divider; /* Calculate the MCG output clock */ } /* (!((MCG->C6 & MCG_C6_PLLS_MASK) == 0x00U)) */ } else if ((MCG->C1 & MCG_C1_CLKS_MASK) == 0x40U) { /* Internal reference clock is selected */ if ((MCG->C2 & MCG_C2_IRCS_MASK) == 0x00U) { MCGOUTClock = CPU_INT_SLOW_CLK_HZ; /* Slow internal reference clock selected */ } else { /* (!((MCG->C2 & MCG_C2_IRCS_MASK) == 0x00U)) */ Divider = (uint16_t)(0x01LU << ((MCG->SC & MCG_SC_FCRDIV_MASK) >> MCG_SC_FCRDIV_SHIFT)); MCGOUTClock = (uint32_t) (CPU_INT_FAST_CLK_HZ / Divider); /* Fast internal reference clock selected */ } /* (!((MCG->C2 & MCG_C2_IRCS_MASK) == 0x00U)) */ } else if ((MCG->C1 & MCG_C1_CLKS_MASK) == 0x80U) { /* External reference clock is selected */ MCGOUTClock = CPU_XTAL_CLK_HZ; /* System oscillator drives MCG clock */ } else { /* (!((MCG->C1 & MCG_C1_CLKS_MASK) == 0x80U)) */ /* Reserved value */ return; } /* (!((MCG->C1 & MCG_C1_CLKS_MASK) == 0x80U)) */ SystemCoreClock = (MCGOUTClock / (0x01U + ((SIM->CLKDIV1 & SIM_CLKDIV1_OUTDIV1_MASK) >> SIM_CLKDIV1_OUTDIV1_SHIFT))); }