696 lines
19 KiB
C
696 lines
19 KiB
C
|
/*
|
||
|
* Copyright 2017-2019 NXP
|
||
|
* All rights reserved.
|
||
|
*
|
||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||
|
*/
|
||
|
|
||
|
#include "fsl_clock.h"
|
||
|
/*******************************************************************************
|
||
|
* Definitions
|
||
|
******************************************************************************/
|
||
|
/* Component ID definition, used by tools. */
|
||
|
#ifndef FSL_COMPONENT_ID
|
||
|
#define FSL_COMPONENT_ID "platform.drivers.clock"
|
||
|
#endif
|
||
|
#define SYSPLL_MIN_INPUT_FREQ_HZ (10000000U) /*!< Minimum PLL input rate */
|
||
|
#define SYSPLL_MAX_INPUT_FREQ_HZ (25000000U) /*!< Maximum PLL input rate */
|
||
|
#define SYSPLL_MAX_OUTPUT_FREQ_HZ (100000000U) /*!< Maximum PLL output rate */
|
||
|
#define SYSPLL_MIN_FCCO_FREQ_HZ (156000000U) /*!< Maximum FCCO output rate */
|
||
|
#define SYSPLL_MAX_FCCO_FREQ_HZ (320000000U) /*!< Maximum FCCO output rate */
|
||
|
#define SYSOSC_BOUNDARY_FREQ_HZ (15000000U) /*!< boundary frequency value */
|
||
|
|
||
|
/* External clock rate.
|
||
|
* Either external clk in rate or system oscillator frequency.
|
||
|
*/
|
||
|
volatile uint32_t g_Ext_Clk_Freq = 0U;
|
||
|
/** watch dog oscillator rate in Hz.*/
|
||
|
volatile uint32_t g_Wdt_Osc_Freq = 0U;
|
||
|
|
||
|
/*******************************************************************************
|
||
|
* Variables
|
||
|
******************************************************************************/
|
||
|
|
||
|
/*******************************************************************************
|
||
|
* Prototypes
|
||
|
******************************************************************************/
|
||
|
/*
|
||
|
* @brief select post divider for system pll according to the target frequency.
|
||
|
* @param outFreq: Value to be output
|
||
|
* @return post divider
|
||
|
*/
|
||
|
static uint32_t findSyestemPllPsel(uint32_t outFreq);
|
||
|
|
||
|
/*
|
||
|
* @brief Get FRG input clock frequency.
|
||
|
* @param fractional clock register base address.
|
||
|
* @return input clock frequency.
|
||
|
*/
|
||
|
static uint32_t CLOCK_GetFRGInputClkFreq(uint32_t *base);
|
||
|
|
||
|
/*
|
||
|
* @brief Update clock source.
|
||
|
* @param base clock register base address.
|
||
|
* @param mask clock source update enable bit mask value.
|
||
|
*/
|
||
|
static void CLOCK_UpdateClkSrc(volatile uint32_t *base, uint32_t mask);
|
||
|
|
||
|
/*******************************************************************************
|
||
|
* Code
|
||
|
******************************************************************************/
|
||
|
static uint32_t CLOCK_GetFRGInputClkFreq(uint32_t *base)
|
||
|
{
|
||
|
uint32_t sel = CLK_FRG_SEL_REG_MAP(base) & SYSCON_FRG_FRGCLKSEL_SEL_MASK;
|
||
|
|
||
|
if (sel == 0U)
|
||
|
{
|
||
|
return CLOCK_GetFroFreq();
|
||
|
}
|
||
|
else if (sel == 1U)
|
||
|
{
|
||
|
return CLOCK_GetMainClkFreq();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return CLOCK_GetSystemPLLFreq();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static bool CLOCK_SetFRGClkFreq(uint32_t *base, uint32_t freq)
|
||
|
{
|
||
|
assert(freq);
|
||
|
|
||
|
uint32_t input = CLOCK_GetFRGInputClkFreq(base);
|
||
|
uint32_t mul;
|
||
|
|
||
|
if ((freq > input) || (input / freq >= 2U))
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
mul = (uint32_t)(((uint64_t)((uint64_t)input - freq) << 8U) / ((uint64_t)freq));
|
||
|
|
||
|
CLK_FRG_DIV_REG_MAP(base) = SYSCON_FRG_FRGDIV_DIV_MASK;
|
||
|
CLK_FRG_MUL_REG_MAP(base) = SYSCON_FRG_FRGMULT_MULT(mul);
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
static void CLOCK_UpdateClkSrc(volatile uint32_t *base, uint32_t mask)
|
||
|
{
|
||
|
assert(base);
|
||
|
|
||
|
*base &= ~mask;
|
||
|
*base |= mask;
|
||
|
while ((*base & mask) == 0U)
|
||
|
{
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*! brief Set FRG0 output frequency.
|
||
|
* param freq, target output frequency,freq < input and (input / freq) < 2 should be satisfy.
|
||
|
* retval true - successfully, false - input argument is invalid.
|
||
|
*
|
||
|
*/
|
||
|
bool CLOCK_SetFRG0ClkFreq(uint32_t freq)
|
||
|
{
|
||
|
return CLOCK_SetFRGClkFreq(((uint32_t *)(uint32_t)(&SYSCON->FRG[0U])), freq);
|
||
|
}
|
||
|
|
||
|
/*! brief Set FRG1 output frequency.
|
||
|
* param freq, target output frequency,freq < input and (input / freq) < 2 should be satisfy.
|
||
|
* retval true - successfully, false - input argument is invalid.
|
||
|
*
|
||
|
*/
|
||
|
bool CLOCK_SetFRG1ClkFreq(uint32_t freq)
|
||
|
{
|
||
|
return CLOCK_SetFRGClkFreq(((uint32_t *)(uint32_t)(&SYSCON->FRG[1U])), freq);
|
||
|
}
|
||
|
|
||
|
/*! brief Return Frequency of FRG0 Clock.
|
||
|
* return Frequency of FRG0 Clock.
|
||
|
*/
|
||
|
uint32_t CLOCK_GetFRG0ClkFreq(void)
|
||
|
{
|
||
|
uint32_t temp;
|
||
|
|
||
|
temp = CLOCK_GetFRGInputClkFreq((uint32_t *)(uint32_t)(&SYSCON->FRG[0U])) << 8U;
|
||
|
return (uint32_t)((uint64_t)(temp) / (((uint64_t)SYSCON->FRG[0U].FRGMULT & SYSCON_FRG_FRGMULT_MULT_MASK) + 256ULL));
|
||
|
}
|
||
|
|
||
|
/*! brief Return Frequency of FRG1 Clock.
|
||
|
* return Frequency of FRG1 Clock.
|
||
|
*/
|
||
|
uint32_t CLOCK_GetFRG1ClkFreq(void)
|
||
|
{
|
||
|
uint32_t temp;
|
||
|
|
||
|
temp = (CLOCK_GetFRGInputClkFreq((uint32_t *)(uint32_t)(&SYSCON->FRG[1U])) << 8U);
|
||
|
return (uint32_t)(((uint64_t)temp) / (((uint64_t)SYSCON->FRG[1U].FRGMULT & SYSCON_FRG_FRGMULT_MULT_MASK) + 256ULL));
|
||
|
}
|
||
|
|
||
|
/*! brief Return Frequency of Main Clock.
|
||
|
* return Frequency of Main Clock.
|
||
|
*/
|
||
|
uint32_t CLOCK_GetMainClkFreq(void)
|
||
|
{
|
||
|
uint32_t freq = 0U;
|
||
|
|
||
|
if ((SYSCON->MAINCLKPLLSEL & SYSCON_MAINCLKPLLSEL_SEL_MASK) == 1U)
|
||
|
{
|
||
|
return CLOCK_GetSystemPLLFreq();
|
||
|
}
|
||
|
|
||
|
switch (SYSCON->MAINCLKSEL)
|
||
|
{
|
||
|
case 0U:
|
||
|
freq = CLOCK_GetFroFreq();
|
||
|
break;
|
||
|
|
||
|
case 1U:
|
||
|
freq = CLOCK_GetExtClkFreq();
|
||
|
break;
|
||
|
|
||
|
case 2U:
|
||
|
freq = CLOCK_GetWdtOscFreq();
|
||
|
break;
|
||
|
|
||
|
case 3U:
|
||
|
freq = CLOCK_GetFroFreq() >> 1U;
|
||
|
break;
|
||
|
default:
|
||
|
freq = 0U;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return freq;
|
||
|
}
|
||
|
|
||
|
/*! brief Return Frequency of FRO.
|
||
|
* return Frequency of FRO.
|
||
|
*/
|
||
|
uint32_t CLOCK_GetFroFreq(void)
|
||
|
{
|
||
|
uint32_t froOscSel = SYSCON->FROOSCCTRL & 3U;
|
||
|
uint32_t froOscFreq = 0U;
|
||
|
|
||
|
if (froOscSel == 0U)
|
||
|
{
|
||
|
froOscFreq = 18000000U;
|
||
|
}
|
||
|
else if (froOscSel == 1U)
|
||
|
{
|
||
|
froOscFreq = 24000000U;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
froOscFreq = 30000000U;
|
||
|
}
|
||
|
|
||
|
if (((SYSCON->FROOSCCTRL & SYSCON_FROOSCCTRL_FRO_DIRECT_MASK) >> SYSCON_FROOSCCTRL_FRO_DIRECT_SHIFT) == 0U)
|
||
|
{
|
||
|
/* need to check the FAIM low power boot value */
|
||
|
froOscFreq /= ((*((volatile uint32_t *)(CLOCK_FAIM_BASE)) & 0x2U) != 0UL) ? 16U : 2U;
|
||
|
}
|
||
|
|
||
|
return froOscFreq;
|
||
|
}
|
||
|
|
||
|
/*! brief Return Frequency of ClockOut
|
||
|
* return Frequency of ClockOut
|
||
|
*/
|
||
|
uint32_t CLOCK_GetClockOutClkFreq(void)
|
||
|
{
|
||
|
uint32_t divider = SYSCON->CLKOUTDIV & 0xffU, freq = 0U;
|
||
|
|
||
|
switch (SYSCON->CLKOUTSEL)
|
||
|
{
|
||
|
case 0U:
|
||
|
freq = CLOCK_GetFroFreq();
|
||
|
break;
|
||
|
|
||
|
case 1U:
|
||
|
freq = CLOCK_GetMainClkFreq();
|
||
|
break;
|
||
|
|
||
|
case 2U:
|
||
|
freq = CLOCK_GetSystemPLLFreq();
|
||
|
break;
|
||
|
|
||
|
case 3U:
|
||
|
freq = CLOCK_GetExtClkFreq();
|
||
|
break;
|
||
|
|
||
|
case 4U:
|
||
|
freq = CLOCK_GetWdtOscFreq();
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
freq = 0U;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return divider == 0U ? 0U : (freq / divider);
|
||
|
}
|
||
|
|
||
|
/*! brief Return Frequency of UART0
|
||
|
* return Frequency of UART0
|
||
|
*/
|
||
|
uint32_t CLOCK_GetUart0ClkFreq(void)
|
||
|
{
|
||
|
uint32_t freq = 0U;
|
||
|
|
||
|
switch (SYSCON->FCLKSEL[0])
|
||
|
{
|
||
|
case 0U:
|
||
|
freq = CLOCK_GetFroFreq();
|
||
|
break;
|
||
|
case 1U:
|
||
|
freq = CLOCK_GetMainClkFreq();
|
||
|
break;
|
||
|
case 2U:
|
||
|
freq = CLOCK_GetFRG0ClkFreq();
|
||
|
break;
|
||
|
case 3U:
|
||
|
freq = CLOCK_GetFRG1ClkFreq();
|
||
|
break;
|
||
|
case 4U:
|
||
|
freq = CLOCK_GetFroFreq() >> 1U;
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
freq = 0U;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return freq;
|
||
|
}
|
||
|
|
||
|
/*! brief Return Frequency of UART1
|
||
|
* return Frequency of UART1
|
||
|
*/
|
||
|
uint32_t CLOCK_GetUart1ClkFreq(void)
|
||
|
{
|
||
|
uint32_t freq = 0U;
|
||
|
|
||
|
switch (SYSCON->FCLKSEL[1])
|
||
|
{
|
||
|
case 0U:
|
||
|
freq = CLOCK_GetFroFreq();
|
||
|
break;
|
||
|
case 1U:
|
||
|
freq = CLOCK_GetMainClkFreq();
|
||
|
break;
|
||
|
case 2U:
|
||
|
freq = CLOCK_GetFRG0ClkFreq();
|
||
|
break;
|
||
|
case 3U:
|
||
|
freq = CLOCK_GetFRG1ClkFreq();
|
||
|
break;
|
||
|
case 4U:
|
||
|
freq = CLOCK_GetFroFreq() >> 1U;
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
freq = 0U;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return freq;
|
||
|
}
|
||
|
|
||
|
/*! brief Return Frequency of UART2
|
||
|
* return Frequency of UART2
|
||
|
*/
|
||
|
uint32_t CLOCK_GetUart2ClkFreq(void)
|
||
|
{
|
||
|
uint32_t freq = 0U;
|
||
|
|
||
|
switch (SYSCON->FCLKSEL[2])
|
||
|
{
|
||
|
case 0U:
|
||
|
freq = CLOCK_GetFroFreq();
|
||
|
break;
|
||
|
case 1U:
|
||
|
freq = CLOCK_GetMainClkFreq();
|
||
|
break;
|
||
|
case 2U:
|
||
|
freq = CLOCK_GetFRG0ClkFreq();
|
||
|
break;
|
||
|
case 3U:
|
||
|
freq = CLOCK_GetFRG1ClkFreq();
|
||
|
break;
|
||
|
case 4U:
|
||
|
freq = CLOCK_GetFroFreq() >> 1U;
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
freq = 0U;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return freq;
|
||
|
}
|
||
|
|
||
|
/*! brief Return Frequency of UART3
|
||
|
* return Frequency of UART3
|
||
|
*/
|
||
|
uint32_t CLOCK_GetUart3ClkFreq(void)
|
||
|
{
|
||
|
uint32_t freq = 0U;
|
||
|
|
||
|
switch (SYSCON->FCLKSEL[3])
|
||
|
{
|
||
|
case 0U:
|
||
|
freq = CLOCK_GetFroFreq();
|
||
|
break;
|
||
|
case 1U:
|
||
|
freq = CLOCK_GetMainClkFreq();
|
||
|
break;
|
||
|
case 2U:
|
||
|
freq = CLOCK_GetFRG0ClkFreq();
|
||
|
break;
|
||
|
case 3U:
|
||
|
freq = CLOCK_GetFRG1ClkFreq();
|
||
|
break;
|
||
|
case 4U:
|
||
|
freq = CLOCK_GetFroFreq() >> 1U;
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
freq = 0U;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return freq;
|
||
|
}
|
||
|
|
||
|
/*! brief Return Frequency of UART4
|
||
|
* return Frequency of UART4
|
||
|
*/
|
||
|
uint32_t CLOCK_GetUart4ClkFreq(void)
|
||
|
{
|
||
|
uint32_t freq = 0U;
|
||
|
|
||
|
switch (SYSCON->FCLKSEL[4])
|
||
|
{
|
||
|
case 0U:
|
||
|
freq = CLOCK_GetFroFreq();
|
||
|
break;
|
||
|
case 1U:
|
||
|
freq = CLOCK_GetMainClkFreq();
|
||
|
break;
|
||
|
case 2U:
|
||
|
freq = CLOCK_GetFRG0ClkFreq();
|
||
|
break;
|
||
|
case 3U:
|
||
|
freq = CLOCK_GetFRG1ClkFreq();
|
||
|
break;
|
||
|
case 4U:
|
||
|
freq = CLOCK_GetFroFreq() >> 1U;
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
freq = 0U;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return freq;
|
||
|
}
|
||
|
|
||
|
/*! brief Return Frequency of selected clock
|
||
|
* return Frequency of selected clock
|
||
|
*/
|
||
|
uint32_t CLOCK_GetFreq(clock_name_t clockName)
|
||
|
{
|
||
|
uint32_t freq;
|
||
|
|
||
|
switch (clockName)
|
||
|
{
|
||
|
case kCLOCK_CoreSysClk:
|
||
|
freq = CLOCK_GetCoreSysClkFreq();
|
||
|
break;
|
||
|
case kCLOCK_MainClk:
|
||
|
freq = CLOCK_GetMainClkFreq();
|
||
|
break;
|
||
|
case kCLOCK_Fro:
|
||
|
freq = CLOCK_GetFroFreq();
|
||
|
break;
|
||
|
case kCLOCK_FroDiv:
|
||
|
freq = CLOCK_GetFroFreq() >> 1U;
|
||
|
break;
|
||
|
case kCLOCK_ExtClk:
|
||
|
freq = CLOCK_GetExtClkFreq();
|
||
|
break;
|
||
|
case kCLOCK_WdtOsc:
|
||
|
freq = CLOCK_GetWdtOscFreq();
|
||
|
break;
|
||
|
case kCLOCK_PllOut:
|
||
|
freq = CLOCK_GetSystemPLLFreq();
|
||
|
break;
|
||
|
case kCLOCK_Frg0:
|
||
|
freq = CLOCK_GetFRG0ClkFreq();
|
||
|
break;
|
||
|
case kCLOCK_Frg1:
|
||
|
freq = CLOCK_GetFRG1ClkFreq();
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
freq = 0U;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return freq;
|
||
|
}
|
||
|
|
||
|
/*! brief Return System PLL input clock rate
|
||
|
* return System PLL input clock rate
|
||
|
*/
|
||
|
uint32_t CLOCK_GetSystemPLLInClockRate(void)
|
||
|
{
|
||
|
uint32_t freq = 0U;
|
||
|
|
||
|
switch ((SYSCON->SYSPLLCLKSEL))
|
||
|
{
|
||
|
/* source from fro div clock */
|
||
|
case 0x03U:
|
||
|
freq = CLOCK_GetFroFreq() >> 1U;
|
||
|
break;
|
||
|
/* source from the fro clock */
|
||
|
case 0x00U:
|
||
|
freq = CLOCK_GetFroFreq();
|
||
|
break;
|
||
|
/* source from external clock in */
|
||
|
case 0x01U:
|
||
|
freq = CLOCK_GetExtClkFreq();
|
||
|
break;
|
||
|
/* source from watchdog oscillator */
|
||
|
case 0x02U:
|
||
|
freq = CLOCK_GetWdtOscFreq();
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
freq = 0U;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return freq;
|
||
|
}
|
||
|
|
||
|
static uint32_t findSyestemPllPsel(uint32_t outFreq)
|
||
|
{
|
||
|
uint32_t pSel = 0U;
|
||
|
|
||
|
if (outFreq > (SYSPLL_MIN_FCCO_FREQ_HZ >> 1U))
|
||
|
{
|
||
|
pSel = 0U;
|
||
|
}
|
||
|
else if (outFreq > (SYSPLL_MIN_FCCO_FREQ_HZ >> 2U))
|
||
|
{
|
||
|
pSel = 1U;
|
||
|
}
|
||
|
else if (outFreq > (SYSPLL_MIN_FCCO_FREQ_HZ >> 3U))
|
||
|
{
|
||
|
pSel = 2U;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pSel = 3U;
|
||
|
}
|
||
|
|
||
|
return pSel;
|
||
|
}
|
||
|
|
||
|
/*! brief System PLL initialize.
|
||
|
* param config System PLL configurations.
|
||
|
*/
|
||
|
void CLOCK_InitSystemPll(const clock_sys_pll_t *config)
|
||
|
{
|
||
|
assert(config->targetFreq <= SYSPLL_MAX_OUTPUT_FREQ_HZ);
|
||
|
|
||
|
uint32_t mSel = 0U, pSel = 0U, inputFreq = 0U;
|
||
|
uint32_t syspllclkseltmp;
|
||
|
/* Power off PLL during setup changes */
|
||
|
SYSCON->PDRUNCFG |= SYSCON_PDRUNCFG_SYSPLL_PD_MASK;
|
||
|
|
||
|
/*set system pll clock source select register */
|
||
|
syspllclkseltmp = (SYSCON->SYSPLLCLKSEL & (~SYSCON_SYSPLLCLKSEL_SEL_MASK)) | (uint32_t)(config->src);
|
||
|
SYSCON->SYSPLLCLKSEL |= syspllclkseltmp;
|
||
|
/* system pll clock source update */
|
||
|
CLOCK_UpdateClkSrc((volatile uint32_t *)(&(SYSCON->SYSPLLCLKUEN)), SYSCON_SYSPLLCLKSEL_SEL_MASK);
|
||
|
|
||
|
inputFreq = CLOCK_GetSystemPLLInClockRate();
|
||
|
assert(inputFreq != 0U);
|
||
|
|
||
|
/* calucate the feedback divider value and post divider value*/
|
||
|
mSel = config->targetFreq / inputFreq;
|
||
|
pSel = findSyestemPllPsel(config->targetFreq);
|
||
|
|
||
|
/* configure PSEL and MSEL */
|
||
|
SYSCON->SYSPLLCTRL = (SYSCON->SYSPLLCTRL & (~(SYSCON_SYSPLLCTRL_MSEL_MASK | SYSCON_SYSPLLCTRL_PSEL_MASK))) |
|
||
|
SYSCON_SYSPLLCTRL_MSEL(mSel == 0U ? 0U : (mSel - 1U)) | SYSCON_SYSPLLCTRL_PSEL(pSel);
|
||
|
|
||
|
/* Power up PLL after setup changes */
|
||
|
SYSCON->PDRUNCFG &= ~SYSCON_PDRUNCFG_SYSPLL_PD_MASK;
|
||
|
|
||
|
/* wait pll lock */
|
||
|
while ((SYSCON->SYSPLLSTAT & SYSCON_SYSPLLSTAT_LOCK_MASK) == 0U)
|
||
|
{
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*! brief Init external CLK IN, select the CLKIN as the external clock source.
|
||
|
* param clkInFreq external clock in frequency.
|
||
|
*/
|
||
|
void CLOCK_InitExtClkin(uint32_t clkInFreq)
|
||
|
{
|
||
|
/* remove the pull up and pull down resistors in the IOCON */
|
||
|
IOCON->PIO[IOCON_INDEX_PIO0_1] &= ~IOCON_PIO_MODE_MASK;
|
||
|
/* enable the 1 bit functions for CLKIN */
|
||
|
SWM0->PINENABLE0 &= ~SWM_PINENABLE0_CLKIN_MASK;
|
||
|
/* enable the external clk in */
|
||
|
SYSCON->EXTCLKSEL |= SYSCON_EXTCLKSEL_SEL_MASK;
|
||
|
/* record the external clock rate */
|
||
|
g_Ext_Clk_Freq = clkInFreq;
|
||
|
}
|
||
|
|
||
|
/*! brief XTALIN init function
|
||
|
* system oscillator is bypassed, sys_osc_clk is fed driectly from the XTALIN.
|
||
|
* param xtalInFreq XTALIN frequency value
|
||
|
* return Frequency of PLL
|
||
|
*/
|
||
|
void CLOCK_InitXtalin(uint32_t xtalInFreq)
|
||
|
{
|
||
|
/* remove the pull up and pull down resistors in the IOCON */
|
||
|
IOCON->PIO[IOCON_INDEX_PIO0_8] &= ~IOCON_PIO_MODE_MASK;
|
||
|
/* enable the 1 bit functions for XTALIN and XTALOUT */
|
||
|
SWM0->PINENABLE0 &= ~SWM_PINENABLE0_XTALIN_MASK;
|
||
|
|
||
|
/* system osc configure */
|
||
|
SYSCON->SYSOSCCTRL |= SYSCON_SYSOSCCTRL_BYPASS_MASK;
|
||
|
/* external clock select */
|
||
|
SYSCON->EXTCLKSEL &= ~SYSCON_EXTCLKSEL_SEL_MASK;
|
||
|
/* enable system osc power first */
|
||
|
SYSCON->PDRUNCFG &= ~SYSCON_PDRUNCFG_SYSOSC_PD_MASK;
|
||
|
|
||
|
/* software delay 500USs */
|
||
|
SDK_DelayAtLeastUs(500U, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
|
||
|
|
||
|
/* record the external clock rate */
|
||
|
g_Ext_Clk_Freq = xtalInFreq;
|
||
|
}
|
||
|
|
||
|
/*! brief Init SYS OSC
|
||
|
* param oscFreq oscillator frequency value.
|
||
|
*/
|
||
|
void CLOCK_InitSysOsc(uint32_t oscFreq)
|
||
|
{
|
||
|
uint32_t sysoscctrltmp;
|
||
|
/* remove the pull up and pull down resistors in the IOCON */
|
||
|
IOCON->PIO[IOCON_INDEX_PIO0_9] &= ~IOCON_PIO_MODE_MASK;
|
||
|
IOCON->PIO[IOCON_INDEX_PIO0_8] &= ~IOCON_PIO_MODE_MASK;
|
||
|
/* enable the 1 bit functions for XTALIN and XTALOUT */
|
||
|
SWM0->PINENABLE0 &= ~(SWM_PINENABLE0_XTALIN_MASK | SWM_PINENABLE0_XTALOUT_MASK);
|
||
|
|
||
|
/* system osc configure */
|
||
|
sysoscctrltmp = (SYSCON->SYSOSCCTRL & (~(SYSCON_SYSOSCCTRL_BYPASS_MASK | SYSCON_SYSOSCCTRL_FREQRANGE_MASK))) |
|
||
|
(oscFreq > SYSOSC_BOUNDARY_FREQ_HZ ? SYSCON_SYSOSCCTRL_FREQRANGE_MASK : 0U);
|
||
|
SYSCON->SYSOSCCTRL |= sysoscctrltmp;
|
||
|
/* external clock select */
|
||
|
SYSCON->EXTCLKSEL &= ~SYSCON_EXTCLKSEL_SEL_MASK;
|
||
|
|
||
|
/* enable system osc power first */
|
||
|
SYSCON->PDRUNCFG &= ~SYSCON_PDRUNCFG_SYSOSC_PD_MASK;
|
||
|
|
||
|
/* software delay 500USs */
|
||
|
SDK_DelayAtLeastUs(500U, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
|
||
|
|
||
|
/* record the external clock rate */
|
||
|
g_Ext_Clk_Freq = oscFreq;
|
||
|
}
|
||
|
|
||
|
/*! brief Init watch dog OSC
|
||
|
* Any setting of the FREQSEL bits will yield a Fclkana value within 40% of the
|
||
|
* listed frequency value. The watchdog oscillator is the clock source with the lowest power
|
||
|
* consumption. If accurate timing is required, use the FRO or system oscillator.
|
||
|
* The frequency of the watchdog oscillator is undefined after reset. The watchdog
|
||
|
* oscillator frequency must be programmed by writing to the WDTOSCCTRL register before
|
||
|
* using the watchdog oscillator.
|
||
|
* Watchdog osc output frequency = wdtOscFreq / wdtOscDiv, should in range 9.3KHZ to 2.3MHZ.
|
||
|
* param wdtOscFreq watch dog analog part output frequency, reference _wdt_analog_output_freq.
|
||
|
* param wdtOscDiv watch dog analog part output frequency divider, shoule be a value >= 2U and multiple of 2
|
||
|
*/
|
||
|
void CLOCK_InitWdtOsc(clock_wdt_analog_freq_t wdtOscFreq, uint32_t wdtOscDiv)
|
||
|
{
|
||
|
assert(wdtOscDiv >= 2U);
|
||
|
|
||
|
uint32_t wdtOscCtrl = SYSCON->WDTOSCCTRL;
|
||
|
|
||
|
wdtOscCtrl &= ~(SYSCON_WDTOSCCTRL_DIVSEL_MASK | SYSCON_WDTOSCCTRL_FREQSEL_MASK);
|
||
|
|
||
|
wdtOscCtrl |= SYSCON_WDTOSCCTRL_DIVSEL((wdtOscDiv >> 1U) - 1U) |
|
||
|
SYSCON_WDTOSCCTRL_FREQSEL(CLK_WDT_OSC_GET_REG((uint32_t)wdtOscFreq));
|
||
|
|
||
|
SYSCON->WDTOSCCTRL = wdtOscCtrl;
|
||
|
|
||
|
/* power up watchdog oscillator */
|
||
|
SYSCON->PDRUNCFG &= ~SYSCON_PDRUNCFG_WDTOSC_PD_MASK;
|
||
|
/* update watch dog oscillator value */
|
||
|
g_Wdt_Osc_Freq = CLK_WDT_OSC_GET_FREQ(wdtOscFreq) / wdtOscDiv;
|
||
|
}
|
||
|
|
||
|
/*! brief Set main clock reference source.
|
||
|
* param src, reference clock_main_clk_src_t to set the main clock source.
|
||
|
*/
|
||
|
void CLOCK_SetMainClkSrc(clock_main_clk_src_t src)
|
||
|
{
|
||
|
uint32_t mainMux = CLK_MAIN_CLK_MUX_GET_MUX(src), mainPreMux = CLK_MAIN_CLK_MUX_GET_PRE_MUX(src);
|
||
|
|
||
|
if (((SYSCON->MAINCLKSEL & SYSCON_MAINCLKSEL_SEL_MASK) != mainPreMux) && (mainMux == 0U))
|
||
|
{
|
||
|
SYSCON->MAINCLKSEL = (SYSCON->MAINCLKSEL & (~SYSCON_MAINCLKSEL_SEL_MASK)) | SYSCON_MAINCLKSEL_SEL(mainPreMux);
|
||
|
CLOCK_UpdateClkSrc((volatile uint32_t *)(&(SYSCON->MAINCLKUEN)), SYSCON_MAINCLKUEN_ENA_MASK);
|
||
|
}
|
||
|
|
||
|
if ((SYSCON->MAINCLKPLLSEL & SYSCON_MAINCLKPLLSEL_SEL_MASK) != mainMux)
|
||
|
{
|
||
|
SYSCON->MAINCLKPLLSEL =
|
||
|
(SYSCON->MAINCLKPLLSEL & (~SYSCON_MAINCLKPLLSEL_SEL_MASK)) | SYSCON_MAINCLKPLLSEL_SEL(mainMux);
|
||
|
CLOCK_UpdateClkSrc((volatile uint32_t *)(&(SYSCON->MAINCLKPLLUEN)), SYSCON_MAINCLKPLLUEN_ENA_MASK);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*! brief Set FRO clock source
|
||
|
* param src, please reference _clock_fro_src definition.
|
||
|
*
|
||
|
*/
|
||
|
void CLOCK_SetFroOutClkSrc(clock_fro_src_t src)
|
||
|
{
|
||
|
if ((uint32_t)src != (SYSCON->FROOSCCTRL & SYSCON_FROOSCCTRL_FRO_DIRECT_MASK))
|
||
|
{
|
||
|
SYSCON->FROOSCCTRL = (SYSCON->FROOSCCTRL & (~SYSCON_FROOSCCTRL_FRO_DIRECT_MASK)) | (uint32_t)src;
|
||
|
/* Update clock source */
|
||
|
CLOCK_UpdateClkSrc((volatile uint32_t *)(&(SYSCON->FRODIRECTCLKUEN)), SYSCON_FRODIRECTCLKUEN_ENA_MASK);
|
||
|
}
|
||
|
}
|