917 lines
26 KiB
C
917 lines
26 KiB
C
/*!
|
|
\file system_gd32f4xx.c
|
|
\brief CMSIS Cortex-M4 Device Peripheral Access Layer Source File for
|
|
GD32F4xx Device Series
|
|
*/
|
|
|
|
/* Copyright (c) 2012 ARM LIMITED
|
|
|
|
All rights reserved.
|
|
Redistribution and use in source and binary forms, with or without
|
|
modification, are permitted provided that the following conditions are met:
|
|
- Redistributions of source code must retain the above copyright
|
|
notice, this list of conditions and the following disclaimer.
|
|
- 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.
|
|
- Neither the name of ARM 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 COPYRIGHT HOLDERS AND 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.
|
|
---------------------------------------------------------------------------*/
|
|
|
|
/* This file refers the CMSIS standard, some adjustments are made according to GigaDevice chips */
|
|
|
|
#include "gd32f4xx.h"
|
|
|
|
/* system frequency define */
|
|
#define __IRC16M (IRC16M_VALUE) /* internal 16 MHz RC oscillator frequency */
|
|
#define __HXTAL (HXTAL_VALUE) /* high speed crystal oscillator frequency */
|
|
#define __SYS_OSC_CLK (__IRC16M) /* main oscillator frequency */
|
|
|
|
/* select a system clock by uncommenting the following line */
|
|
//#define __SYSTEM_CLOCK_IRC16M (uint32_t)(__IRC16M)
|
|
//#define __SYSTEM_CLOCK_HXTAL (uint32_t)(__HXTAL)
|
|
//#define __SYSTEM_CLOCK_120M_PLL_IRC16M (uint32_t)(120000000)
|
|
//#define __SYSTEM_CLOCK_120M_PLL_8M_HXTAL (uint32_t)(120000000)
|
|
//#define __SYSTEM_CLOCK_120M_PLL_25M_HXTAL (uint32_t)(120000000)
|
|
//#define __SYSTEM_CLOCK_168M_PLL_IRC16M (uint32_t)(168000000)
|
|
//#define __SYSTEM_CLOCK_168M_PLL_8M_HXTAL (uint32_t)(168000000)
|
|
//#define __SYSTEM_CLOCK_168M_PLL_25M_HXTAL (uint32_t)(168000000)
|
|
//#define __SYSTEM_CLOCK_200M_PLL_IRC16M (uint32_t)(200000000)
|
|
//#define __SYSTEM_CLOCK_200M_PLL_8M_HXTAL (uint32_t)(200000000)
|
|
#define __SYSTEM_CLOCK_200M_PLL_25M_HXTAL (uint32_t)(200000000)
|
|
|
|
#define SEL_IRC16M 0x00U
|
|
#define SEL_HXTAL 0x01U
|
|
#define SEL_PLLP 0x02U
|
|
#define RCU_MODIFY {volatile uint32_t i; \
|
|
RCU_CFG0 |= RCU_AHB_CKSYS_DIV2; \
|
|
for(i=0;i<50000;i++);}
|
|
|
|
/* set the system clock frequency and declare the system clock configuration function */
|
|
#ifdef __SYSTEM_CLOCK_IRC16M
|
|
uint32_t SystemCoreClock = __SYSTEM_CLOCK_IRC16M;
|
|
static void system_clock_16m_irc16m(void);
|
|
#elif defined (__SYSTEM_CLOCK_HXTAL)
|
|
uint32_t SystemCoreClock = __SYSTEM_CLOCK_HXTAL;
|
|
static void system_clock_hxtal(void);
|
|
#elif defined (__SYSTEM_CLOCK_120M_PLL_IRC16M)
|
|
uint32_t SystemCoreClock = __SYSTEM_CLOCK_120M_PLL_IRC16M;
|
|
static void system_clock_120m_irc16m(void);
|
|
#elif defined (__SYSTEM_CLOCK_120M_PLL_8M_HXTAL)
|
|
uint32_t SystemCoreClock = __SYSTEM_CLOCK_120M_PLL_8M_HXTAL;
|
|
static void system_clock_120m_8m_hxtal(void);
|
|
#elif defined (__SYSTEM_CLOCK_120M_PLL_25M_HXTAL)
|
|
uint32_t SystemCoreClock = __SYSTEM_CLOCK_120M_PLL_25M_HXTAL;
|
|
static void system_clock_120m_25m_hxtal(void);
|
|
#elif defined (__SYSTEM_CLOCK_168M_PLL_IRC16M)
|
|
uint32_t SystemCoreClock = __SYSTEM_CLOCK_168M_PLL_IRC16M;
|
|
static void system_clock_168m_irc16m(void);
|
|
#elif defined (__SYSTEM_CLOCK_168M_PLL_8M_HXTAL)
|
|
uint32_t SystemCoreClock = __SYSTEM_CLOCK_168M_PLL_8M_HXTAL;
|
|
static void system_clock_168m_8m_hxtal(void);
|
|
#elif defined (__SYSTEM_CLOCK_168M_PLL_25M_HXTAL)
|
|
uint32_t SystemCoreClock = __SYSTEM_CLOCK_168M_PLL_25M_HXTAL;
|
|
static void system_clock_168m_25m_hxtal(void);
|
|
#elif defined (__SYSTEM_CLOCK_200M_PLL_IRC16M)
|
|
uint32_t SystemCoreClock = __SYSTEM_CLOCK_200M_PLL_IRC16M;
|
|
static void system_clock_200m_irc16m(void);
|
|
#elif defined (__SYSTEM_CLOCK_200M_PLL_8M_HXTAL)
|
|
uint32_t SystemCoreClock = __SYSTEM_CLOCK_200M_PLL_8M_HXTAL;
|
|
static void system_clock_200m_8m_hxtal(void);
|
|
#elif defined (__SYSTEM_CLOCK_200M_PLL_25M_HXTAL)
|
|
uint32_t SystemCoreClock = __SYSTEM_CLOCK_200M_PLL_25M_HXTAL;
|
|
static void system_clock_200m_25m_hxtal(void);
|
|
|
|
#endif /* __SYSTEM_CLOCK_IRC16M */
|
|
|
|
/* configure the system clock */
|
|
static void system_clock_config(void);
|
|
|
|
/*!
|
|
\brief setup the microcontroller system, initialize the system
|
|
\param[in] none
|
|
\param[out] none
|
|
\retval none
|
|
*/
|
|
void SystemInit (void)
|
|
{
|
|
/* FPU settings ------------------------------------------------------------*/
|
|
#if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
|
|
SCB->CPACR |= ((3UL << 10*2)|(3UL << 11*2)); /* set CP10 and CP11 Full Access */
|
|
#endif
|
|
/* Reset the RCU clock configuration to the default reset state ------------*/
|
|
/* Set IRC16MEN bit */
|
|
RCU_CTL |= RCU_CTL_IRC16MEN;
|
|
|
|
RCU_MODIFY
|
|
|
|
/* Reset CFG0 register */
|
|
RCU_CFG0 = 0x00000000U;
|
|
|
|
/* Reset HXTALEN, CKMEN and PLLEN bits */
|
|
RCU_CTL &= ~(RCU_CTL_PLLEN | RCU_CTL_CKMEN | RCU_CTL_HXTALEN);
|
|
|
|
/* Reset PLLCFGR register */
|
|
RCU_PLL = 0x24003010U;
|
|
|
|
/* Reset HSEBYP bit */
|
|
RCU_CTL &= ~(RCU_CTL_HXTALBPS);
|
|
|
|
/* Disable all interrupts */
|
|
RCU_INT = 0x00000000U;
|
|
|
|
/* Configure the System clock source, PLL Multiplier and Divider factors,
|
|
AHB/APBx prescalers and Flash settings ----------------------------------*/
|
|
system_clock_config();
|
|
}
|
|
/*!
|
|
\brief configure the system clock
|
|
\param[in] none
|
|
\param[out] none
|
|
\retval none
|
|
*/
|
|
static void system_clock_config(void)
|
|
{
|
|
#ifdef __SYSTEM_CLOCK_IRC16M
|
|
system_clock_16m_irc16m();
|
|
#elif defined (__SYSTEM_CLOCK_HXTAL)
|
|
system_clock_hxtal();
|
|
#elif defined (__SYSTEM_CLOCK_120M_PLL_IRC16M)
|
|
system_clock_120m_irc16m();
|
|
#elif defined (__SYSTEM_CLOCK_120M_PLL_8M_HXTAL)
|
|
system_clock_120m_8m_hxtal();
|
|
#elif defined (__SYSTEM_CLOCK_120M_PLL_25M_HXTAL)
|
|
system_clock_120m_25m_hxtal();
|
|
#elif defined (__SYSTEM_CLOCK_168M_PLL_IRC16M)
|
|
system_clock_168m_irc16m();
|
|
#elif defined (__SYSTEM_CLOCK_168M_PLL_8M_HXTAL)
|
|
system_clock_168m_8m_hxtal();
|
|
#elif defined (__SYSTEM_CLOCK_168M_PLL_25M_HXTAL)
|
|
system_clock_168m_25m_hxtal();
|
|
#elif defined (__SYSTEM_CLOCK_200M_PLL_IRC16M)
|
|
system_clock_200m_irc16m();
|
|
#elif defined (__SYSTEM_CLOCK_200M_PLL_8M_HXTAL)
|
|
system_clock_200m_8m_hxtal();
|
|
#elif defined (__SYSTEM_CLOCK_200M_PLL_25M_HXTAL)
|
|
system_clock_200m_25m_hxtal();
|
|
#endif /* __SYSTEM_CLOCK_IRC16M */
|
|
}
|
|
|
|
#ifdef __SYSTEM_CLOCK_IRC16M
|
|
/*!
|
|
\brief configure the system clock to 16M by IRC16M
|
|
\param[in] none
|
|
\param[out] none
|
|
\retval none
|
|
*/
|
|
static void system_clock_16m_irc16m(void)
|
|
{
|
|
uint32_t timeout = 0U;
|
|
uint32_t stab_flag = 0U;
|
|
|
|
/* enable IRC16M */
|
|
RCU_CTL |= RCU_CTL_IRC16MEN;
|
|
|
|
/* wait until IRC16M is stable or the startup time is longer than IRC16M_STARTUP_TIMEOUT */
|
|
do{
|
|
timeout++;
|
|
stab_flag = (RCU_CTL & RCU_CTL_IRC16MSTB);
|
|
}while((0U == stab_flag) && (IRC16M_STARTUP_TIMEOUT != timeout));
|
|
|
|
/* if fail */
|
|
if(0U == (RCU_CTL & RCU_CTL_IRC16MSTB)){
|
|
while(1){
|
|
}
|
|
}
|
|
|
|
/* AHB = SYSCLK */
|
|
RCU_CFG0 |= RCU_AHB_CKSYS_DIV1;
|
|
/* APB2 = AHB */
|
|
RCU_CFG0 |= RCU_APB2_CKAHB_DIV1;
|
|
/* APB1 = AHB */
|
|
RCU_CFG0 |= RCU_APB1_CKAHB_DIV1;
|
|
|
|
/* select IRC16M as system clock */
|
|
RCU_CFG0 &= ~RCU_CFG0_SCS;
|
|
RCU_CFG0 |= RCU_CKSYSSRC_IRC16M;
|
|
|
|
/* wait until IRC16M is selected as system clock */
|
|
while(0 != (RCU_CFG0 & RCU_SCSS_IRC16M)){
|
|
}
|
|
}
|
|
|
|
#elif defined (__SYSTEM_CLOCK_HXTAL)
|
|
/*!
|
|
\brief configure the system clock to HXTAL
|
|
\param[in] none
|
|
\param[out] none
|
|
\retval none
|
|
*/
|
|
static void system_clock_hxtal(void)
|
|
{
|
|
uint32_t timeout = 0U;
|
|
uint32_t stab_flag = 0U;
|
|
|
|
/* enable HXTAL */
|
|
RCU_CTL |= RCU_CTL_HXTALEN;
|
|
|
|
/* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */
|
|
do{
|
|
timeout++;
|
|
stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB);
|
|
}while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout));
|
|
|
|
/* if fail */
|
|
if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){
|
|
while(1){
|
|
}
|
|
}
|
|
|
|
/* AHB = SYSCLK */
|
|
RCU_CFG0 |= RCU_AHB_CKSYS_DIV1;
|
|
/* APB2 = AHB */
|
|
RCU_CFG0 |= RCU_APB2_CKAHB_DIV1;
|
|
/* APB1 = AHB */
|
|
RCU_CFG0 |= RCU_APB1_CKAHB_DIV1;
|
|
|
|
/* select HXTAL as system clock */
|
|
RCU_CFG0 &= ~RCU_CFG0_SCS;
|
|
RCU_CFG0 |= RCU_CKSYSSRC_HXTAL;
|
|
|
|
/* wait until HXTAL is selected as system clock */
|
|
while(0 == (RCU_CFG0 & RCU_SCSS_HXTAL)){
|
|
}
|
|
}
|
|
|
|
#elif defined (__SYSTEM_CLOCK_120M_PLL_IRC16M)
|
|
/*!
|
|
\brief configure the system clock to 120M by PLL which selects IRC16M as its clock source
|
|
\param[in] none
|
|
\param[out] none
|
|
\retval none
|
|
*/
|
|
static void system_clock_120m_irc16m(void)
|
|
{
|
|
uint32_t timeout = 0U;
|
|
uint32_t stab_flag = 0U;
|
|
|
|
/* enable IRC16M */
|
|
RCU_CTL |= RCU_CTL_IRC16MEN;
|
|
|
|
/* wait until IRC16M is stable or the startup time is longer than IRC16M_STARTUP_TIMEOUT */
|
|
do{
|
|
timeout++;
|
|
stab_flag = (RCU_CTL & RCU_CTL_IRC16MSTB);
|
|
}while((0U == stab_flag) && (IRC16M_STARTUP_TIMEOUT != timeout));
|
|
|
|
/* if fail */
|
|
if(0U == (RCU_CTL & RCU_CTL_IRC16MSTB)){
|
|
while(1){
|
|
}
|
|
}
|
|
|
|
RCU_APB1EN |= RCU_APB1EN_PMUEN;
|
|
PMU_CTL |= PMU_CTL_LDOVS;
|
|
|
|
/* IRC16M is stable */
|
|
/* AHB = SYSCLK */
|
|
RCU_CFG0 |= RCU_AHB_CKSYS_DIV1;
|
|
/* APB2 = AHB/2 */
|
|
RCU_CFG0 |= RCU_APB2_CKAHB_DIV2;
|
|
/* APB1 = AHB/4 */
|
|
RCU_CFG0 |= RCU_APB1_CKAHB_DIV4;
|
|
|
|
/* Configure the main PLL, PSC = 16, PLL_N = 240, PLL_P = 2, PLL_Q = 5 */
|
|
RCU_PLL = (16U | (240U << 6U) | (((2U >> 1U) - 1U) << 16U) |
|
|
(RCU_PLLSRC_IRC16M) | (5U << 24U));
|
|
|
|
/* enable PLL */
|
|
RCU_CTL |= RCU_CTL_PLLEN;
|
|
|
|
/* wait until PLL is stable */
|
|
while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){
|
|
}
|
|
|
|
/* Enable the high-drive to extend the clock frequency to 120 Mhz */
|
|
PMU_CTL |= PMU_CTL_HDEN;
|
|
while(0U == (PMU_CS & PMU_CS_HDRF)){
|
|
}
|
|
|
|
/* select the high-drive mode */
|
|
PMU_CTL |= PMU_CTL_HDS;
|
|
while(0U == (PMU_CS & PMU_CS_HDSRF)){
|
|
}
|
|
|
|
/* select PLL as system clock */
|
|
RCU_CFG0 &= ~RCU_CFG0_SCS;
|
|
RCU_CFG0 |= RCU_CKSYSSRC_PLLP;
|
|
|
|
/* wait until PLL is selected as system clock */
|
|
while(0U == (RCU_CFG0 & RCU_SCSS_PLLP)){
|
|
}
|
|
}
|
|
|
|
#elif defined (__SYSTEM_CLOCK_120M_PLL_8M_HXTAL)
|
|
/*!
|
|
\brief configure the system clock to 120M by PLL which selects HXTAL(8M) as its clock source
|
|
\param[in] none
|
|
\param[out] none
|
|
\retval none
|
|
*/
|
|
static void system_clock_120m_8m_hxtal(void)
|
|
{
|
|
uint32_t timeout = 0U;
|
|
uint32_t stab_flag = 0U;
|
|
|
|
/* enable HXTAL */
|
|
RCU_CTL |= RCU_CTL_HXTALEN;
|
|
|
|
/* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */
|
|
do{
|
|
timeout++;
|
|
stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB);
|
|
}while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout));
|
|
|
|
/* if fail */
|
|
if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){
|
|
while(1){
|
|
}
|
|
}
|
|
|
|
RCU_APB1EN |= RCU_APB1EN_PMUEN;
|
|
PMU_CTL |= PMU_CTL_LDOVS;
|
|
|
|
/* HXTAL is stable */
|
|
/* AHB = SYSCLK */
|
|
RCU_CFG0 |= RCU_AHB_CKSYS_DIV1;
|
|
/* APB2 = AHB/2 */
|
|
RCU_CFG0 |= RCU_APB2_CKAHB_DIV2;
|
|
/* APB1 = AHB/4 */
|
|
RCU_CFG0 |= RCU_APB1_CKAHB_DIV4;
|
|
|
|
/* Configure the main PLL, PSC = 8, PLL_N = 240, PLL_P = 2, PLL_Q = 5 */
|
|
RCU_PLL = (8U | (240U << 6U) | (((2U >> 1U) - 1U) << 16U) |
|
|
(RCU_PLLSRC_HXTAL) | (5U << 24U));
|
|
|
|
/* enable PLL */
|
|
RCU_CTL |= RCU_CTL_PLLEN;
|
|
|
|
/* wait until PLL is stable */
|
|
while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){
|
|
}
|
|
|
|
/* Enable the high-drive to extend the clock frequency to 120 Mhz */
|
|
PMU_CTL |= PMU_CTL_HDEN;
|
|
while(0U == (PMU_CS & PMU_CS_HDRF)){
|
|
}
|
|
|
|
/* select the high-drive mode */
|
|
PMU_CTL |= PMU_CTL_HDS;
|
|
while(0U == (PMU_CS & PMU_CS_HDSRF)){
|
|
}
|
|
|
|
/* select PLL as system clock */
|
|
RCU_CFG0 &= ~RCU_CFG0_SCS;
|
|
RCU_CFG0 |= RCU_CKSYSSRC_PLLP;
|
|
|
|
/* wait until PLL is selected as system clock */
|
|
while(0U == (RCU_CFG0 & RCU_SCSS_PLLP)){
|
|
}
|
|
}
|
|
|
|
#elif defined (__SYSTEM_CLOCK_120M_PLL_25M_HXTAL)
|
|
/*!
|
|
\brief configure the system clock to 120M by PLL which selects HXTAL(25M) as its clock source
|
|
\param[in] none
|
|
\param[out] none
|
|
\retval none
|
|
*/
|
|
static void system_clock_120m_25m_hxtal(void)
|
|
{
|
|
uint32_t timeout = 0U;
|
|
uint32_t stab_flag = 0U;
|
|
|
|
/* enable HXTAL */
|
|
RCU_CTL |= RCU_CTL_HXTALEN;
|
|
|
|
/* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */
|
|
do{
|
|
timeout++;
|
|
stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB);
|
|
}while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout));
|
|
|
|
/* if fail */
|
|
if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){
|
|
while(1){
|
|
}
|
|
}
|
|
|
|
RCU_APB1EN |= RCU_APB1EN_PMUEN;
|
|
PMU_CTL |= PMU_CTL_LDOVS;
|
|
|
|
/* HXTAL is stable */
|
|
/* AHB = SYSCLK */
|
|
RCU_CFG0 |= RCU_AHB_CKSYS_DIV1;
|
|
/* APB2 = AHB/2 */
|
|
RCU_CFG0 |= RCU_APB2_CKAHB_DIV2;
|
|
/* APB1 = AHB/4 */
|
|
RCU_CFG0 |= RCU_APB1_CKAHB_DIV4;
|
|
|
|
/* Configure the main PLL, PSC = 25, PLL_N = 240, PLL_P = 2, PLL_Q = 5 */
|
|
RCU_PLL = (25U | (240U << 6U) | (((2U >> 1U) - 1U) << 16U) |
|
|
(RCU_PLLSRC_HXTAL) | (5U << 24U));
|
|
|
|
/* enable PLL */
|
|
RCU_CTL |= RCU_CTL_PLLEN;
|
|
|
|
/* wait until PLL is stable */
|
|
while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){
|
|
}
|
|
|
|
/* Enable the high-drive to extend the clock frequency to 120 Mhz */
|
|
PMU_CTL |= PMU_CTL_HDEN;
|
|
while(0U == (PMU_CS & PMU_CS_HDRF)){
|
|
}
|
|
|
|
/* select the high-drive mode */
|
|
PMU_CTL |= PMU_CTL_HDS;
|
|
while(0U == (PMU_CS & PMU_CS_HDSRF)){
|
|
}
|
|
|
|
/* select PLL as system clock */
|
|
RCU_CFG0 &= ~RCU_CFG0_SCS;
|
|
RCU_CFG0 |= RCU_CKSYSSRC_PLLP;
|
|
|
|
/* wait until PLL is selected as system clock */
|
|
while(0U == (RCU_CFG0 & RCU_SCSS_PLLP)){
|
|
}
|
|
}
|
|
|
|
#elif defined (__SYSTEM_CLOCK_168M_PLL_IRC16M)
|
|
/*!
|
|
\brief configure the system clock to 168M by PLL which selects IRC16M as its clock source
|
|
\param[in] none
|
|
\param[out] none
|
|
\retval none
|
|
*/
|
|
static void system_clock_168m_irc16m(void)
|
|
{
|
|
uint32_t timeout = 0U;
|
|
uint32_t stab_flag = 0U;
|
|
|
|
/* enable IRC16M */
|
|
RCU_CTL |= RCU_CTL_IRC16MEN;
|
|
|
|
/* wait until IRC16M is stable or the startup time is longer than IRC16M_STARTUP_TIMEOUT */
|
|
do{
|
|
timeout++;
|
|
stab_flag = (RCU_CTL & RCU_CTL_IRC16MSTB);
|
|
}while((0U == stab_flag) && (IRC16M_STARTUP_TIMEOUT != timeout));
|
|
|
|
/* if fail */
|
|
if(0U == (RCU_CTL & RCU_CTL_IRC16MSTB)){
|
|
while(1){
|
|
}
|
|
}
|
|
|
|
RCU_APB1EN |= RCU_APB1EN_PMUEN;
|
|
PMU_CTL |= PMU_CTL_LDOVS;
|
|
|
|
/* IRC16M is stable */
|
|
/* AHB = SYSCLK */
|
|
RCU_CFG0 |= RCU_AHB_CKSYS_DIV1;
|
|
/* APB2 = AHB/2 */
|
|
RCU_CFG0 |= RCU_APB2_CKAHB_DIV2;
|
|
/* APB1 = AHB/4 */
|
|
RCU_CFG0 |= RCU_APB1_CKAHB_DIV4;
|
|
|
|
/* Configure the main PLL, PSC = 16, PLL_N = 336, PLL_P = 2, PLL_Q = 7 */
|
|
RCU_PLL = (16U | (336U << 6U) | (((2U >> 1U) - 1U) << 16U) |
|
|
(RCU_PLLSRC_IRC16M) | (7U << 24U));
|
|
|
|
/* enable PLL */
|
|
RCU_CTL |= RCU_CTL_PLLEN;
|
|
|
|
/* wait until PLL is stable */
|
|
while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){
|
|
}
|
|
|
|
/* Enable the high-drive to extend the clock frequency to 168 Mhz */
|
|
PMU_CTL |= PMU_CTL_HDEN;
|
|
while(0U == (PMU_CS & PMU_CS_HDRF)){
|
|
}
|
|
|
|
/* select the high-drive mode */
|
|
PMU_CTL |= PMU_CTL_HDS;
|
|
while(0U == (PMU_CS & PMU_CS_HDSRF)){
|
|
}
|
|
|
|
/* select PLL as system clock */
|
|
RCU_CFG0 &= ~RCU_CFG0_SCS;
|
|
RCU_CFG0 |= RCU_CKSYSSRC_PLLP;
|
|
|
|
/* wait until PLL is selected as system clock */
|
|
while(0U == (RCU_CFG0 & RCU_SCSS_PLLP)){
|
|
}
|
|
}
|
|
|
|
#elif defined (__SYSTEM_CLOCK_168M_PLL_8M_HXTAL)
|
|
/*!
|
|
\brief configure the system clock to 168M by PLL which selects HXTAL(8M) as its clock source
|
|
\param[in] none
|
|
\param[out] none
|
|
\retval none
|
|
*/
|
|
static void system_clock_168m_8m_hxtal(void)
|
|
{
|
|
uint32_t timeout = 0U;
|
|
|
|
/* enable HXTAL */
|
|
RCU_CTL |= RCU_CTL_HXTALEN;
|
|
|
|
/* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */
|
|
while((0U == (RCU_CTL & RCU_CTL_HXTALSTB)) && (HXTAL_STARTUP_TIMEOUT != timeout++)){
|
|
}
|
|
|
|
/* if fail */
|
|
if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){
|
|
while(1){
|
|
}
|
|
}
|
|
|
|
RCU_APB1EN |= RCU_APB1EN_PMUEN;
|
|
PMU_CTL |= PMU_CTL_LDOVS;
|
|
/* HXTAL is stable */
|
|
/* AHB = SYSCLK */
|
|
RCU_CFG0 |= RCU_AHB_CKSYS_DIV1;
|
|
/* APB2 = AHB/2 */
|
|
RCU_CFG0 |= RCU_APB2_CKAHB_DIV2;
|
|
/* APB1 = AHB/4 */
|
|
RCU_CFG0 |= RCU_APB1_CKAHB_DIV4;
|
|
|
|
/* Configure the main PLL, PSC = 8, PLL_N = 336, PLL_P = 2, PLL_Q = 7 */
|
|
RCU_PLL = (8U | (336 << 6U) | (((2 >> 1U) -1U) << 16U) |
|
|
(RCU_PLLSRC_HXTAL) | (7 << 24U));
|
|
|
|
/* enable PLL */
|
|
RCU_CTL |= RCU_CTL_PLLEN;
|
|
|
|
/* wait until PLL is stable */
|
|
while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){
|
|
}
|
|
|
|
/* Enable the high-drive to extend the clock frequency to 168 Mhz */
|
|
PMU_CTL |= PMU_CTL_HDEN;
|
|
while(0U == (PMU_CS & PMU_CS_HDRF)){
|
|
}
|
|
|
|
/* select the high-drive mode */
|
|
PMU_CTL |= PMU_CTL_HDS;
|
|
while(0U == (PMU_CS & PMU_CS_HDSRF)){
|
|
}
|
|
|
|
/* select PLL as system clock */
|
|
RCU_CFG0 &= ~RCU_CFG0_SCS;
|
|
RCU_CFG0 |= RCU_CKSYSSRC_PLLP;
|
|
|
|
/* wait until PLL is selected as system clock */
|
|
while(0U == (RCU_CFG0 & RCU_SCSS_PLLP)){
|
|
}
|
|
}
|
|
|
|
#elif defined (__SYSTEM_CLOCK_168M_PLL_25M_HXTAL)
|
|
/*!
|
|
\brief configure the system clock to 168M by PLL which selects HXTAL(25M) as its clock source
|
|
\param[in] none
|
|
\param[out] none
|
|
\retval none
|
|
*/
|
|
static void system_clock_168m_25m_hxtal(void)
|
|
{
|
|
uint32_t timeout = 0U;
|
|
uint32_t stab_flag = 0U;
|
|
|
|
/* enable HXTAL */
|
|
RCU_CTL |= RCU_CTL_HXTALEN;
|
|
|
|
/* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */
|
|
do{
|
|
timeout++;
|
|
stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB);
|
|
}while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout));
|
|
|
|
/* if fail */
|
|
if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){
|
|
while(1){
|
|
}
|
|
}
|
|
|
|
RCU_APB1EN |= RCU_APB1EN_PMUEN;
|
|
PMU_CTL |= PMU_CTL_LDOVS;
|
|
|
|
/* HXTAL is stable */
|
|
/* AHB = SYSCLK */
|
|
RCU_CFG0 |= RCU_AHB_CKSYS_DIV1;
|
|
/* APB2 = AHB */
|
|
RCU_CFG0 |= RCU_APB2_CKAHB_DIV2;
|
|
/* APB1 = AHB */
|
|
RCU_CFG0 |= RCU_APB1_CKAHB_DIV4;
|
|
|
|
/* Configure the main PLL, PSC = 25, PLL_N = 336, PLL_P = 2, PLL_Q = 7 */
|
|
RCU_PLL = (25U | (336U << 6U) | (((2U >> 1U) - 1U) << 16U) |
|
|
(RCU_PLLSRC_HXTAL) | (7U << 24U));
|
|
|
|
/* enable PLL */
|
|
RCU_CTL |= RCU_CTL_PLLEN;
|
|
|
|
/* wait until PLL is stable */
|
|
while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){
|
|
}
|
|
|
|
/* Enable the high-drive to extend the clock frequency to 168 Mhz */
|
|
PMU_CTL |= PMU_CTL_HDEN;
|
|
while(0U == (PMU_CS & PMU_CS_HDRF)){
|
|
}
|
|
|
|
/* select the high-drive mode */
|
|
PMU_CTL |= PMU_CTL_HDS;
|
|
while(0U == (PMU_CS & PMU_CS_HDSRF)){
|
|
}
|
|
|
|
/* select PLL as system clock */
|
|
RCU_CFG0 &= ~RCU_CFG0_SCS;
|
|
RCU_CFG0 |= RCU_CKSYSSRC_PLLP;
|
|
|
|
/* wait until PLL is selected as system clock */
|
|
while(0U == (RCU_CFG0 & RCU_SCSS_PLLP)){
|
|
}
|
|
}
|
|
|
|
#elif defined (__SYSTEM_CLOCK_200M_PLL_IRC16M)
|
|
/*!
|
|
\brief configure the system clock to 200M by PLL which selects IRC16M as its clock source
|
|
\param[in] none
|
|
\param[out] none
|
|
\retval none
|
|
*/
|
|
static void system_clock_200m_irc16m(void)
|
|
{
|
|
uint32_t timeout = 0U;
|
|
uint32_t stab_flag = 0U;
|
|
|
|
/* enable IRC16M */
|
|
RCU_CTL |= RCU_CTL_IRC16MEN;
|
|
|
|
/* wait until IRC16M is stable or the startup time is longer than IRC16M_STARTUP_TIMEOUT */
|
|
do{
|
|
timeout++;
|
|
stab_flag = (RCU_CTL & RCU_CTL_IRC16MSTB);
|
|
}while((0U == stab_flag) && (IRC16M_STARTUP_TIMEOUT != timeout));
|
|
|
|
/* if fail */
|
|
if(0U == (RCU_CTL & RCU_CTL_IRC16MSTB)){
|
|
while(1){
|
|
}
|
|
}
|
|
|
|
RCU_APB1EN |= RCU_APB1EN_PMUEN;
|
|
PMU_CTL |= PMU_CTL_LDOVS;
|
|
|
|
/* IRC16M is stable */
|
|
/* AHB = SYSCLK */
|
|
RCU_CFG0 |= RCU_AHB_CKSYS_DIV1;
|
|
/* APB2 = AHB/2 */
|
|
RCU_CFG0 |= RCU_APB2_CKAHB_DIV2;
|
|
/* APB1 = AHB/4 */
|
|
RCU_CFG0 |= RCU_APB1_CKAHB_DIV4;
|
|
|
|
/* Configure the main PLL, PSC = 16, PLL_N = 400, PLL_P = 2, PLL_Q = 9 */
|
|
RCU_PLL = (16U | (400U << 6U) | (((2U >> 1U) - 1U) << 16U) |
|
|
(RCU_PLLSRC_IRC16M) | (9U << 24U));
|
|
|
|
/* enable PLL */
|
|
RCU_CTL |= RCU_CTL_PLLEN;
|
|
|
|
/* wait until PLL is stable */
|
|
while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){
|
|
}
|
|
|
|
/* Enable the high-drive to extend the clock frequency to 200 Mhz */
|
|
PMU_CTL |= PMU_CTL_HDEN;
|
|
while(0U == (PMU_CS & PMU_CS_HDRF)){
|
|
}
|
|
|
|
/* select the high-drive mode */
|
|
PMU_CTL |= PMU_CTL_HDS;
|
|
while(0U == (PMU_CS & PMU_CS_HDSRF)){
|
|
}
|
|
|
|
/* select PLL as system clock */
|
|
RCU_CFG0 &= ~RCU_CFG0_SCS;
|
|
RCU_CFG0 |= RCU_CKSYSSRC_PLLP;
|
|
|
|
/* wait until PLL is selected as system clock */
|
|
while(0U == (RCU_CFG0 & RCU_SCSS_PLLP)){
|
|
}
|
|
}
|
|
|
|
#elif defined (__SYSTEM_CLOCK_200M_PLL_8M_HXTAL)
|
|
/*!
|
|
\brief configure the system clock to 200M by PLL which selects HXTAL(8M) as its clock source
|
|
\param[in] none
|
|
\param[out] none
|
|
\retval none
|
|
*/
|
|
static void system_clock_200m_8m_hxtal(void)
|
|
{
|
|
uint32_t timeout = 0U;
|
|
uint32_t stab_flag = 0U;
|
|
|
|
/* enable HXTAL */
|
|
RCU_CTL |= RCU_CTL_HXTALEN;
|
|
|
|
/* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */
|
|
do{
|
|
timeout++;
|
|
stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB);
|
|
}while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout));
|
|
|
|
/* if fail */
|
|
if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){
|
|
while(1){
|
|
}
|
|
}
|
|
|
|
RCU_APB1EN |= RCU_APB1EN_PMUEN;
|
|
PMU_CTL |= PMU_CTL_LDOVS;
|
|
|
|
/* HXTAL is stable */
|
|
/* AHB = SYSCLK */
|
|
RCU_CFG0 |= RCU_AHB_CKSYS_DIV1;
|
|
/* APB2 = AHB/2 */
|
|
RCU_CFG0 |= RCU_APB2_CKAHB_DIV2;
|
|
/* APB1 = AHB/4 */
|
|
RCU_CFG0 |= RCU_APB1_CKAHB_DIV4;
|
|
|
|
/* Configure the main PLL, PSC = 8, PLL_N = 400, PLL_P = 2, PLL_Q = 9 */
|
|
RCU_PLL = (8U | (400U << 6U) | (((2U >> 1U) - 1U) << 16U) |
|
|
(RCU_PLLSRC_HXTAL) | (9U << 24U));
|
|
|
|
/* enable PLL */
|
|
RCU_CTL |= RCU_CTL_PLLEN;
|
|
|
|
/* wait until PLL is stable */
|
|
while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){
|
|
}
|
|
|
|
/* Enable the high-drive to extend the clock frequency to 200 Mhz */
|
|
PMU_CTL |= PMU_CTL_HDEN;
|
|
while(0U == (PMU_CS & PMU_CS_HDRF)){
|
|
}
|
|
|
|
/* select the high-drive mode */
|
|
PMU_CTL |= PMU_CTL_HDS;
|
|
while(0U == (PMU_CS & PMU_CS_HDSRF)){
|
|
}
|
|
|
|
/* select PLL as system clock */
|
|
RCU_CFG0 &= ~RCU_CFG0_SCS;
|
|
RCU_CFG0 |= RCU_CKSYSSRC_PLLP;
|
|
|
|
/* wait until PLL is selected as system clock */
|
|
while(0U == (RCU_CFG0 & RCU_SCSS_PLLP)){
|
|
}
|
|
}
|
|
|
|
#elif defined (__SYSTEM_CLOCK_200M_PLL_25M_HXTAL)
|
|
/*!
|
|
\brief configure the system clock to 200M by PLL which selects HXTAL(25M) as its clock source
|
|
\param[in] none
|
|
\param[out] none
|
|
\retval none
|
|
*/
|
|
static void system_clock_200m_25m_hxtal(void)
|
|
{
|
|
uint32_t timeout = 0U;
|
|
uint32_t stab_flag = 0U;
|
|
|
|
/* enable HXTAL */
|
|
RCU_CTL |= RCU_CTL_HXTALEN;
|
|
|
|
/* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */
|
|
do{
|
|
timeout++;
|
|
stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB);
|
|
}while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout));
|
|
|
|
/* if fail */
|
|
if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){
|
|
while(1){
|
|
}
|
|
}
|
|
|
|
RCU_APB1EN |= RCU_APB1EN_PMUEN;
|
|
PMU_CTL |= PMU_CTL_LDOVS;
|
|
|
|
/* HXTAL is stable */
|
|
/* AHB = SYSCLK */
|
|
RCU_CFG0 |= RCU_AHB_CKSYS_DIV1;
|
|
/* APB2 = AHB/2 */
|
|
RCU_CFG0 |= RCU_APB2_CKAHB_DIV2;
|
|
/* APB1 = AHB/4 */
|
|
RCU_CFG0 |= RCU_APB1_CKAHB_DIV4;
|
|
|
|
/* Configure the main PLL, PSC = 25, PLL_N = 400, PLL_P = 2, PLL_Q = 9 */
|
|
RCU_PLL = (25U | (400U << 6U) | (((2U >> 1U) - 1U) << 16U) |
|
|
(RCU_PLLSRC_HXTAL) | (9U << 24U));
|
|
|
|
/* enable PLL */
|
|
RCU_CTL |= RCU_CTL_PLLEN;
|
|
|
|
/* wait until PLL is stable */
|
|
while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){
|
|
}
|
|
|
|
/* Enable the high-drive to extend the clock frequency to 200 Mhz */
|
|
PMU_CTL |= PMU_CTL_HDEN;
|
|
while(0U == (PMU_CS & PMU_CS_HDRF)){
|
|
}
|
|
|
|
/* select the high-drive mode */
|
|
PMU_CTL |= PMU_CTL_HDS;
|
|
while(0U == (PMU_CS & PMU_CS_HDSRF)){
|
|
}
|
|
|
|
/* select PLL as system clock */
|
|
RCU_CFG0 &= ~RCU_CFG0_SCS;
|
|
RCU_CFG0 |= RCU_CKSYSSRC_PLLP;
|
|
|
|
/* wait until PLL is selected as system clock */
|
|
while(0U == (RCU_CFG0 & RCU_SCSS_PLLP)){
|
|
}
|
|
}
|
|
|
|
#endif /* __SYSTEM_CLOCK_IRC16M */
|
|
/*!
|
|
\brief update the SystemCoreClock with current core clock retrieved from cpu registers
|
|
\param[in] none
|
|
\param[out] none
|
|
\retval none
|
|
*/
|
|
void SystemCoreClockUpdate (void)
|
|
{
|
|
uint32_t sws;
|
|
uint32_t pllpsc, plln, pllsel, pllp, ck_src, idx, clk_exp;
|
|
|
|
/* exponent of AHB, APB1 and APB2 clock divider */
|
|
const uint8_t ahb_exp[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9};
|
|
|
|
sws = GET_BITS(RCU_CFG0, 2, 3);
|
|
switch(sws){
|
|
/* IRC16M is selected as CK_SYS */
|
|
case SEL_IRC16M:
|
|
SystemCoreClock = IRC16M_VALUE;
|
|
break;
|
|
/* HXTAL is selected as CK_SYS */
|
|
case SEL_HXTAL:
|
|
SystemCoreClock = HXTAL_VALUE;
|
|
break;
|
|
/* PLLP is selected as CK_SYS */
|
|
case SEL_PLLP:
|
|
/* get the value of PLLPSC[5:0] */
|
|
pllpsc = GET_BITS(RCU_PLL, 0U, 5U);
|
|
plln = GET_BITS(RCU_PLL, 6U, 14U);
|
|
pllp = (GET_BITS(RCU_PLL, 16U, 17U) + 1U) * 2U;
|
|
/* PLL clock source selection, HXTAL or IRC8M/2 */
|
|
pllsel = (RCU_PLL & RCU_PLL_PLLSEL);
|
|
if (RCU_PLLSRC_HXTAL == pllsel) {
|
|
ck_src = HXTAL_VALUE;
|
|
} else {
|
|
ck_src = IRC16M_VALUE;
|
|
}
|
|
SystemCoreClock = ((ck_src / pllpsc) * plln)/pllp;
|
|
break;
|
|
/* IRC16M is selected as CK_SYS */
|
|
default:
|
|
SystemCoreClock = IRC16M_VALUE;
|
|
break;
|
|
}
|
|
/* calculate AHB clock frequency */
|
|
idx = GET_BITS(RCU_CFG0, 4, 7);
|
|
clk_exp = ahb_exp[idx];
|
|
SystemCoreClock = SystemCoreClock >> clk_exp;
|
|
}
|