/*
*********************************************************************************************************
* BSP_PLL_Init()
*
* Description : Set up and activate the PLL.
*
* Argument(s) : none.
*
* Return(s) : none.
*
* Caller(s) : BSP_Init()
*
* Note(s) : (1) The PLL output frequency is calculated by:
*
* Fcco = 2 * Fin * m / n
*
* where
*
* Fin is the PLL input clock (here, the main oscillator)
* M is the PLL clock multiplier. The value (M - 1) is programmed in PLLCFG.
* N is the PLL clock divider. The value (N - 1) is programmed in PLLCFG.
*
* (2) Fcco must be between 275 and 550 MHz. The ARM Core clock must never exceed 72 MHz.
* Set clk_div to divide Fcco accordingly.
*
* (3) When using the USB device, you must choose Fcco as a multiple of 96 MHz, and then
* set clk_div_usb to divide Fcco to exactly 48 MHz.
*
* (4) In this example
*
* Fin = 12MHz,
* M = 12,
* N = 1,
* clk_div = 4, and
* clk_div_usb = 6.
*
* Therefore, Fcco = 2 * Fin * M / N = (2 * 12 * 12 / 1) = 288MHz.
* The processor clock = (Fcco / clk_div) = (288MHz / 4) = 72MHz.
* Finally, the USB clock = (Fcco / clk_div_usb) = (288MHz / 6) = 48MHz.
**********************************************************************************************************
*/
void BSP_PLL_Init (void)
{
#if CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_STATUS_LOCAL
CPU_SR cpu_sr = 0;
#endif
CPU_INT32U m;
CPU_INT32U n;
CPU_INT32U clk_div;
CPU_INT32U clk_div_usb;
m = 11; /* PLL Multiplier = 20, MSEL bits = 12 - 1 = 11. */
n = 0; /* PLL Divider = 1, NSEL bits = 1 - 1 = 0. */
clk_div = 3; /* Cfg the ARM Core clock div to 4. CCLKSEL = 4 - 1. */
clk_div_usb = 5; /* Cfg the USB clock divider to 6, USBSEL = 6 - 1. */
if (DEF_BIT_IS_SET(PLLSTAT, DEF_BIT_25)) { /* If the PLL is already running. */
CPU_CRITICAL_ENTER();
PLLCON &= ~DEF_BIT_01;/* Disconnect the PLL. */
PLLFEED = 0xAA; /* PLL register update sequence, 0xAA, 0x55. */
PLLFEED = 0x55;
CPU_CRITICAL_EXIT();
}
CPU_CRITICAL_ENTER();
PLLCON &= ~DEF_BIT_00;/* Disable the PLL. */
PLLFEED = 0xAA; /* PLL register update sequence, 0xAA, 0x55. */
PLLFEED = 0x55;
CPU_CRITICAL_EXIT();
SCS &= ~DEF_BIT_04; /* OSCRANGE = 0, Main OSC is between 1 and 20 Mhz. */
SCS |= DEF_BIT_05; /* OSCEN = 1, Enable the main oscillator. */
while (DEF_BIT_IS_CLR(SCS, DEF_BIT_06)) { /* Wait until OSCSTAT is set (Main OSC rdy to be used). */
;
}
CLKSRCSEL = DEF_BIT_00; /* Select main OSC, 12MHz, as the PLL clock source. */
CPU_CRITICAL_ENTER();
PLLCFG = (m << 0) | (n << 16); /* Configure the PLL multiplier and divider. */
PLLFEED = 0xAA; /* PLL register update sequence, 0xAA, 0x55. */
PLLFEED = 0x55;
CPU_CRITICAL_EXIT();
CPU_CRITICAL_ENTER();
PLLCON |= DEF_BIT_00; /* Enable the PLL. */
PLLFEED = 0xAA; /* PLL register update sequence, 0xAA, 0x55. */
PLLFEED = 0x55;
CPU_CRITICAL_EXIT();
CCLKCFG = clk_div; /* Configure the ARM Core Processor clock divider. */
USBCLKCFG = clk_div_usb; /* Configure the USB clock divider. */
while (DEF_BIT_IS_CLR(PLLSTAT, DEF_BIT_26)) { /* Wait for PLOCK to become set. */
;
}
PCLKSEL0 = 0xAAAAAAAA; /* Set peripheral clocks to be half of main clock. */
PCLKSEL1 = 0x22AAA8AA;
CPU_CRITICAL_ENTER();
PLLCON |= DEF_BIT_01; /* Connect the PLL. The PLL is now the active clk src. */
PLLFEED = 0xAA; /* PLL register update sequence, 0xAA, 0x55. */
PLLFEED = 0x55;
CPU_CRITICAL_EXIT();
while (DEF_BIT_IS_CLR(PLLSTAT, DEF_BIT_25)) { /* Wait PLLC, the PLL connect status bit to become set. */
;
}
}
一://先获取CPU时钟频率
CPU_INT32U BSP_CPU_ClkFreq (void)
{
CPU_INT32U clk_src;
CPU_INT32U clk_div;
CPU_INT32U clk_freq;
CPU_INT32U pll_stat; /* PLL status */
CPU_INT32U pll_clk_feq; /* When the PLL is enabled, this is Fcco. */
CPU_INT32U pll_msel; /* PLL multipler and pre-dividier values */
CPU_INT32U pll_nsel;
switch (CLKSRCSEL & 0x03) { /* Determine the current clock source. */
case 0:
clk_src = BSP_IRC_OSC_FRQ;
break;
case 1:
clk_src = BSP_MAIN_OSC_FRQ;
break;
case 2:
clk_src = BSP_RTC_OSC_FRQ;
break;
default:
clk_src = BSP_IRC_OSC_FRQ;
break;
}
pll_stat = PLLSTAT;
if ((DEF_BIT_IS_SET(pll_stat, DEF_BIT_24)) && /* If the PLL is currently enabled and connected. */
(DEF_BIT_IS_SET(pll_stat, DEF_BIT_25))) {
pll_msel = (CPU_INT32U)((pll_stat >> 0 ) & 0x3FFF) + 1;
pll_nsel = (CPU_INT32U)((pll_stat >> 16 ) & 0x000F) + 1;
pll_clk_feq = (2 * pll_msel * (clk_src / pll_nsel)); /* Compute the PLL output frequency. */
} else {
pll_clk_feq = (clk_src); /* The PLL is bypassed. */
}
clk_div = (CPU_INT32U)(CCLKCFG & 0xFF) + 1; /* Obtain the CPU core clock divider. */
clk_freq = (CPU_INT32U)(pll_clk_feq / clk_div); /* Compute the ARM Core clock frequency. */
return (clk_freq);
}
二://Get the peripheral clock frequency for a specific peripheral再获取获取外围设备的时钟频率,这里是串口
uint32_t per_clk_freq = BSP_CPU_PclkFreq(BSP_PCLK_UART0);
CPU_INT32U BSP_CPU_PclkFreq (CPU_INT08U pclk)
{
CPU_INT32U clk_freq;
CPU_INT32U pclk_freq;
CPU_INT32U sel;
clk_freq = BSP_CPU_ClkFreq(); //获取CPU时钟频率
if (pclk > 29) {
return (CPU_INT32U)0;
}
if (pclk < 16) {
sel = (PCLKSEL0 >> (2 * pclk )) & 0x03;
} else {
sel = (PCLKSEL1 >> (2 * (pclk - 16))) & 0x03;
}
if (sel == 0 ){
pclk_freq = clk_freq / 4;
} else if (sel == 1) {
pclk_freq = clk_freq;
} else if (sel == 2) {
pclk_freq = clk_freq / 2;
} else {
if ((pclk == BSP_PCLK_CAN1) || (pclk == BSP_PCLK_CAN1)) {
pclk_freq = clk_freq / 6;
} else {
pclk_freq = clk_freq / 8;
}
}
return (pclk_freq);
}