Files
DCU_APP/GD32E508_DCU_APP/RTE/Device/GD32E508VE/system_gd32e50x.c
T
cbb 44d407390b fix(esc_lan9252): 修复LAN9252 HBI访问模型和IRQ输出使能问题
- 修正HBI访问模型:将ESC核心CSR(0x0000-0x0FFF)改为通过ECAT_CSR_CMD/DATA
  间接端口访问,解决此前直接寻址导致核心寄存器恒读0/写丢弃的问题

- 新增csrRead/csrWrite/pramRead/pramWrite接口,正确实现LAN9252访问端口操作

- 添加PDI就绪检测:等待DL_STATUS bit0置位确认EEPROM加载完成和EtherCAT核心使能

- 实现IRQ引脚输出使能:配置IRQ_CFG和INT_EN寄存器,使EtherCAT事件能到达PB1,
  解决PDI_Isr未触发导致SAFEOP->OP无限挂起的问题

- 为ESC_EXMC硬件诊断添加CONFIG_ESC_EXMC_DIAG门控,默认关闭避免影响正常运行

- 修正system_gd32e50x.c中HXTAL故障诊断的寄存器偏移和位设置错
2026-09-02 02:38:35 +08:00

1309 lines
44 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*!
\file system_gd32e50x.c
\brief CMSIS Cortex-M33 Device Peripheral Access Layer Source File for
GD32E50x Device Series
*/
/*
* Copyright (c) 2009-2018 Arm Limited. All rights reserved.
* Copyright (c) 2023, GigaDevice Semiconductor Inc.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* This file refers the CMSIS standard, some adjustments are made according to GigaDevice chips */
#include "gd32e50x.h"
/* system frequency define */
#define __IRC8M (IRC8M_VALUE) /* internal 8 MHz RC oscillator frequency */
#define __HXTAL (HXTAL_VALUE) /* high speed crystal oscillator frequency */
#define VECT_TAB_OFFSET (uint32_t)0x00048000 /* vector table base offset */
/* select a system clock by uncommenting the following line */
/* use IRC8M */
//#define __SYSTEM_CLOCK_IRC8M (uint32_t)(__IRC8M)
//#define __SYSTEM_CLOCK_72M_PLL_IRC8M (uint32_t)(72000000)
//#define __SYSTEM_CLOCK_120M_PLL_IRC8M (uint32_t)(120000000)
//#define __SYSTEM_CLOCK_168M_PLL_IRC8M (uint32_t)(168000000)
//#define __SYSTEM_CLOCK_180M_PLL_IRC8M (uint32_t)(180000000)
/* use HXTAL(EPRT/HD series CK_HXTAL = 8M, CL series CK_HXTAL = 25M) */
//#define __SYSTEM_CLOCK_HXTAL (uint32_t)(__HXTAL)
//#define __SYSTEM_CLOCK_72M_PLL_HXTAL (uint32_t)(72000000)
//#define __SYSTEM_CLOCK_120M_PLL_HXTAL (uint32_t)(120000000)
//#define __SYSTEM_CLOCK_168M_PLL_HXTAL (uint32_t)(168000000)
#define __SYSTEM_CLOCK_180M_PLL_HXTAL (uint32_t)(180000000)
/* The following is to prevent Vcore fluctuations caused by frequency switching.
It is strongly recommended to include it to avoid issues caused by self-removal. */
#define RCU_MODIFY(__delay) do{ \
volatile uint32_t i,reg;; \
if(0 != __delay){ \
/* Insert a software delay */ \
for(i=0; i<__delay; i++){ \
} \
reg = RCU_CFG0; \
reg &= ~(RCU_CFG0_AHBPSC); \
reg |= RCU_AHB_CKSYS_DIV2; \
/* AHB = SYSCLK/2 */ \
RCU_CFG0 = reg; \
/* Insert a software delay */ \
for(i=0; i<__delay; i++){ \
} \
reg = RCU_CFG0; \
reg &= ~(RCU_CFG0_AHBPSC); \
reg |= RCU_AHB_CKSYS_DIV4; \
/* AHB = SYSCLK/4 */ \
RCU_CFG0 = reg; \
/* Insert a software delay */ \
for(i=0; i<__delay; i++){ \
} \
} \
}while(0)
/* The following is to prevent Vcore fluctuations caused by frequency switching.
It is strongly recommended to include it to avoid issues caused by self-removal. */
#define RCU_MODIFY_UP(__delay) do{ \
volatile uint32_t i,reg; \
if(0 != __delay){ \
for(i=0; i<__delay; i++){ \
} \
reg = RCU_CFG0; \
reg &= ~(RCU_CFG0_AHBPSC); \
reg |= RCU_AHB_CKSYS_DIV2; \
RCU_CFG0 = reg; \
for(i=0; i<__delay; i++){ \
} \
reg = RCU_CFG0; \
reg &= ~(RCU_CFG0_AHBPSC); \
reg |= RCU_AHB_CKSYS_DIV1; \
RCU_CFG0 = reg; \
} \
}while(0)
#define HXTALSTB_DELAY { \
volatile uint32_t i; \
for(i=0; i<0x1000; i++){ \
} \
}
#define SEL_IRC8M 0x00
#define SEL_HXTAL 0x01
#define SEL_PLL 0x02
/* set the system clock frequency and declare the system clock configuration function */
#ifdef __SYSTEM_CLOCK_IRC8M
uint32_t SystemCoreClock = __SYSTEM_CLOCK_IRC8M;
static void system_clock_8m_irc8m(void);
#elif defined (__SYSTEM_CLOCK_72M_PLL_IRC8M)
uint32_t SystemCoreClock = __SYSTEM_CLOCK_72M_PLL_IRC8M;
static void system_clock_72m_irc8m(void);
#elif defined (__SYSTEM_CLOCK_120M_PLL_IRC8M)
uint32_t SystemCoreClock = __SYSTEM_CLOCK_120M_PLL_IRC8M;
static void system_clock_120m_irc8m(void);
#elif defined (__SYSTEM_CLOCK_168M_PLL_IRC8M)
uint32_t SystemCoreClock = __SYSTEM_CLOCK_168M_PLL_IRC8M;
static void system_clock_168m_irc8m(void);
#elif defined (__SYSTEM_CLOCK_180M_PLL_IRC8M)
uint32_t SystemCoreClock = __SYSTEM_CLOCK_180M_PLL_IRC8M;
static void system_clock_180m_irc8m(void);
#elif defined (__SYSTEM_CLOCK_HXTAL)
uint32_t SystemCoreClock = __SYSTEM_CLOCK_HXTAL;
static void system_clock_hxtal(void);
#elif defined (__SYSTEM_CLOCK_72M_PLL_HXTAL)
uint32_t SystemCoreClock = __SYSTEM_CLOCK_72M_PLL_HXTAL;
static void system_clock_72m_hxtal(void);
#elif defined (__SYSTEM_CLOCK_120M_PLL_HXTAL)
uint32_t SystemCoreClock = __SYSTEM_CLOCK_120M_PLL_HXTAL;
static void system_clock_120m_hxtal(void);
#elif defined (__SYSTEM_CLOCK_168M_PLL_HXTAL)
uint32_t SystemCoreClock = __SYSTEM_CLOCK_168M_PLL_HXTAL;
static void system_clock_168m_hxtal(void);
#elif defined (__SYSTEM_CLOCK_180M_PLL_HXTAL)
uint32_t SystemCoreClock = __SYSTEM_CLOCK_180M_PLL_HXTAL;
static void system_clock_180m_hxtal(void);
#endif /* __SYSTEM_CLOCK_IRC8M */
/* configure the system clock */
static void system_clock_config(void);
/*!
\brief software delay to prevent the impact of Vcore fluctuations
\param[in] time delay factor
\param[out] none
\retval none
*/
static void _soft_delay_(uint32_t time)
{
__IO uint32_t i;
for(i=0; i<time*10; i++){
}
}
/*!
\brief setup the micro-controller system, initialize the system
\param[in] none
\param[out] none
\retval none
*/
void SystemInit (void)
{
/* ===== DIAG: raw USART0 output — detect current clock for baudrate ===== */
/* Enable AFIO + GPIOA + USART0 clocks via raw register */
*((volatile uint32_t *)0x40021018U) |= (1U << 14) | (1U << 2) | (1U << 0);
/* PA9 = AF_PP, 50MHz (CTL=0b11, MD=0b11) -> CTL1 bit[4..7]=0b1011 */
{
volatile uint32_t ctl = *((volatile uint32_t *)0x40010804U);
ctl &= ~(0xFU << 4);
ctl |= (0xBU << 4); /* AF_PP 50MHz */
*((volatile uint32_t *)0x40010804U) = ctl;
}
/* Detect current system clock: if PLL is selected, assume 180MHz; otherwise IRC8M=8MHz.
* This handles both cold boot (IRC8M) and BOOT jump (PLL 180MHz). */
{
uint32_t scss = (*((volatile uint32_t *)0x40021000U) >> 2) & 0x3U; /* RCU_CFG0 SCSS bits */
uint32_t baud_div;
if (scss == 0x2U) { /* PLL selected as system clock -> 180MHz */
baud_div = 180000000U / 115200U; /* = 1562 */
} else { /* IRC8M or HXTAL -> 8MHz */
baud_div = 8000000U / 115200U; /* = 69 */
}
*((volatile uint32_t *)0x40013808U) = baud_div;
}
/* USART0 CTL0: TE + EN = bit3 + bit13 */
*((volatile uint32_t *)0x40013800U) = (1U << 3) | (1U << 13);
/* Send "APP" via USART0 DATA register */
*((volatile uint32_t *)0x40013804U) = 'A';
while ((*((volatile uint32_t *)0x40013800U) & (1U << 7)) == 0U) {}
*((volatile uint32_t *)0x40013804U) = 'P';
while ((*((volatile uint32_t *)0x40013800U) & (1U << 7)) == 0U) {}
*((volatile uint32_t *)0x40013804U) = 'P';
while ((*((volatile uint32_t *)0x40013800U) & (1U << 7)) == 0U) {}
*((volatile uint32_t *)0x40013804U) = '\r';
while ((*((volatile uint32_t *)0x40013800U) & (1U << 7)) == 0U) {}
*((volatile uint32_t *)0x40013804U) = '\n';
while ((*((volatile uint32_t *)0x40013800U) & (1U << 7)) == 0U) {}
/* ===== END DIAG ===== */
/* 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 IRC8MEN bit */
RCU_CTL |= RCU_CTL_IRC8MEN;
while(0U == (RCU_CTL & RCU_CTL_IRC8MSTB)){
}
if(((RCU_CFG0 & RCU_CFG0_SCSS) == RCU_SCSS_PLL)){
RCU_MODIFY(0x100);
}
RCU_CFG0 &= ~RCU_CFG0_SCS;
_soft_delay_(100);
#if (defined(GD32EPRT) || defined(GD32E50X_HD))
/* reset HXTALEN, CKMEN and PLLEN bits */
RCU_CTL &= ~(RCU_CTL_PLLEN | RCU_CTL_CKMEN | RCU_CTL_HXTALEN);
/* disable all interrupts */
RCU_INT = 0x009f0000U;
#elif (defined(GD32E50X_CL) || defined(GD32E508))
/* Reset HXTALEN, CKMEN, PLLEN, PLL1EN and PLL2EN bits */
RCU_CTL &= ~(RCU_CTL_PLLEN |RCU_CTL_PLL1EN | RCU_CTL_PLL2EN | RCU_CTL_CKMEN | RCU_CTL_HXTALEN);
/* disable all interrupts */
RCU_INT = 0x00ff0000U;
#endif /* GD32E50X_EPRT and GD32E50X_HD */
/* Reset CFG0 and CFG1 registers */
RCU_CFG0 = 0x00000000U;
RCU_CFG1 = 0x00000000U;
/* reset HXTALBPS bit */
RCU_CTL &= ~(RCU_CTL_HXTALBPS);
/* configure the system clock source, PLL Multiplier, AHB/APBx prescalers and Flash settings */
system_clock_config();
/* ===== DIAG: after PLL config, at 180MHz, send "CLK" ===== */
/* Re-enable USART0 at 180MHz: BAUD = 180000000/115200 = 1562.5 = 1563 */
*((volatile uint32_t *)0x40013808U) = 1563U;
*((volatile uint32_t *)0x40013800U) = (1U << 3) | (1U << 13);
*((volatile uint32_t *)0x40013804U) = 'C';
while ((*((volatile uint32_t *)0x40013800U) & (1U << 7)) == 0U) {}
*((volatile uint32_t *)0x40013804U) = 'L';
while ((*((volatile uint32_t *)0x40013800U) & (1U << 7)) == 0U) {}
*((volatile uint32_t *)0x40013804U) = 'K';
while ((*((volatile uint32_t *)0x40013800U) & (1U << 7)) == 0U) {}
*((volatile uint32_t *)0x40013804U) = '\r';
while ((*((volatile uint32_t *)0x40013800U) & (1U << 7)) == 0U) {}
*((volatile uint32_t *)0x40013804U) = '\n';
while ((*((volatile uint32_t *)0x40013800U) & (1U << 7)) == 0U) {}
/* ===== END DIAG ===== */
#ifdef VECT_TAB_SRAM
nvic_vector_table_set(NVIC_VECTTAB_RAM,VECT_TAB_OFFSET);
#else
nvic_vector_table_set(NVIC_VECTTAB_FLASH,VECT_TAB_OFFSET);
#endif
}
/*!
\brief configure the system clock
\param[in] none
\param[out] none
\retval none
*/
static void system_clock_config(void)
{
#ifdef __SYSTEM_CLOCK_IRC8M
system_clock_8m_irc8m();
#elif defined (__SYSTEM_CLOCK_72M_PLL_IRC8M)
system_clock_72m_irc8m();
#elif defined (__SYSTEM_CLOCK_120M_PLL_IRC8M)
system_clock_120m_irc8m();
#elif defined (__SYSTEM_CLOCK_168M_PLL_IRC8M)
system_clock_168m_irc8m();
#elif defined (__SYSTEM_CLOCK_180M_PLL_IRC8M)
system_clock_180m_irc8m();
#elif defined (__SYSTEM_CLOCK_HXTAL)
system_clock_hxtal();
#elif defined (__SYSTEM_CLOCK_72M_PLL_HXTAL)
system_clock_72m_hxtal();
#elif defined (__SYSTEM_CLOCK_120M_PLL_HXTAL)
system_clock_120m_hxtal();
#elif defined (__SYSTEM_CLOCK_168M_PLL_HXTAL)
system_clock_168m_hxtal();
#elif defined (__SYSTEM_CLOCK_180M_PLL_HXTAL)
system_clock_180m_hxtal();
#endif /* __SYSTEM_CLOCK_IRC8M */
}
#ifdef __SYSTEM_CLOCK_IRC8M
/*!
\brief configure the system clock to 8M by IRC8M
\param[in] none
\param[out] none
\retval none
*/
static void system_clock_8m_irc8m(void)
{
uint32_t timeout = 0U;
uint32_t stab_flag = 0U;
__IO uint32_t reg_temp;
/* enable IRC8M */
RCU_CTL |= RCU_CTL_IRC8MEN;
/* wait until IRC8M is stable or the startup time is longer than IRC8M_STARTUP_TIMEOUT */
do{
timeout++;
stab_flag = (RCU_CTL & RCU_CTL_IRC8MSTB);
}
while((0U == stab_flag) && (IRC8M_STARTUP_TIMEOUT != timeout));
/* if fail */
if(0U == (RCU_CTL & RCU_CTL_IRC8MSTB)){
while(1){
}
}
/* AHB = SYSCLK */
RCU_CFG0 |= RCU_AHB_CKSYS_DIV1;
/* APB2 = AHB/1 */
RCU_CFG0 |= RCU_APB2_CKAHB_DIV1;
/* APB1 = AHB/2 */
RCU_CFG0 |= RCU_APB1_CKAHB_DIV2;
reg_temp = RCU_CFG0;
/* select IRC8M as system clock */
reg_temp &= ~RCU_CFG0_SCS;
reg_temp |= RCU_CKSYSSRC_IRC8M;
RCU_CFG0 = reg_temp;
/* wait until IRC8M is selected as system clock */
while(RCU_SCSS_IRC8M != (RCU_CFG0 & RCU_CFG0_SCSS)){
}
}
#elif defined (__SYSTEM_CLOCK_72M_PLL_IRC8M)
/*!
\brief configure the system clock to 72M by PLL which selects IRC8M as its clock source
\param[in] none
\param[out] none
\retval none
*/
static void system_clock_72m_irc8m(void)
{
uint32_t timeout = 0U;
uint32_t stab_flag = 0U;
__IO uint32_t reg_temp;
/* enable IRC8M */
RCU_CTL |= RCU_CTL_IRC8MEN;
/* wait until IRC8M is stable or the startup time is longer than IRC8M_STARTUP_TIMEOUT */
do{
timeout++;
stab_flag = (RCU_CTL & RCU_CTL_IRC8MSTB);
}
while((0U == stab_flag) && (IRC8M_STARTUP_TIMEOUT != timeout));
/* if fail */
if(0U == (RCU_CTL & RCU_CTL_IRC8MSTB)){
while(1){
}
}
FMC_WS = (FMC_WS & (~FMC_WS_WSCNT)) | WS_WSCNT(1);
/* LDO output voltage high mode */
RCU_APB1EN |= RCU_APB1EN_PMUEN;
/* IRC8M is stable */
/* AHB = SYSCLK/4 */
RCU_CFG0 |= RCU_AHB_CKSYS_DIV4;
/* APB2 = AHB/1 */
RCU_CFG0 |= RCU_APB2_CKAHB_DIV1;
/* APB1 = AHB/2 */
RCU_CFG0 |= RCU_APB1_CKAHB_DIV2;
/* CK_PLL = (CK_IRC8M/2) * 18 = 72 MHz */
RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PLLMF_5);
RCU_CFG0 |= RCU_PLL_MUL18;
/* 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_CTL0 |= PMU_CTL0_HDEN;
while(0U == (PMU_CS0 & PMU_CS0_HDRF)){
}
/* select the high-drive mode */
PMU_CTL0 |= PMU_CTL0_HDS;
while(0U == (PMU_CS0 & PMU_CS0_HDSRF)){
}
reg_temp = RCU_CFG0;
/* select PLL as system clock */
reg_temp &= ~RCU_CFG0_SCS;
reg_temp |= RCU_CKSYSSRC_PLL;
RCU_CFG0 = reg_temp;
/* wait until PLL is selected as system clock */
while(RCU_SCSS_PLL != (RCU_CFG0 & RCU_CFG0_SCSS)){
}
RCU_MODIFY_UP(0x50);
}
#elif defined (__SYSTEM_CLOCK_120M_PLL_IRC8M)
/*!
\brief configure the system clock to 120M by PLL which selects IRC8M as its clock source
\param[in] none
\param[out] none
\retval none
*/
static void system_clock_120m_irc8m(void)
{
uint32_t timeout = 0U;
uint32_t stab_flag = 0U;
__IO uint32_t reg_temp;
/* enable IRC8M */
RCU_CTL |= RCU_CTL_IRC8MEN;
/* wait until IRC8M is stable or the startup time is longer than IRC8M_STARTUP_TIMEOUT */
do{
timeout++;
stab_flag = (RCU_CTL & RCU_CTL_IRC8MSTB);
}while((0U == stab_flag) && (IRC8M_STARTUP_TIMEOUT != timeout));
/* if fail */
if(0U == (RCU_CTL & RCU_CTL_IRC8MSTB)){
while(1){
}
}
FMC_WS = (FMC_WS & (~FMC_WS_WSCNT)) | WS_WSCNT(3);
/* LDO output voltage high mode */
RCU_APB1EN |= RCU_APB1EN_PMUEN;
/* IRC8M is stable */
/* AHB = SYSCLK/4 */
RCU_CFG0 |= RCU_AHB_CKSYS_DIV4;
/* APB2 = AHB/1 */
RCU_CFG0 |= RCU_APB2_CKAHB_DIV1;
/* APB1 = AHB/2 */
RCU_CFG0 |= RCU_APB1_CKAHB_DIV2;
/* CK_PLL = (CK_IRC8M/2) * 30 = 120 MHz */
RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PLLMF_5);
RCU_CFG0 |= RCU_PLL_MUL30;
/* 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_CTL0 |= PMU_CTL0_HDEN;
while(0U == (PMU_CS0 & PMU_CS0_HDRF)){
}
/* select the high-drive mode */
PMU_CTL0 |= PMU_CTL0_HDS;
while(0U == (PMU_CS0 & PMU_CS0_HDSRF)){
}
reg_temp = RCU_CFG0;
/* select PLL as system clock */
reg_temp &= ~RCU_CFG0_SCS;
reg_temp |= RCU_CKSYSSRC_PLL;
RCU_CFG0 = reg_temp;
/* wait until PLL is selected as system clock */
while(RCU_SCSS_PLL != (RCU_CFG0 & RCU_CFG0_SCSS)){
}
RCU_MODIFY_UP(0x50);
}
#elif defined (__SYSTEM_CLOCK_168M_PLL_IRC8M)
/*!
\brief configure the system clock to 168M by PLL which selects IRC8M as its clock source
\param[in] none
\param[out] none
\retval none
*/
static void system_clock_168m_irc8m(void)
{
uint32_t timeout = 0U;
uint32_t stab_flag = 0U;
__IO uint32_t reg_temp;
/* enable IRC8M */
RCU_CTL |= RCU_CTL_IRC8MEN;
/* wait until IRC8M is stable or the startup time is longer than IRC8M_STARTUP_TIMEOUT */
do{
timeout++;
stab_flag = (RCU_CTL & RCU_CTL_IRC8MSTB);
}while((0U == stab_flag) && (IRC8M_STARTUP_TIMEOUT != timeout));
/* if fail */
if(0U == (RCU_CTL & RCU_CTL_IRC8MSTB)){
while(1){
}
}
FMC_WS = (FMC_WS & (~FMC_WS_WSCNT)) | WS_WSCNT(4);
/* LDO output voltage high mode */
RCU_APB1EN |= RCU_APB1EN_PMUEN;
/* IRC8M is stable */
/* AHB = SYSCLK/4 */
RCU_CFG0 |= RCU_AHB_CKSYS_DIV4;
/* APB2 = AHB/1 */
RCU_CFG0 |= RCU_APB2_CKAHB_DIV1;
/* APB1 = AHB/2 */
RCU_CFG0 |= RCU_APB1_CKAHB_DIV2;
/* CK_PLL = (CK_IRC8M/2) * 42 = 168 MHz */
RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PLLMF_5);
RCU_CFG0 |= RCU_PLL_MUL42;
/* 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_CTL0 |= PMU_CTL0_HDEN;
while(0U == (PMU_CS0 & PMU_CS0_HDRF)){
}
/* select the high-drive mode */
PMU_CTL0 |= PMU_CTL0_HDS;
while(0U == (PMU_CS0 & PMU_CS0_HDSRF)){
}
reg_temp = RCU_CFG0;
/* select PLL as system clock */
reg_temp &= ~RCU_CFG0_SCS;
reg_temp |= RCU_CKSYSSRC_PLL;
RCU_CFG0 = reg_temp;
/* wait until PLL is selected as system clock */
while(RCU_SCSS_PLL != (RCU_CFG0 & RCU_CFG0_SCSS)){
}
RCU_MODIFY_UP(0x50);
}
#elif defined (__SYSTEM_CLOCK_180M_PLL_IRC8M)
/*!
\brief configure the system clock to 180M by PLL which selects IRC8M as its clock source
\param[in] none
\param[out] none
\retval none
*/
static void system_clock_180m_irc8m(void)
{
uint32_t timeout = 0U;
uint32_t stab_flag = 0U;
__IO uint32_t reg_temp;
/* enable IRC8M */
RCU_CTL |= RCU_CTL_IRC8MEN;
/* wait until IRC8M is stable or the startup time is longer than IRC8M_STARTUP_TIMEOUT */
do{
timeout++;
stab_flag = (RCU_CTL & RCU_CTL_IRC8MSTB);
}while((0U == stab_flag) && (IRC8M_STARTUP_TIMEOUT != timeout));
/* if fail */
if(0U == (RCU_CTL & RCU_CTL_IRC8MSTB)){
while(1){
}
}
FMC_WS = (FMC_WS & (~FMC_WS_WSCNT)) | WS_WSCNT(4);
/* LDO output voltage high mode */
RCU_APB1EN |= RCU_APB1EN_PMUEN;
/* IRC8M is stable */
/* AHB = SYSCLK/4 */
RCU_CFG0 |= RCU_AHB_CKSYS_DIV4;
/* APB2 = AHB/1 */
RCU_CFG0 |= RCU_APB2_CKAHB_DIV1;
/* APB1 = AHB/2 */
RCU_CFG0 |= RCU_APB1_CKAHB_DIV2;
/* CK_PLL = (CK_IRC8M/2) * 45 = 180 MHz */
RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PLLMF_5);
RCU_CFG0 |= RCU_PLL_MUL45;
/* 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_CTL0 |= PMU_CTL0_HDEN;
while(0U == (PMU_CS0 & PMU_CS0_HDRF)){
}
/* select the high-drive mode */
PMU_CTL0 |= PMU_CTL0_HDS;
while(0U == (PMU_CS0 & PMU_CS0_HDSRF)){
}
reg_temp = RCU_CFG0;
/* select PLL as system clock */
reg_temp &= ~RCU_CFG0_SCS;
reg_temp |= RCU_CKSYSSRC_PLL;
RCU_CFG0 = reg_temp;
/* wait until PLL is selected as system clock */
while(RCU_SCSS_PLL != (RCU_CFG0 & RCU_CFG0_SCSS)){
}
RCU_MODIFY_UP(0x50);
}
#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;
__IO uint32_t reg_temp;
/* enable HXTAL */
RCU_CTL |= RCU_CTL_HXTALEN;
HXTALSTB_DELAY
/* 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)){
/* HXTAL failed: output diagnostic via USART0 at IRC8M.
* 修正(1.5.34):原段把 CTL0 写到 STAT0 偏移(0x40013800)且漏开 USART0EN(APB2EN bit14),
* 该诊断从未真正发出;正确布局:CTL0 @ USART0+0x0C,APB2EN bit14|bit2|bit0。 */
*((volatile uint32_t *)0x40021018U) |= (1U << 14) | (1U << 2) | (1U << 0);
{ volatile uint32_t _ctl = *((volatile uint32_t *)0x40010804U);
_ctl &= ~(0xFU << 4); _ctl |= (0xBU << 4);
*((volatile uint32_t *)0x40010804U) = _ctl; }
*((volatile uint32_t *)0x40013808U) = 69U; /* 8MHz/115200 */
*((volatile uint32_t *)0x4001380CU) = (1U << 3) | (1U << 13);
{ const char *_msg = "HXTAL FAIL\r\n";
for(int i=0; _msg[i]; i++){
*((volatile uint32_t *)0x40013804U) = _msg[i];
while((*((volatile uint32_t *)0x40013800U) & (1U << 7)) == 0U) {} } }
while(1){ }
}
/* AHB = SYSCLK */
RCU_CFG0 |= RCU_AHB_CKSYS_DIV1;
/* APB2 = AHB/1 */
RCU_CFG0 |= RCU_APB2_CKAHB_DIV1;
/* APB1 = AHB/2 */
RCU_CFG0 |= RCU_APB1_CKAHB_DIV2;
reg_temp = RCU_CFG0;
/* select HXTAL as system clock */
reg_temp &= ~RCU_CFG0_SCS;
reg_temp |= RCU_CKSYSSRC_HXTAL;
RCU_CFG0 = reg_temp;
/* wait until HXTAL is selected as system clock */
while(RCU_SCSS_HXTAL != (RCU_CFG0 & RCU_CFG0_SCSS)){
}
}
#elif defined (__SYSTEM_CLOCK_72M_PLL_HXTAL)
/*!
\brief configure the system clock to 72M by PLL which selects HXTAL as its clock source
\param[in] none
\param[out] none
\retval none
*/
static void system_clock_72m_hxtal(void)
{
uint32_t timeout = 0U;
uint32_t stab_flag = 0U;
__IO uint32_t reg_temp;
/* enable HXTAL */
RCU_CTL |= RCU_CTL_HXTALEN;
HXTALSTB_DELAY
/* 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)){
/* HXTAL failed: output diagnostic via USART0 at IRC8M.
* 修正(1.5.34):原段把 CTL0 写到 STAT0 偏移(0x40013800)且漏开 USART0EN(APB2EN bit14),
* 该诊断从未真正发出;正确布局:CTL0 @ USART0+0x0C,APB2EN bit14|bit2|bit0。 */
*((volatile uint32_t *)0x40021018U) |= (1U << 14) | (1U << 2) | (1U << 0);
{ volatile uint32_t _ctl = *((volatile uint32_t *)0x40010804U);
_ctl &= ~(0xFU << 4); _ctl |= (0xBU << 4);
*((volatile uint32_t *)0x40010804U) = _ctl; }
*((volatile uint32_t *)0x40013808U) = 69U; /* 8MHz/115200 */
*((volatile uint32_t *)0x4001380CU) = (1U << 3) | (1U << 13);
{ const char *_msg = "HXTAL FAIL\r\n";
for(int i=0; _msg[i]; i++){
*((volatile uint32_t *)0x40013804U) = _msg[i];
while((*((volatile uint32_t *)0x40013800U) & (1U << 7)) == 0U) {} } }
while(1){ }
}
FMC_WS = (FMC_WS & (~FMC_WS_WSCNT)) | WS_WSCNT(1);
RCU_APB1EN |= RCU_APB1EN_PMUEN;
/* HXTAL is stable */
/* AHB = SYSCLK/4 */
RCU_CFG0 |= RCU_AHB_CKSYS_DIV4;
/* APB2 = AHB/1 */
RCU_CFG0 |= RCU_APB2_CKAHB_DIV1;
/* APB1 = AHB/2 */
RCU_CFG0 |= RCU_APB1_CKAHB_DIV2;
#if defined(GD32E50X_HD)
/* select HXTAL/2 as clock source */
RCU_CFG0 &= ~(RCU_CFG0_PLLSEL | RCU_CFG0_PREDV0);
RCU_CFG0 |= (RCU_PLLSRC_HXTAL_IRC48M | RCU_CFG0_PREDV0);
/* CK_PLL = (CK_HXTAL/2) * 18 = 72 MHz */
RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PLLMF_5);
RCU_CFG0 |= RCU_PLL_MUL18;
#elif (defined(GD32E50X_CL) || defined(GD32E508))
/* CK_PLL = (CK_PREDIV0) * 18 = 72 MHz */
RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PLLMF_5);
RCU_CFG0 |= (RCU_PLLSRC_HXTAL_IRC48M | RCU_PLL_MUL18);
/* CK_PREDIV0 = (CK_HXTAL)/5 *8 /10 = 4 MHz */
RCU_CFG1 &= ~(RCU_CFG1_PLLPRESEL | RCU_CFG1_PREDV0SEL | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV1 | RCU_CFG1_PREDV0);
RCU_CFG1 |= (RCU_PLLPRESRC_HXTAL | RCU_PREDV0SRC_CKPLL1 | RCU_PLL1_MUL8 | RCU_PREDV1_DIV5 | RCU_PREDV0_DIV10);
/* enable PLL1 */
RCU_CTL |= RCU_CTL_PLL1EN;
/* wait till PLL1 is ready */
while((RCU_CTL & RCU_CTL_PLL1STB) == 0U){
}
#elif defined(GD32EPRT)
/* CK_PLL = (CK_PREDIV0) * 18 = 72 MHz */
RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PLLMF_5);
RCU_CFG0 |= (RCU_PLLSRC_HXTAL_IRC48M | RCU_PLL_MUL18);
/* CK_PREDIV0 = (CK_HXTAL)/2 *8 /8 = 4 MHz */
RCU_CFG1 &= ~(RCU_CFG1_PLLPRESEL | RCU_CFG1_PREDV0SEL | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV1 | RCU_CFG1_PREDV0);
RCU_CFG1 |= (RCU_PLLPRESRC_HXTAL | RCU_PREDV0SRC_CKPLL1 | RCU_PLL1_MUL8 | RCU_PREDV1_DIV2 | RCU_PREDV0_DIV8);
/* enable PLL1 */
RCU_CTL |= RCU_CTL_PLL1EN;
/* wait till PLL1 is ready */
while((RCU_CTL & RCU_CTL_PLL1STB) == 0U){
}
#endif /* GD32E50X_HD */
/* 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 180 MHz */
PMU_CTL0 |= PMU_CTL0_HDEN;
while(0U == (PMU_CS0 & PMU_CS0_HDRF)){
}
/* select the high-drive mode */
PMU_CTL0 |= PMU_CTL0_HDS;
while(0U == (PMU_CS0 & PMU_CS0_HDSRF)){
}
reg_temp = RCU_CFG0;
/* select PLL as system clock */
reg_temp &= ~RCU_CFG0_SCS;
reg_temp |= RCU_CKSYSSRC_PLL;
RCU_CFG0 = reg_temp;
/* wait until PLL is selected as system clock */
while(RCU_SCSS_PLL != (RCU_CFG0 & RCU_CFG0_SCSS)){
}
RCU_MODIFY_UP(0x50);
}
#elif defined (__SYSTEM_CLOCK_120M_PLL_HXTAL)
/*!
\brief configure the system clock to 72M by PLL which selects HXTAL as its clock source
\param[in] none
\param[out] none
\retval none
*/
static void system_clock_120m_hxtal(void)
{
uint32_t timeout = 0U;
uint32_t stab_flag = 0U;
__IO uint32_t reg_temp;
/* enable HXTAL */
RCU_CTL |= RCU_CTL_HXTALEN;
HXTALSTB_DELAY
/* 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)){
/* HXTAL failed: output diagnostic via USART0 at IRC8M.
* 修正(1.5.34):原段把 CTL0 写到 STAT0 偏移(0x40013800)且漏开 USART0EN(APB2EN bit14),
* 该诊断从未真正发出;正确布局:CTL0 @ USART0+0x0C,APB2EN bit14|bit2|bit0。 */
*((volatile uint32_t *)0x40021018U) |= (1U << 14) | (1U << 2) | (1U << 0);
{ volatile uint32_t _ctl = *((volatile uint32_t *)0x40010804U);
_ctl &= ~(0xFU << 4); _ctl |= (0xBU << 4);
*((volatile uint32_t *)0x40010804U) = _ctl; }
*((volatile uint32_t *)0x40013808U) = 69U; /* 8MHz/115200 */
*((volatile uint32_t *)0x4001380CU) = (1U << 3) | (1U << 13);
{ const char *_msg = "HXTAL FAIL\r\n";
for(int i=0; _msg[i]; i++){
*((volatile uint32_t *)0x40013804U) = _msg[i];
while((*((volatile uint32_t *)0x40013800U) & (1U << 7)) == 0U) {} } }
while(1){ }
}
FMC_WS = (FMC_WS & (~FMC_WS_WSCNT)) | WS_WSCNT(3);
RCU_APB1EN |= RCU_APB1EN_PMUEN;
/* HXTAL is stable */
/* AHB = SYSCLK/2 (60 MHz) */
RCU_CFG0 |= RCU_AHB_CKSYS_DIV2;
/* APB2 = AHB/1 (60 MHz) */
RCU_CFG0 |= RCU_APB2_CKAHB_DIV1;
/* APB1 = AHB/2 (30 MHz) */
RCU_CFG0 |= RCU_APB1_CKAHB_DIV2;
#if defined(GD32E50X_HD)
/* select HXTAL/2 as clock source */
RCU_CFG0 &= ~(RCU_CFG0_PLLSEL | RCU_CFG0_PREDV0);
RCU_CFG0 |= (RCU_PLLSRC_HXTAL_IRC48M | RCU_CFG0_PREDV0);
/* CK_PLL = (CK_HXTAL/2) * 30 = 120 MHz */
RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PLLMF_5);
RCU_CFG0 |= RCU_PLL_MUL30;
#elif (defined(GD32E50X_CL) || defined(GD32E508))
/* CK_PLL = (CK_PREDIV0) * 30 = 120 MHz */
RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PLLMF_5);
RCU_CFG0 |= (RCU_PLLSRC_HXTAL_IRC48M | RCU_PLL_MUL30);
/* CK_PREDIV0 = (CK_HXTAL)/2 *8 /8 = 4 MHz */
RCU_CFG1 &= ~(RCU_CFG1_PLLPRESEL | RCU_CFG1_PREDV0SEL | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV1 | RCU_CFG1_PREDV0);
RCU_CFG1 |= (RCU_PLLPRESRC_HXTAL | RCU_PREDV0SRC_CKPLL1 | RCU_PLL1_MUL8 | RCU_PREDV1_DIV2 | RCU_PREDV0_DIV8);
/* enable PLL1 */
RCU_CTL |= RCU_CTL_PLL1EN;
/* wait till PLL1 is ready */
while((RCU_CTL & RCU_CTL_PLL1STB) == 0U){
}
#elif defined(GD32EPRT)
/* CK_PLL = (CK_PREDIV0) * 30 = 120 MHz */
RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PLLMF_5);
RCU_CFG0 |= (RCU_PLLSRC_HXTAL_IRC48M | RCU_PLL_MUL30);
/* CK_PREDIV0 = (CK_HXTAL)/2 *8 /8 = 4 MHz */
RCU_CFG1 &= ~(RCU_CFG1_PLLPRESEL | RCU_CFG1_PREDV0SEL | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV1 | RCU_CFG1_PREDV0);
RCU_CFG1 |= (RCU_PLLPRESRC_HXTAL | RCU_PREDV0SRC_CKPLL1 | RCU_PLL1_MUL8 | RCU_PREDV1_DIV2 | RCU_PREDV0_DIV8);
/* enable PLL1 */
RCU_CTL |= RCU_CTL_PLL1EN;
/* wait till PLL1 is ready */
while((RCU_CTL & RCU_CTL_PLL1STB) == 0U){
}
#endif /* GD32F50X_HD */
/* 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 180 MHz */
PMU_CTL0 |= PMU_CTL0_HDEN;
while(0U == (PMU_CS0 & PMU_CS0_HDRF)){
}
/* select the high-drive mode */
PMU_CTL0 |= PMU_CTL0_HDS;
while(0U == (PMU_CS0 & PMU_CS0_HDSRF)){
}
reg_temp = RCU_CFG0;
/* select PLL as system clock */
reg_temp &= ~RCU_CFG0_SCS;
reg_temp |= RCU_CKSYSSRC_PLL;
RCU_CFG0 = reg_temp;
/* wait until PLL is selected as system clock */
while(RCU_SCSS_PLL != (RCU_CFG0 & RCU_CFG0_SCSS)){
}
RCU_MODIFY_UP(0x50);
}
#elif defined (__SYSTEM_CLOCK_168M_PLL_HXTAL)
/*!
\brief configure the system clock to 108M by PLL which selects HXTAL as its clock source
\param[in] none
\param[out] none
\retval none
*/
static void system_clock_168m_hxtal(void)
{
uint32_t timeout = 0U;
uint32_t stab_flag = 0U;
__IO uint32_t reg_temp;
/* enable HXTAL */
RCU_CTL |= RCU_CTL_HXTALEN;
HXTALSTB_DELAY
/* 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)){
/* HXTAL failed: output diagnostic via USART0 at IRC8M.
* 修正(1.5.34):原段把 CTL0 写到 STAT0 偏移(0x40013800)且漏开 USART0EN(APB2EN bit14),
* 该诊断从未真正发出;正确布局:CTL0 @ USART0+0x0C,APB2EN bit14|bit2|bit0。 */
*((volatile uint32_t *)0x40021018U) |= (1U << 14) | (1U << 2) | (1U << 0);
{ volatile uint32_t _ctl = *((volatile uint32_t *)0x40010804U);
_ctl &= ~(0xFU << 4); _ctl |= (0xBU << 4);
*((volatile uint32_t *)0x40010804U) = _ctl; }
*((volatile uint32_t *)0x40013808U) = 69U; /* 8MHz/115200 */
*((volatile uint32_t *)0x4001380CU) = (1U << 3) | (1U << 13);
{ const char *_msg = "HXTAL FAIL\r\n";
for(int i=0; _msg[i]; i++){
*((volatile uint32_t *)0x40013804U) = _msg[i];
while((*((volatile uint32_t *)0x40013800U) & (1U << 7)) == 0U) {} } }
while(1){ }
}
FMC_WS = (FMC_WS & (~FMC_WS_WSCNT)) | WS_WSCNT(4);
RCU_APB1EN |= RCU_APB1EN_PMUEN;
/* HXTAL is stable */
/* AHB = SYSCLK/4 */
RCU_CFG0 |= RCU_AHB_CKSYS_DIV4;
/* APB2 = AHB/1 */
RCU_CFG0 |= RCU_APB2_CKAHB_DIV1;
/* APB1 = AHB/2 */
RCU_CFG0 |= RCU_APB1_CKAHB_DIV2;
#if defined(GD32E50X_HD)
/* select HXTAL/2 as clock source */
RCU_CFG0 &= ~(RCU_CFG0_PLLSEL | RCU_CFG0_PREDV0);
RCU_CFG0 |= (RCU_PLLSRC_HXTAL_IRC48M | RCU_CFG0_PREDV0);
/* CK_PLL = (CK_HXTAL/2) * 42 = 168 MHz */
RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PLLMF_5);
RCU_CFG0 |= RCU_PLL_MUL42;
#elif (defined(GD32E50X_CL) || defined(GD32E508))
/* CK_PLL = (CK_PREDIV0) * 42 = 168 MHz */
RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PLLMF_5);
RCU_CFG0 |= (RCU_PLLSRC_HXTAL_IRC48M | RCU_PLL_MUL42);
/* CK_PREDIV0 = (CK_HXTAL)/5 *8 /10 = 4 MHz */
RCU_CFG1 &= ~(RCU_CFG1_PLLPRESEL | RCU_CFG1_PREDV0SEL | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV1 | RCU_CFG1_PREDV0);
RCU_CFG1 |= (RCU_PLLPRESRC_HXTAL | RCU_PREDV0SRC_CKPLL1 | RCU_PLL1_MUL8 | RCU_PREDV1_DIV5 | RCU_PREDV0_DIV10);
/* enable PLL1 */
RCU_CTL |= RCU_CTL_PLL1EN;
/* wait till PLL1 is ready */
while((RCU_CTL & RCU_CTL_PLL1STB) == 0U){
}
#elif defined(GD32EPRT)
/* CK_PLL = (CK_PREDIV0) * 42 = 168 MHz */
RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PLLMF_5);
RCU_CFG0 |= (RCU_PLLSRC_HXTAL_IRC48M | RCU_PLL_MUL42);
/* CK_PREDIV0 = (CK_HXTAL)/2 *8 /8 = 4 MHz */
RCU_CFG1 &= ~(RCU_CFG1_PLLPRESEL | RCU_CFG1_PREDV0SEL | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV1 | RCU_CFG1_PREDV0);
RCU_CFG1 |= (RCU_PLLPRESRC_HXTAL | RCU_PREDV0SRC_CKPLL1 | RCU_PLL1_MUL8 | RCU_PREDV1_DIV2 | RCU_PREDV0_DIV8);
/* enable PLL1 */
RCU_CTL |= RCU_CTL_PLL1EN;
/* wait till PLL1 is ready */
while((RCU_CTL & RCU_CTL_PLL1STB) == 0U){
}
#endif /* GD32F50X_HD */
/* 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 180 MHz */
PMU_CTL0 |= PMU_CTL0_HDEN;
while(0U == (PMU_CS0 & PMU_CS0_HDRF)){
}
/* select the high-drive mode */
PMU_CTL0 |= PMU_CTL0_HDS;
while(0U == (PMU_CS0 & PMU_CS0_HDSRF)){
}
reg_temp = RCU_CFG0;
/* select PLL as system clock */
reg_temp &= ~RCU_CFG0_SCS;
reg_temp |= RCU_CKSYSSRC_PLL;
RCU_CFG0 = reg_temp;
/* wait until PLL is selected as system clock */
while(RCU_SCSS_PLL != (RCU_CFG0 & RCU_CFG0_SCSS)){
}
RCU_MODIFY_UP(0x50);
}
#elif defined (__SYSTEM_CLOCK_180M_PLL_HXTAL)
/*!
\brief configure the system clock to 180M by PLL which selects HXTAL as its clock source
\param[in] none
\param[out] none
\retval none
*/
static void system_clock_180m_hxtal(void)
{
uint32_t timeout = 0U;
uint32_t stab_flag = 0U;
__IO uint32_t reg_temp;
/* enable HXTAL */
RCU_CTL |= RCU_CTL_HXTALEN;
HXTALSTB_DELAY
/* 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)){
/* HXTAL failed: output diagnostic via USART0 at IRC8M.
* 修正(1.5.34):原段把 CTL0 写到 STAT0 偏移(0x40013800)且漏开 USART0EN(APB2EN bit14),
* 该诊断从未真正发出;正确布局:CTL0 @ USART0+0x0C,APB2EN bit14|bit2|bit0。 */
*((volatile uint32_t *)0x40021018U) |= (1U << 14) | (1U << 2) | (1U << 0);
{ volatile uint32_t _ctl = *((volatile uint32_t *)0x40010804U);
_ctl &= ~(0xFU << 4); _ctl |= (0xBU << 4);
*((volatile uint32_t *)0x40010804U) = _ctl; }
*((volatile uint32_t *)0x40013808U) = 69U; /* 8MHz/115200 */
*((volatile uint32_t *)0x4001380CU) = (1U << 3) | (1U << 13);
{ const char *_msg = "HXTAL FAIL\r\n";
for(int i=0; _msg[i]; i++){
*((volatile uint32_t *)0x40013804U) = _msg[i];
while((*((volatile uint32_t *)0x40013800U) & (1U << 7)) == 0U) {} } }
while(1){ }
}
FMC_WS = (FMC_WS & (~FMC_WS_WSCNT)) | WS_WSCNT(4);
RCU_APB1EN |= RCU_APB1EN_PMUEN;
/* HXTAL is stable */
/* AHB = SYSCLK/4 */
RCU_CFG0 |= RCU_AHB_CKSYS_DIV4;
/* APB2 = AHB/1 */
RCU_CFG0 |= RCU_APB2_CKAHB_DIV1;
/* APB1 = AHB/2 */
RCU_CFG0 |= RCU_APB1_CKAHB_DIV2;
#if defined(GD32E50X_HD)
/* select HXTAL/2 as clock source */
RCU_CFG0 &= ~(RCU_CFG0_PLLSEL | RCU_CFG0_PREDV0);
RCU_CFG0 |= (RCU_PLLSRC_HXTAL_IRC48M | RCU_CFG0_PREDV0);
/* CK_PLL = (CK_HXTAL/2) * 45 = 180 MHz */
RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PLLMF_5);
RCU_CFG0 |= RCU_PLL_MUL45;
#elif defined(GD32E508)
/* GD32E508 + 8MHz HXTAL:
CK_PREDIV0 = (CK_HXTAL)/2 *8 /8 = 4 MHz
CK_PLL = CK_PREDIV0 * 45 = 180 MHz */
RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PLLMF_5);
RCU_CFG0 |= (RCU_PLLSRC_HXTAL_IRC48M | RCU_PLL_MUL45);
RCU_CFG1 &= ~(RCU_CFG1_PLLPRESEL | RCU_CFG1_PREDV0SEL | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV1 | RCU_CFG1_PREDV0);
RCU_CFG1 |= (RCU_PLLPRESRC_HXTAL | RCU_PREDV0SRC_CKPLL1 | RCU_PLL1_MUL8 | RCU_PREDV1_DIV2 | RCU_PREDV0_DIV8);
/* enable PLL1 */
RCU_CTL |= RCU_CTL_PLL1EN;
/* wait till PLL1 is ready */
while((RCU_CTL & RCU_CTL_PLL1STB) == 0U){
}
#elif defined(GD32E50X_CL)
/* CK_PLL = (CK_PREDIV0) * 45 = 180 MHz */
RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PLLMF_5);
RCU_CFG0 |= (RCU_PLLSRC_HXTAL_IRC48M | RCU_PLL_MUL45);
/* CK_PREDIV0 = (CK_HXTAL)/5 *8 /10 = 4 MHz */
RCU_CFG1 &= ~(RCU_CFG1_PLLPRESEL | RCU_CFG1_PREDV0SEL | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV1 | RCU_CFG1_PREDV0);
RCU_CFG1 |= (RCU_PLLPRESRC_HXTAL | RCU_PREDV0SRC_CKPLL1 | RCU_PLL1_MUL8 | RCU_PREDV1_DIV5 | RCU_PREDV0_DIV10) ;
/* enable PLL1 */
RCU_CTL |= RCU_CTL_PLL1EN;
/* wait till PLL1 is ready */
while((RCU_CTL & RCU_CTL_PLL1STB) == 0U){
}
#elif defined(GD32EPRT)
/* CK_PLL = (CK_PREDIV0) * 45 = 180 MHz */
RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PLLMF_5);
RCU_CFG0 |= (RCU_PLLSRC_HXTAL_IRC48M | RCU_PLL_MUL45);
/* CK_PREDIV0 = (CK_HXTAL)/2 *8 /8 = 4 MHz */
RCU_CFG1 &= ~(RCU_CFG1_PLLPRESEL | RCU_CFG1_PREDV0SEL | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV1 | RCU_CFG1_PREDV0);
RCU_CFG1 |= (RCU_PLLPRESRC_HXTAL | RCU_PREDV0SRC_CKPLL1 | RCU_PLL1_MUL8 | RCU_PREDV1_DIV2 | RCU_PREDV0_DIV8);
/* enable PLL1 */
RCU_CTL |= RCU_CTL_PLL1EN;
/* wait till PLL1 is ready */
while((RCU_CTL & RCU_CTL_PLL1STB) == 0U){
}
#endif /* GD32F50X_HD */
/* 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 180 MHz */
PMU_CTL0 |= PMU_CTL0_HDEN;
while(0U == (PMU_CS0 & PMU_CS0_HDRF)){
}
/* select the high-drive mode */
PMU_CTL0 |= PMU_CTL0_HDS;
while(0U == (PMU_CS0 & PMU_CS0_HDSRF)){
}
reg_temp = RCU_CFG0;
/* select PLL as system clock */
reg_temp &= ~RCU_CFG0_SCS;
reg_temp |= RCU_CKSYSSRC_PLL;
RCU_CFG0 = reg_temp;
/* wait until PLL is selected as system clock */
while(RCU_SCSS_PLL != (RCU_CFG0 & RCU_CFG0_SCSS)){
}
RCU_MODIFY_UP(0x50);
}
#endif /* __SYSTEM_CLOCK_IRC8M */
/*!
\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 pllsel, pllpresel, predv0sel, pllmf, ck_src, idx, clk_exp;
#if (defined(GD32E50X_CL) || defined(GD32EPRT) || defined(GD32E508))
uint32_t predv0, predv1, pll1mf;
#endif /* GD32E50X_CL and GD32EPRT*/
/* exponent of AHB, APB1 and APB2 clock divider */
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){
/* IRC8M is selected as CK_SYS */
case SEL_IRC8M:
SystemCoreClock = IRC8M_VALUE;
break;
/* HXTAL is selected as CK_SYS */
case SEL_HXTAL:
SystemCoreClock = HXTAL_VALUE;
break;
/* PLL is selected as CK_SYS */
case SEL_PLL:
/* PLL clock source selection, HXTAL, IRC48M or IRC8M/2 */
pllsel = (RCU_CFG0 & RCU_CFG0_PLLSEL);
if(RCU_PLLSRC_HXTAL_IRC48M == pllsel) {
/* PLL clock source is HXTAL or IRC48M */
pllpresel = (RCU_CFG1 & RCU_CFG1_PLLPRESEL);
if(RCU_PLLPRESRC_HXTAL == pllpresel){
/* PLL clock source is HXTAL */
ck_src = HXTAL_VALUE;
}else{
/* PLL clock source is IRC48 */
ck_src = IRC48M_VALUE;
}
#if defined(GD32E50X_HD)
predv0sel = (RCU_CFG0 & RCU_CFG0_PREDV0);
/* PREDV0 input source clock divided by 2 */
if(RCU_CFG0_PREDV0 == predv0sel){
ck_src = ck_src/2U;
}
#elif (defined(GD32E50X_CL) || defined(GD32EPRT) || defined(GD32E508))
predv0sel = (RCU_CFG1 & RCU_CFG1_PREDV0SEL);
/* source clock use PLL1 */
if(RCU_PREDV0SRC_CKPLL1 == predv0sel){
predv1 = ((RCU_CFG1 & RCU_CFG1_PREDV1) >> ((uint32_t)4U)) + 1U;
pll1mf = (uint32_t)((RCU_CFG1 & RCU_CFG1_PLL1MF) >> ((uint32_t)8U)) + 2U;
if(17U == pll1mf){
pll1mf = 20U;
}
ck_src = (ck_src/predv1)*pll1mf;
}
predv0 = (RCU_CFG1 & RCU_CFG1_PREDV0) + 1U;
ck_src /= predv0;
#endif /* GD32E50X_HD */
}else{
/* PLL clock source is IRC8M/2 */
ck_src = IRC8M_VALUE/2U;
}
/* PLL multiplication factor */
pllmf = GET_BITS(RCU_CFG0, 18, 21);
if((RCU_CFG0 & RCU_CFG0_PLLMF_4)){
pllmf |= 0x10U;
}
if((RCU_CFG0 & RCU_CFG0_PLLMF_5)){
pllmf |= 0x20U;
}
if(pllmf < 15U){
pllmf += 2U;
}else if((pllmf >= 15U) && (pllmf <= 64U)){
pllmf += 1U;
}else{
}
SystemCoreClock = ck_src*pllmf;
#if (defined(GD32E50X_CL) || defined(GD32EPRT) || defined(GD32E508))
if(15U == pllmf){
SystemCoreClock = ck_src*6U + ck_src/2U;
}
#endif /* GD32E50X_CL and GD32EPRT and GD32E508 */
break;
/* IRC8M is selected as CK_SYS */
default:
SystemCoreClock = IRC8M_VALUE;
break;
}
/* calculate AHB clock frequency */
idx = GET_BITS(RCU_CFG0, 4, 7);
clk_exp = ahb_exp[idx];
SystemCoreClock >>= clk_exp;
}
#ifdef __FIRMWARE_VERSION_DEFINE
/*!
\brief get firmware version
\param[in] none
\param[out] none
\retval firmware version
*/
uint32_t gd32e50x_firmware_version_get(void)
{
return __GD32E50X_STDPERIPH_VERSION;
}
#endif /* __FIRMWARE_VERSION_DEFINE */