[feat] update clock driver

This commit is contained in:
zhji 2025-05-11 22:30:39 +08:00
parent d5f776d614
commit 2d11df7c38
7 changed files with 415 additions and 415 deletions

View File

@ -52,12 +52,11 @@ void SystemCoreClockUpdate (void)
void __attribute__((constructor)) SystemInit (void)
{
system_regulator_set(SYSTEM_REGULATOR_VOLTAGE_1P30V);
clock_ref_set_src(CLOCK_REF_SRC_XOSC_GLITCHLESS);
clock_sys_set_src(CLOCK_SYS_SRC_REF_GLITCHLESS);
clock_ref_set(CLOCK_REF_SRC_XOSC_GLITCHLESS, 1);
clock_sys_set(CLOCK_SYS_SRC_REF_GLITCHLESS, 1);
/* refdiv >= 5MHz, VCO=[750:1600]MHz, fbdiv=[16:320], postdiv=[1:7] */
clock_pll_init(CLOCK_PLL_SYSPLL, 1, 100, 3, 2); /* 12MHz / 1 * 100 / 3 / 2 = 200MHz */
clock_sys_set_div(1 << 8); /* 200MHz / 1 = 200MHz */
clock_sys_set_src(CLOCK_SYS_SRC_SYSPLL);
clock_syspll_init(1, 100, 3, 2); /* 12MHz / 1 * 100 / 3 / 2 = 200MHz */
clock_sys_set(CLOCK_SYS_SRC_SYSPLL, 1); /* 200MHz / 1 = 200MHz */
clock_peri_set(ENABLE, CLOCK_PERI_SRC_SYSPLL);
SystemCoreClockUpdate();

View File

@ -19,10 +19,6 @@
#define CLOCK_XOSC_STATUS_BADWRITE (24)
#define CLOCK_XOSC_STATUS_STABLE (31)
/* PLL type */
#define CLOCK_PLL_SYSPLL (0)
#define CLOCK_PLL_USBPLL (1)
/* clock instance */
#define CLOCK_GPOUT0 (0)
#define CLOCK_GPOUT1 (1)
@ -36,53 +32,17 @@
#define CLOCK_RTC (9)
/* clock source */
#define CLOCK_GPOUT0_SRC_SYSPLL (0)
#define CLOCK_GPOUT0_SRC_GPIN0 (1)
#define CLOCK_GPOUT0_SRC_GPIN1 (2)
#define CLOCK_GPOUT0_SRC_USBPLL (3)
#define CLOCK_GPOUT0_SRC_ROSC (4)
#define CLOCK_GPOUT0_SRC_XOSC (5)
#define CLOCK_GPOUT0_SRC_SYS (6)
#define CLOCK_GPOUT0_SRC_USB (7)
#define CLOCK_GPOUT0_SRC_ADC (8)
#define CLOCK_GPOUT0_SRC_RTC (9)
#define CLOCK_GPOUT0_SRC_REF (10)
#define CLOCK_GPOUT1_SRC_SYSPLL (0)
#define CLOCK_GPOUT1_SRC_GPIN0 (1)
#define CLOCK_GPOUT1_SRC_GPIN1 (2)
#define CLOCK_GPOUT1_SRC_USBPLL (3)
#define CLOCK_GPOUT1_SRC_ROSC (4)
#define CLOCK_GPOUT1_SRC_XOSC (5)
#define CLOCK_GPOUT1_SRC_SYS (6)
#define CLOCK_GPOUT1_SRC_USB (7)
#define CLOCK_GPOUT1_SRC_ADC (8)
#define CLOCK_GPOUT1_SRC_RTC (9)
#define CLOCK_GPOUT1_SRC_REF (10)
#define CLOCK_GPOUT2_SRC_SYSPLL (0)
#define CLOCK_GPOUT2_SRC_GPIN0 (1)
#define CLOCK_GPOUT2_SRC_GPIN1 (2)
#define CLOCK_GPOUT2_SRC_USBPLL (3)
#define CLOCK_GPOUT2_SRC_ROSC_PH (4)
#define CLOCK_GPOUT2_SRC_XOSC (5)
#define CLOCK_GPOUT2_SRC_SYS (6)
#define CLOCK_GPOUT2_SRC_USB (7)
#define CLOCK_GPOUT2_SRC_ADC (8)
#define CLOCK_GPOUT2_SRC_RTC (9)
#define CLOCK_GPOUT2_SRC_REF (10)
#define CLOCK_GPOUT3_SRC_SYSPLL (0)
#define CLOCK_GPOUT3_SRC_GPIN0 (1)
#define CLOCK_GPOUT3_SRC_GPIN1 (2)
#define CLOCK_GPOUT3_SRC_USBPLL (3)
#define CLOCK_GPOUT3_SRC_ROSC_PH (4)
#define CLOCK_GPOUT3_SRC_XOSC (5)
#define CLOCK_GPOUT3_SRC_SYS (6)
#define CLOCK_GPOUT3_SRC_USB (7)
#define CLOCK_GPOUT3_SRC_ADC (8)
#define CLOCK_GPOUT3_SRC_RTC (9)
#define CLOCK_GPOUT3_SRC_REF (10)
#define CLOCK_GPOUT_SRC_SYSPLL (0)
#define CLOCK_GPOUT_SRC_GPIN0 (1)
#define CLOCK_GPOUT_SRC_GPIN1 (2)
#define CLOCK_GPOUT_SRC_USBPLL (3)
#define CLOCK_GPOUT_SRC_ROSC (4)
#define CLOCK_GPOUT_SRC_XOSC (5)
#define CLOCK_GPOUT_SRC_SYS (6)
#define CLOCK_GPOUT_SRC_USB (7)
#define CLOCK_GPOUT_SRC_ADC (8)
#define CLOCK_GPOUT_SRC_RTC (9)
#define CLOCK_GPOUT_SRC_REF (10)
#define CLOCK_REF_SRC_USBPLL (0)
#define CLOCK_REF_SRC_GPIN0 (1)
@ -159,25 +119,20 @@ void clock_xosc_set_startup_delay(uint32_t cycle);
void clock_xosc_set_count(uint8_t count);
uint8_t clock_xosc_get_count(void);
/* PLL function */
void clock_pll_init(uint8_t pll, uint8_t refdiv, uint8_t fbdiv, uint8_t postdiv1, uint8_t postdiv2);
void clock_pll_deinit(uint8_t pll);
/* pll function */
void clock_syspll_init(uint8_t refdiv, uint16_t feedback, uint8_t postdiv1, uint8_t postdiv2);
void clock_usbpll_init(uint8_t refdiv, uint16_t feedback, uint8_t postdiv1, uint8_t postdiv2);
void clock_syspll_deinit(void);
void clock_usbpll_deinit(void);
/* CLOCK function */
void clock_gpout_set(uint8_t id, uint8_t enable, uint8_t src, uint32_t div, uint8_t dc50, uint8_t phase, uint8_t nudge);
uint32_t clock_ref_get_selected(void);
void clock_ref_set_src(uint8_t src);
void clock_ref_set_div(uint32_t div);
uint32_t clock_sys_get_selected(void);
void clock_sys_set_src(uint8_t src);
void clock_sys_set_div(uint32_t div);
/* clock function */
void clock_gpout_set(uint8_t id, uint8_t enable, uint8_t src, uint32_t div); /* div is 1~16777215 */
void clock_ref_set(uint8_t src, uint32_t div); /* div is 1~3 */
void clock_sys_set(uint8_t src, uint32_t div); /* div is 1~16777215 */
void clock_peri_set(uint8_t enable, uint8_t src);
void clock_usb_set(uint8_t enable, uint8_t src, uint32_t div, uint8_t phase, uint8_t nudge);
void clock_adc_set(uint8_t enable, uint8_t src, uint32_t div, uint8_t phase, uint8_t nudge);
void clock_rtc_set(uint8_t enable, uint8_t src, uint32_t div, uint8_t phase, uint8_t nudge);
void clock_enable(uint8_t clock);
void clock_disable(uint8_t clock);
void clock_kill(uint8_t clock);
void clock_usb_set(uint8_t enable, uint8_t src, uint32_t div); /* div is 1~3 */
void clock_adc_set(uint8_t enable, uint8_t src, uint32_t div); /* div is 1~3 */
void clock_rtc_set(uint8_t enable, uint8_t src, uint32_t div); /* div is 1~16777215 */
#ifdef __cplusplus
}

View File

@ -3,6 +3,29 @@
#include "reg.h"
struct fw_header_s {
uint32_t size;
uint32_t jump_address;
/* syspll config */
uint8_t syspll_refdiv; /* must be in 1~63, fref/refdiv must >= 5MHz */
uint8_t syspll_feedback; /* must be in 16~320, fvco must be in 750MHz~1600MHz */
uint8_t syspll_postdiv1; /* must be in 1~7 */
uint8_t syspll_postdiv2; /* must be in 1~7 */
/* usbpll config */
uint8_t usbpll_refdiv; /* must be in 1~63, fref/refdiv must >= 5MHz */
uint8_t usbpll_feedback; /* must be in 16~320, fvco must be in 750MHz~1600MHz */
uint8_t usbpll_postdiv1; /* must be in 1~7 */
uint8_t usbpll_postdiv2; /* must be in 1~7 */
/* system clock div */
uint32_t sysclk_div; /* 1~2^24-1 is available */
/* flash config */
uint16_t flash_div; /* 0 is for disable, 2~65534 is available, must be even value */
uint16_t flash_resv;
uint32_t resv;
/* checksum */
uint32_t checksum;
};
#ifdef __cplusplus
extern "C" {
#endif

View File

@ -81,38 +81,116 @@
#define CLOCK_XOSC_STARTUP_DELAY_MASK (0x3FFF)
#define CLOCK_XOSC_STARTUP_X4_POS (20)
/* CLOCK_PLL_CS_OFFSET */
#define CLOCK_PLL_REFDIV_POS (0)
#define CLOCK_PLL_REFDIV_MASK (0x3F)
#define CLOCK_PLL_BYPASS_POS (8)
#define CLOCK_PLL_LOCK_POS (31)
/* CLOCK_PLL_CS_OFFSET @ 0x000 */
#define CLOCK_PLL_CS_REFDIV_POS (0)
#define CLOCK_PLL_CS_REFDIV_MASK (0x3F << CLOCK_PLL_CS_REFDIV_POS)
#define CLOCK_PLL_CS_BYPASS (1 << 8U)
#define CLOCK_PLL_CS_LOCK (1 << 31U)
/* CLOCK_PLL_PWR_OFFSET */
#define CLOCK_PLL_PD_POS (0)
#define CLOCK_PLL_DSMPD_POS (2)
#define CLOCK_PLL_POSTDIVPD_POS (3)
#define CLOCK_PLL_VCOPD_POS (5)
#define CLOCK_PLL_PWR_MASK ((1 << CLOCK_PLL_PD_POS) | \
(1 << CLOCK_PLL_DSMPD_POS) | \
(1 << CLOCK_PLL_POSTDIVPD_POS) | \
(1 << CLOCK_PLL_VCOPD_POS))
/* CLOCK_PLL_PRIM_OFFSET */
#define CLOCK_PLL_POSTDIV2_POS (12)
#define CLOCK_PLL_POSTDIV2_MASK (0x7)
#define CLOCK_PLL_POSTDIV1_POS (16)
#define CLOCK_PLL_POSTDIV1_MASK (0x7)
/* CLOCK_PLL_PWR_OFFSET @ 0x004 */
#define CLOCK_PLL_PWR_PD (1 << 0U)
#define CLOCK_PLL_PWR_DSMPD (1 << 2U)
#define CLOCK_PLL_PWR_POSTDIVPD (1 << 3U)
#define CLOCK_PLL_PWR_VCOPD (1 << 5U)
/* CLOCK_CTRL_OFFSET */
#define CLOCK_SRC_POS (0)
#define CLOCK_SRC_MASK (0x3)
#define CLOCK_AUXSRC_POS (5)
#define CLOCK_AUXSRC_MASK (0xF)
#define CLOCK_KILL_POS (10)
#define CLOCK_ENABLE_POS (11)
#define CLOCK_DC50_POS (12)
#define CLOCK_PHASE_POS (16)
#define CLOCK_PHASE_MASK (0x3)
#define CLOCK_NUDGE_POS (20)
/* CLOCK_PLL_PRIM_OFFSET @ 0x00C */
#define CLOCK_PLL_PRIM_POSTDIV2_POS (12U)
#define CLOCK_PLL_PRIM_POSTDIV2_MASK (0x7 << CLOCK_PLL_PRIM_POSTDIV2_POS)
#define CLOCK_PLL_PRIM_POSTDIV1_POS (16U)
#define CLOCK_PLL_PRIM_POSTDIV1_MASK (0x7 << CLOCK_PLL_PRIM_POSTDIV1_POS)
/* CLOCK_CTRL_OFFSET @ 0x000 */
#define CLOCK_CTRL_SRC_POS (0U)
#define CLOCK_CTRL_AUXSRC_POS (5U)
#define CLOCK_CTRL_KILL (1 << 10U)
#define CLOCK_CTRL_ENABLE (1 << 11U)
#define CLOCK_CTRL_DC50 (1 << 12U)
#define CLOCK_CTRL_PHASE_POS (16U)
#define CLOCK_CTRL_NUDGE (1 << 20U)
/* CLOCK_DIV_OFFSET @0x004 */
#define CLOCK_DIV_FRAC_POS (0U)
#define CLOCK_DIV_INT_POS (8U)
typedef struct {
io_rw_32 ctrl;
io_rw_32 div;
io_rw_32 selected;
} clock_hw_t;
typedef struct {
io_rw_32 ref_khz;
io_rw_32 min_khz;
io_rw_32 max_khz;
io_rw_32 delay;
io_rw_32 interval;
io_rw_32 src;
io_ro_32 status;
io_ro_32 result;
} fc_hw_t;
typedef struct {
clock_hw_t clk[10];
struct {
io_rw_32 ctrl;
io_rw_32 status;
} resus;
fc_hw_t fc0;
io_rw_32 wake_en0;
io_rw_32 wake_en1;
io_rw_32 sleep_en0;
io_rw_32 sleep_en1;
io_rw_32 enabled0;
io_rw_32 enabled1;
io_rw_32 intr;
io_rw_32 inte;
io_rw_32 intf;
io_rw_32 ints;
} clocks_hw_t;
#define clocks_hw ((clocks_hw_t *const)CLOCKS_BASE)
#define clocks_hw_set ((clocks_hw *const)hw_set_alias_untyped(clocks_hw))
#define clocks_hw_clear ((clocks_hw *const)hw_clear_alias_untyped(clocks_hw))
typedef struct {
io_rw_32 cs;
io_rw_32 pwr;
io_rw_32 fbdiv_int;
io_rw_32 prim;
} pll_hw_t;
#define pll_sys_hw ((pll_hw_t *const)PLL_SYS_BASE)
#define pll_sys_hw_set ((pll_sys_hw *const)hw_set_alias_untyped(pll_sys_hw))
#define pll_sys_hw_clear ((pll_sys_hw *const)hw_clear_alias_untyped(pll_sys_hw))
#define pll_usb_hw ((pll_hw_t *const)PLL_USB_BASE)
#define pll_usb_hw_set ((pll_usb_hw *const)hw_set_alias_untyped(pll_usb_hw))
#define pll_usb_hw_clear ((pll_usb_hw *const)hw_clear_alias_untyped(pll_usb_hw))
typedef struct {
io_rw_32 ctrl;
io_rw_32 freqa;
io_rw_32 freqb;
io_rw_32 dormant;
io_rw_32 div;
io_rw_32 phase;
io_rw_32 status;
io_rw_32 randombit;
io_rw_32 count;
io_rw_32 dftx;
} rosc_hw_t;
#define rosc_hw ((rosc_hw_t *const)ROSC_BASE)
typedef struct {
io_rw_32 ctrl;
io_rw_32 status;
io_rw_32 dormant;
io_rw_32 startup;
io_rw_32 _reserved[3];
io_rw_32 count;
} xosc_hw_t;
#define xosc_hw ((xosc_hw_t *const)XOSC_BASE)
#ifdef __cplusplus
extern "C" {

View File

@ -36,6 +36,30 @@
#define SYSTEM_BLOCK_PROC0 (1 << 15)
#define SYSTEM_BLOCK_PROC1 (1 << 16)
#define SYSTEM_CLOCK_REF_XOSC_8MHZ (0)
#define SYSTEM_CLOCK_REF_XOSC_12MHZ (1)
#define SYSTEM_CLOCK_REF_XOSC_24MHZ (2)
#define SYSTEM_CLOCK_REF_XOSC_32MHZ (3)
#define SYSTEM_CLOCK_REF_XOSC_40MHZ (4)
#define SYSTEM_CLOCK_REF_XOSC_50MHZ (5)
#define SYSTEM_CLOCK_REF_XOSC_MHZ_COUNT (6)
#define SYSTEM_CLOCK_FREQ_48MHZ (0)
#define SYSTEM_CLOCK_FREQ_96MHZ (1)
#define SYSTEM_CLOCK_FREQ_100MHZ (2)
#define SYSTEM_CLOCK_FREQ_120MHZ (2)
#define SYSTEM_CLOCK_FREQ_125MHZ (3)
#define SYSTEM_CLOCK_FREQ_144MHZ (4)
#define SYSTEM_CLOCK_FREQ_150MHZ (5)
#define SYSTEM_CLOCK_FREQ_192MHZ (6)
#define SYSTEM_CLOCK_FREQ_200MHZ (7)
#define SYSTEM_CLOCK_FREQ_240MHZ (8)
#define SYSTEM_CLOCK_FREQ_250MHZ (9)
#define SYSTEM_CLOCK_FREQ_320MHZ (10)
#define SYSTEM_CLOCK_FREQ_384MHZ (11)
#define SYSTEM_CLOCK_FREQ_400MHZ (12)
#define SYSTEM_CLOCK_FREQ_MHZ_COUNT (13)
#ifdef __cplusplus
extern "C" {
#endif
@ -50,6 +74,7 @@ void system_wdg_unbound(uint32_t block);
uint8_t system_block_is_available(uint32_t block);
void system_init(void);
void system_clock_config(uint8_t ref_xosc, uint8_t sys_freq);
#ifdef __cplusplus
}

View File

@ -273,371 +273,190 @@ uint8_t clock_xosc_get_count(void)
return (uint8_t)getreg32(XOSC_BASE + CLOCK_XOSC_COUNT_OFFSET);
}
void clock_pll_init(uint8_t pll, uint8_t refdiv, uint8_t fbdiv, uint8_t postdiv1, uint8_t postdiv2)
/******************************** PLL *********************************/
static void pll_init(pll_hw_t *pll, uint8_t refdiv, uint16_t feedback, uint8_t postdiv1, uint8_t postdiv2)
{
uint32_t addr;
uint32_t val;
if (pll == CLOCK_PLL_SYSPLL) {
reset_unreset_blocks_wait(RESETS_BLOCK_SYSPLL);
addr = PLL_SYS_BASE;
} else if (pll == CLOCK_PLL_USBPLL) {
reset_unreset_blocks_wait(RESETS_BLOCK_USBPLL);
addr = PLL_USB_BASE;
} else {
return;
/* load VCO-related dividers before starting VCO */
if (refdiv == 0) {
refdiv = 1;
} else if (refdiv > 63) {
refdiv = 63;
}
/* Load VCO-related dividers before starting VCO */
putreg32((uint32_t)refdiv, addr + CLOCK_PLL_CS_OFFSET);
putreg32((uint32_t)fbdiv, addr + CLOCK_PLL_FBDIV_INT_OFFSET);
/* Turn on PLL */
val = (1 << CLOCK_PLL_PD_POS) | (1 << CLOCK_PLL_VCOPD_POS);
putreg32(val, addr + CLOCK_PLL_PWR_OFFSET + REG_ALIAS_CLR_BITS);
/* Wait for PLL to lock */
while (1) {
val = getreg32(addr + CLOCK_PLL_CS_OFFSET);
val &= (1 << CLOCK_PLL_LOCK_POS);
if (val) {
break;
}
pll->cs = refdiv;
if (feedback == 0) {
feedback = 1;
} else if (feedback > 4095) {
feedback = 4095;
}
/* Set up post dividers */
val = (postdiv1 << CLOCK_PLL_POSTDIV1_POS) | (postdiv2 << CLOCK_PLL_POSTDIV2_POS);
putreg32(val, addr + CLOCK_PLL_PRIM_OFFSET);
/* Turn on post divider */
putreg32(1 << CLOCK_PLL_POSTDIVPD_POS, addr + CLOCK_PLL_PWR_OFFSET + REG_ALIAS_CLR_BITS);
pll->fbdiv_int = feedback;
/* turn on PLL, write 0 for release power down */
pll->pwr = CLOCK_PLL_PWR_POSTDIVPD | CLOCK_PLL_PWR_DSMPD;
/* wait for PLL to lock */
while (!(pll->cs & CLOCK_PLL_CS_LOCK));
/* set up post dividers */
if (postdiv1 == 0) {
postdiv1 = 1;
} else if (postdiv1 > 7) {
postdiv1 = 7;
}
if (postdiv2 == 0) {
postdiv2 = 1;
} else if (postdiv2 > 7) {
postdiv2 = 7;
}
pll->prim = (postdiv1 << CLOCK_PLL_PRIM_POSTDIV1_POS) | (postdiv2 << CLOCK_PLL_PRIM_POSTDIV2_POS);
/* turn on post divider */
pll->pwr = 0;
}
void clock_pll_deinit(uint8_t pll)
void clock_syspll_init(uint8_t refdiv, uint16_t feedback, uint8_t postdiv1, uint8_t postdiv2)
{
if (pll == CLOCK_PLL_SYSPLL) {
reset_unreset_blocks_wait(RESETS_BLOCK_SYSPLL);
putreg32(CLOCK_PLL_PWR_MASK, PLL_SYS_BASE + CLOCK_PLL_PWR_OFFSET);
} else if (pll == CLOCK_PLL_USBPLL) {
reset_unreset_blocks_wait(RESETS_BLOCK_USBPLL);
putreg32(CLOCK_PLL_PWR_MASK, PLL_USB_BASE + CLOCK_PLL_PWR_OFFSET);
}
reset_unreset_blocks_wait(RESETS_BLOCK_SYSPLL);
pll_init(pll_sys_hw, refdiv, feedback, postdiv1, postdiv2);
}
/* id: 0 ~ 3 */
/* div[31:8]: Integer component of the divisor, 0 is for 2^24 */
/* div[ 7:0]: Fractional component of the divisor */
/* phase: 0 ~ 3 */
void clock_gpout_set(uint8_t id, uint8_t enable, uint8_t src, uint32_t div, uint8_t dc50, uint8_t phase, uint8_t nudge)
void clock_usbpll_init(uint8_t refdiv, uint16_t feedback, uint8_t postdiv1, uint8_t postdiv2)
{
reset_unreset_blocks_wait(RESETS_BLOCK_USBPLL);
pll_init(pll_usb_hw, refdiv, feedback, postdiv1, postdiv2);
}
void clock_syspll_deinit(void)
{
reset_unreset_blocks_wait(RESETS_BLOCK_SYSPLL);
}
void clock_usbpll_deinit(void)
{
reset_unreset_blocks_wait(RESETS_BLOCK_USBPLL);
}
void clock_gpout_set(uint8_t id, uint8_t enable, uint8_t src, uint32_t div)
{
uint32_t addr;
uint32_t val;
/* step1: disable clock */
addr = CLOCKS_BASE + CLOCK_GPOUT0_CTRL_OFFSET + id * 0xC;
putreg32(1 << CLOCK_ENABLE_POS, addr + REG_ALIAS_CLR_BITS);
/* step2: config ctrl register */
val = getreg32(addr);
/* config clock source */
val &= ~(CLOCK_AUXSRC_MASK << CLOCK_AUXSRC_POS);
val |= ((src & CLOCK_AUXSRC_MASK) << CLOCK_AUXSRC_POS);
/* config duty cycle correction for odd divisors */
if (dc50) {
val |= 1 << CLOCK_DC50_POS;
} else {
val &= ~(1 << CLOCK_DC50_POS);
}
/* config delay phase up to 3 cycles of the input clock */
val &= ~(CLOCK_PHASE_MASK << CLOCK_PHASE_POS);
val |= ((phase & CLOCK_PHASE_MASK) << CLOCK_PHASE_POS);
/* config signal shifts the phase of the output by 1 cycle of the input clock */
if (nudge) {
val |= 1 << CLOCK_NUDGE_POS;
} else {
val &= ~(1 << CLOCK_NUDGE_POS);
}
/* disable clock */
val &= ~(1 << CLOCK_ENABLE_POS);
putreg32(val, addr);
/* step3: config div */
putreg32(div, CLOCKS_BASE + CLOCK_GPOUT0_DIV_OFFSET + id * 0xC);
/* step4: config enable */
div = (div > 0xFFFFFF) ? 0xFFFFFF : div;
div = div << CLOCK_DIV_INT_POS;
val = ((uint32_t)src << CLOCK_CTRL_AUXSRC_POS) | CLOCK_CTRL_DC50;
clocks_hw->clk[CLOCK_GPOUT0 + id].ctrl = val;
clocks_hw->clk[CLOCK_GPOUT0 + id].div = div;
if (enable) {
putreg32(1 << CLOCK_ENABLE_POS, addr + REG_ALIAS_SET_BITS);
val |= CLOCK_CTRL_ENABLE;
clocks_hw->clk[CLOCK_GPOUT0 + id].ctrl = val;
}
}
uint32_t clock_ref_get_selected(void)
void clock_ref_set(uint8_t src, uint32_t div)
{
return getreg32(CLOCKS_BASE + CLOCK_REF_SELECTED_OFFSET);
}
void clock_ref_set_src(uint8_t src)
{
uint32_t addr;
uint32_t val;
addr = CLOCKS_BASE + CLOCK_REF_CTRL_OFFSET;
div = (div > 3) ? 3 : div;
div = div << CLOCK_DIV_INT_POS;
if (div > clocks_hw->clk[CLOCK_REF].div) {
clocks_hw->clk[CLOCK_REF].div = div;
}
if (src == CLOCK_REF_SRC_ROSC_PH_GLITCHLESS) {
/* switch to the glitchless mux */
clock_rosc_enable();
/* step1: switch the glitchless mux to an alternate source */
putreg32(0, addr);
/* step2: poll the SELECTED register until the switch is completed */
while (1) {
if (clock_ref_get_selected() & (1 << 0)) {
break;
}
}
clocks_hw->clk[CLOCK_REF].ctrl = 0;
while (!(clocks_hw->clk[CLOCK_REF].selected & (1u << 0)));
} else if (src == CLOCK_REF_SRC_XOSC_GLITCHLESS) {
/* switch to the glitchless mux */
clock_xosc_enable();
/* step1: switch the glitchless mux to an alternate source */
putreg32(2, addr);
/* step2: poll the SELECTED register until the switch is completed */
while (1) {
if (clock_ref_get_selected() & (1 << 2)) {
break;
}
}
clocks_hw->clk[CLOCK_REF].ctrl = 2;
while (!(clocks_hw->clk[CLOCK_REF].selected & (1u << 2)));
} else {
/* switch to the auxiliary mux when the generator has a glitchless mux */
clock_rosc_enable();
/* step1: switch the glitchless mux to a source that isnt the aux mux */
putreg32(0, addr);
/* step2: poll the SELECTED register until the switch is completed */
while (1) {
if (clock_ref_get_selected() & (1 << 0)) {
break;
}
}
/* step3: change the auxiliary mux select control */
val = (uint32_t)src << CLOCK_AUXSRC_POS;
putreg32(val, addr);
/* step4: switch the glitchless mux back to the aux mux */
val |= 1;
putreg32(val, addr);
/* step5: if required, poll the SELECTED register until the switch is completed */
while (1) {
if (clock_ref_get_selected() & (1 << 1)) {
break;
}
}
clocks_hw->clk[CLOCK_REF].ctrl = 0;
while (!(clocks_hw->clk[CLOCK_REF].selected & (1u << 0)));
val = (uint32_t)src << CLOCK_CTRL_AUXSRC_POS;
clocks_hw->clk[CLOCK_REF].ctrl = val;
val |= (1u << CLOCK_CTRL_SRC_POS);
clocks_hw->clk[CLOCK_REF].ctrl = val;
while (!(clocks_hw->clk[CLOCK_REF].selected & (1u << 1)));
}
if (div < clocks_hw->clk[CLOCK_REF].div) {
clocks_hw->clk[CLOCK_REF].div = div;
}
}
/* div[9:8]: Integer component of the divisor, 0 is for 2^2 */
/* div[7:0]: reserved */
void clock_ref_set_div(uint32_t div)
void clock_sys_set(uint8_t src, uint32_t div)
{
putreg32(div, CLOCKS_BASE + CLOCK_REF_DIV_OFFSET);
}
uint32_t clock_sys_get_selected(void)
{
return getreg32(CLOCKS_BASE + CLOCK_SYS_SELECTED_OFFSET);
}
/* must: call clock_ref_set_src brfore call clock_sys_set_src */
void clock_sys_set_src(uint8_t src)
{
uint32_t addr;
uint32_t val;
addr = CLOCKS_BASE + CLOCK_SYS_CTRL_OFFSET;
if (src == CLOCK_SYS_SRC_REF_GLITCHLESS) {
/* switch to the glitchless mux */
/* step1: switch the glitchless mux to an alternate source */
putreg32(0, addr);
/* step2: poll the SELECTED register until the switch is completed */
while (1) {
if (clock_sys_get_selected() & (1 << 0)) {
break;
}
}
} else {
/* switch to the auxiliary mux when the generator has a glitchless mux */
/* step1: switch the glitchless mux to a source that isnt the aux mux */
putreg32(0, addr);
/* step2: poll the SELECTED register until the switch is completed */
while (1) {
if (clock_sys_get_selected() & (1 << 0)) {
break;
}
}
/* step3: change the auxiliary mux select control */
val = (uint32_t)src << CLOCK_AUXSRC_POS;
putreg32(val, addr);
/* step4: switch the glitchless mux back to the aux mux */
val |= 1;
putreg32(val, addr);
/* step5: if required, poll the SELECTED register until the switch is completed */
while (1) {
if (clock_sys_get_selected() & (1 << 1)) {
break;
}
}
div = (div > 0xFFFFFF) ? 0xFFFFFF : div;
div = div << CLOCK_DIV_INT_POS;
if (div > clocks_hw->clk[CLOCK_SYS].div) {
clocks_hw->clk[CLOCK_SYS].div = div;
}
if (src == CLOCK_SYS_SRC_REF_GLITCHLESS) {
clocks_hw->clk[CLOCK_SYS].ctrl = 0;
while (!(clocks_hw->clk[CLOCK_SYS].selected & (1u << 0)));
} else {
clocks_hw->clk[CLOCK_SYS].ctrl = 0;
while (!(clocks_hw->clk[CLOCK_SYS].selected & (1u << 0)));
val = (uint32_t)src << CLOCK_CTRL_AUXSRC_POS;
clocks_hw->clk[CLOCK_SYS].ctrl = val;
val |= (1u << CLOCK_CTRL_SRC_POS);
clocks_hw->clk[CLOCK_SYS].ctrl = val;
while (!(clocks_hw->clk[CLOCK_SYS].selected & (1u << 1)));
}
if (div < clocks_hw->clk[CLOCK_SYS].div) {
clocks_hw->clk[CLOCK_SYS].div = div;
}
}
/* div[31:8]: Integer component of the divisor, 0 is for 2^24 */
/* div[ 7:0]: Fractional component of the divisor */
void clock_sys_set_div(uint32_t div)
{
putreg32(div, CLOCKS_BASE + CLOCK_SYS_DIV_OFFSET);
}
void clock_peri_set(uint8_t enable, uint8_t src)
{
uint32_t addr;
uint32_t val;
/* step1: disable clock */
addr = CLOCKS_BASE + CLOCK_PERI_CTRL_OFFSET;
putreg32(1 << CLOCK_ENABLE_POS, addr + REG_ALIAS_CLR_BITS);
/* step2: config ctrl register */
val = getreg32(addr);
/* config clock source */
val &= ~(CLOCK_AUXSRC_MASK << CLOCK_AUXSRC_POS);
val |= ((src & CLOCK_AUXSRC_MASK) << CLOCK_AUXSRC_POS);
/* disable clock */
val &= ~(1 << CLOCK_ENABLE_POS);
putreg32(val, addr);
/* step3: config enable */
val = (uint32_t)src << CLOCK_CTRL_AUXSRC_POS;
clocks_hw->clk[CLOCK_PERI].ctrl = val;
if (enable) {
putreg32(1 << CLOCK_ENABLE_POS, addr + REG_ALIAS_SET_BITS);
val |= CLOCK_CTRL_ENABLE;
clocks_hw->clk[CLOCK_PERI].ctrl = val;
}
}
/* div[9:8]: Integer component of the divisor, 0 is for 2^2 */
/* div[7:0]: reserved */
/* phase: 0 ~ 3 */
void clock_usb_set(uint8_t enable, uint8_t src, uint32_t div, uint8_t phase, uint8_t nudge)
void clock_usb_set(uint8_t enable, uint8_t src, uint32_t div)
{
uint32_t addr;
uint32_t val;
/* step1: disable clock */
addr = CLOCKS_BASE + CLOCK_USB_CTRL_OFFSET;
putreg32(1 << CLOCK_ENABLE_POS, addr + REG_ALIAS_CLR_BITS);
/* step2: config ctrl register */
val = getreg32(addr);
/* config clock source */
val &= ~(CLOCK_AUXSRC_MASK << CLOCK_AUXSRC_POS);
val |= ((src & CLOCK_AUXSRC_MASK) << CLOCK_AUXSRC_POS);
/* config delay phase up to 3 cycles of the input clock */
val &= ~(CLOCK_PHASE_MASK << CLOCK_PHASE_POS);
val |= ((phase & CLOCK_PHASE_MASK) << CLOCK_PHASE_POS);
/* config signal shifts the phase of the output by 1 cycle of the input clock */
if (nudge) {
val |= 1 << CLOCK_NUDGE_POS;
} else {
val &= ~(1 << CLOCK_NUDGE_POS);
}
/* disable clock */
val &= ~(1 << CLOCK_ENABLE_POS);
putreg32(val, addr);
/* step3: config div */
putreg32(div, CLOCKS_BASE + CLOCK_USB_DIV_OFFSET);
/* step4: config enable */
div = (div > 3) ? 3 : div;
div = div << CLOCK_DIV_INT_POS;
val = (uint32_t)src << CLOCK_CTRL_AUXSRC_POS;
clocks_hw->clk[CLOCK_USB].ctrl = val;
clocks_hw->clk[CLOCK_USB].div = div;
if (enable) {
putreg32(1 << CLOCK_ENABLE_POS, addr + REG_ALIAS_SET_BITS);
val |= CLOCK_CTRL_ENABLE;
clocks_hw->clk[CLOCK_USB].ctrl = val;
}
}
/* div[9:8]: Integer component of the divisor, 0 is for 2^2 */
/* div[7:0]: reserved */
/* phase: 0 ~ 3 */
void clock_adc_set(uint8_t enable, uint8_t src, uint32_t div, uint8_t phase, uint8_t nudge)
void clock_adc_set(uint8_t enable, uint8_t src, uint32_t div)
{
uint32_t addr;
uint32_t val;
/* step1: disable clock */
addr = CLOCKS_BASE + CLOCK_ADC_CTRL_OFFSET;
putreg32(1 << CLOCK_ENABLE_POS, addr + REG_ALIAS_CLR_BITS);
/* step2: config ctrl register */
val = getreg32(addr);
/* config clock source */
val &= ~(CLOCK_AUXSRC_MASK << CLOCK_AUXSRC_POS);
val |= ((src & CLOCK_AUXSRC_MASK) << CLOCK_AUXSRC_POS);
/* config delay phase up to 3 cycles of the input clock */
val &= ~(CLOCK_PHASE_MASK << CLOCK_PHASE_POS);
val |= ((phase & CLOCK_PHASE_MASK) << CLOCK_PHASE_POS);
/* config signal shifts the phase of the output by 1 cycle of the input clock */
if (nudge) {
val |= 1 << CLOCK_NUDGE_POS;
} else {
val &= ~(1 << CLOCK_NUDGE_POS);
}
/* disable clock */
val &= ~(1 << CLOCK_ENABLE_POS);
putreg32(val, addr);
/* step3: config div */
putreg32(div, CLOCKS_BASE + CLOCK_ADC_DIV_OFFSET);
/* step4: config enable */
div = (div > 3) ? 3 : div;
div = div << CLOCK_DIV_INT_POS;
val = (uint32_t)src << CLOCK_CTRL_AUXSRC_POS;
clocks_hw->clk[CLOCK_ADC].ctrl = val;
clocks_hw->clk[CLOCK_ADC].div = div;
if (enable) {
putreg32(1 << CLOCK_ENABLE_POS, addr + REG_ALIAS_SET_BITS);
val |= CLOCK_CTRL_ENABLE;
clocks_hw->clk[CLOCK_ADC].ctrl = val;
}
}
/* div[31:8]: Integer component of the divisor, 0 is for 2^2 */
/* div[ 7:0]: Fractional component of the divisor */
/* phase: 0 ~ 3 */
void clock_rtc_set(uint8_t enable, uint8_t src, uint32_t div, uint8_t phase, uint8_t nudge)
void clock_rtc_set(uint8_t enable, uint8_t src, uint32_t div)
{
uint32_t addr;
uint32_t val;
/* step1: disable clock */
addr = CLOCKS_BASE + CLOCK_RTC_CTRL_OFFSET;
putreg32(1 << CLOCK_ENABLE_POS, addr + REG_ALIAS_CLR_BITS);
/* step2: config ctrl register */
val = getreg32(addr);
/* config clock source */
val &= ~(CLOCK_AUXSRC_MASK << CLOCK_AUXSRC_POS);
val |= ((src & CLOCK_AUXSRC_MASK) << CLOCK_AUXSRC_POS);
/* config delay phase up to 3 cycles of the input clock */
val &= ~(CLOCK_PHASE_MASK << CLOCK_PHASE_POS);
val |= ((phase & CLOCK_PHASE_MASK) << CLOCK_PHASE_POS);
/* config signal shifts the phase of the output by 1 cycle of the input clock */
if (nudge) {
val |= 1 << CLOCK_NUDGE_POS;
} else {
val &= ~(1 << CLOCK_NUDGE_POS);
}
/* disable clock */
val &= ~(1 << CLOCK_ENABLE_POS);
putreg32(val, addr);
/* step3: config div */
putreg32(div, CLOCKS_BASE + CLOCK_RTC_DIV_OFFSET);
/* step4: config enable */
div = (div > 0xFFFFFF) ? 0xFFFFFF : div;
div = div << CLOCK_DIV_INT_POS;
val = (uint32_t)src << CLOCK_CTRL_AUXSRC_POS;
clocks_hw->clk[CLOCK_RTC].ctrl = val;
clocks_hw->clk[CLOCK_RTC].div = div;
if (enable) {
putreg32(1 << CLOCK_ENABLE_POS, addr + REG_ALIAS_SET_BITS);
val |= CLOCK_CTRL_ENABLE;
clocks_hw->clk[CLOCK_RTC].ctrl = val;
}
}
void clock_enable(uint8_t clock)
{
putreg32(1 << CLOCK_ENABLE_POS, CLOCKS_BASE + CLOCK_CTRL_OFFSET + REG_ALIAS_SET_BITS + (uint32_t)clock * 0xC);
}
void clock_disable(uint8_t clock)
{
putreg32(1 << CLOCK_ENABLE_POS, CLOCKS_BASE + CLOCK_CTRL_OFFSET + REG_ALIAS_CLR_BITS + (uint32_t)clock * 0xC);
}
void clock_kill(uint8_t clock)
{
putreg32(1 << CLOCK_KILL_POS, CLOCKS_BASE + CLOCK_CTRL_OFFSET + REG_ALIAS_SET_BITS + (uint32_t)clock * 0xC);
putreg32(1 << CLOCK_KILL_POS, CLOCKS_BASE + CLOCK_CTRL_OFFSET + REG_ALIAS_CLR_BITS + (uint32_t)clock * 0xC);
}

View File

@ -5,6 +5,7 @@
#include "gpio.h"
#include "timer.h"
#include "uart.h"
#include "RP2040.h"
#include "stdio.h"
/* voltage: SYSTEM_REGULATOR_VOLTAGE_XXX */
@ -106,17 +107,117 @@ void system_init(void)
};
system_regulator_set(SYSTEM_REGULATOR_VOLTAGE_1P30V);
clock_ref_set_src(CLOCK_REF_SRC_XOSC_GLITCHLESS);
clock_sys_set_src(CLOCK_SYS_SRC_REF_GLITCHLESS);
clock_ref_set(CLOCK_REF_SRC_XOSC_GLITCHLESS, 1);
clock_sys_set(CLOCK_SYS_SRC_REF_GLITCHLESS, 1);
/* refdiv >= 5MHz, VCO=[750:1600]MHz, fbdiv=[16:320], postdiv=[1:7] */
clock_pll_init(CLOCK_PLL_SYSPLL, 1, 100, 3, 2); /* 12MHz / 1 * 100 / 3 / 2 = 200MHz */
clock_sys_set_div(1 << 8); /* 200MHz / 1 = 200MHz */
clock_sys_set_src(CLOCK_SYS_SRC_SYSPLL);
clock_syspll_init(1, 100, 3, 2); /* 12MHz / 1 * 100 / 3 / 2 = 200MHz */
clock_sys_set(CLOCK_SYS_SRC_SYSPLL, 1); /* 200MHz / 1 = 200MHz */
clock_peri_set(ENABLE, CLOCK_PERI_SRC_SYSPLL);
reset_unreset_blocks_wait(RESETS_BLOCK_IO_BANK0 | RESETS_BLOCK_PADS_BANK0 | RESETS_BLOCK_UART0 | RESETS_BLOCK_TIMER);
uart_init(UART_ID_0, &uart_cfg);
gpio_init_simple(0, GPIO_FUNC_UART, DISABLE, ENABLE);
timer_start();
irq_init();
SysTick->CTRL = 0;
printf("system clock = 200MHz\r\n");
}
const static uint8_t system_clock_cfg_para[SYSTEM_CLOCK_REF_XOSC_MHZ_COUNT][SYSTEM_CLOCK_FREQ_MHZ_COUNT][5] = {
[SYSTEM_CLOCK_REF_XOSC_8MHZ][SYSTEM_CLOCK_FREQ_48MHZ] = {1, 2, 3, 4, 5},
[SYSTEM_CLOCK_REF_XOSC_8MHZ][SYSTEM_CLOCK_FREQ_96MHZ] = {6, 7, 8, 9, 0},
[SYSTEM_CLOCK_REF_XOSC_8MHZ][SYSTEM_CLOCK_FREQ_100MHZ] = {0, 0, 0, 0, 0},
[SYSTEM_CLOCK_REF_XOSC_8MHZ][SYSTEM_CLOCK_FREQ_120MHZ] = {0, 0, 0, 0, 0},
[SYSTEM_CLOCK_REF_XOSC_8MHZ][SYSTEM_CLOCK_FREQ_125MHZ] = {0, 0, 0, 0, 0},
[SYSTEM_CLOCK_REF_XOSC_8MHZ][SYSTEM_CLOCK_FREQ_144MHZ] = {0, 0, 0, 0, 0},
[SYSTEM_CLOCK_REF_XOSC_8MHZ][SYSTEM_CLOCK_FREQ_150MHZ] = {0, 0, 0, 0, 0},
[SYSTEM_CLOCK_REF_XOSC_8MHZ][SYSTEM_CLOCK_FREQ_192MHZ] = {0, 0, 0, 0, 0},
[SYSTEM_CLOCK_REF_XOSC_8MHZ][SYSTEM_CLOCK_FREQ_200MHZ] = {0, 0, 0, 0, 0},
[SYSTEM_CLOCK_REF_XOSC_8MHZ][SYSTEM_CLOCK_FREQ_240MHZ] = {0, 0, 0, 0, 0},
[SYSTEM_CLOCK_REF_XOSC_8MHZ][SYSTEM_CLOCK_FREQ_250MHZ] = {0, 0, 0, 0, 0},
[SYSTEM_CLOCK_REF_XOSC_8MHZ][SYSTEM_CLOCK_FREQ_320MHZ] = {0, 0, 0, 0, 0},
[SYSTEM_CLOCK_REF_XOSC_8MHZ][SYSTEM_CLOCK_FREQ_384MHZ] = {0, 0, 0, 0, 0},
[SYSTEM_CLOCK_REF_XOSC_8MHZ][SYSTEM_CLOCK_FREQ_400MHZ] = {0, 0, 0, 0, 0},
[SYSTEM_CLOCK_REF_XOSC_12MHZ][SYSTEM_CLOCK_FREQ_48MHZ] = {1, 96, 6, 4, 1}, /* 12MHz / 1 * 96 / 6 / 4 = 48MHz */
[SYSTEM_CLOCK_REF_XOSC_12MHZ][SYSTEM_CLOCK_FREQ_96MHZ] = {1, 96, 6, 2, 1}, /* 12MHz / 1 * 96 / 6 / 2 = 96MHz */
[SYSTEM_CLOCK_REF_XOSC_12MHZ][SYSTEM_CLOCK_FREQ_100MHZ] = {1, 100, 6, 2, 1}, /* 12MHz / 1 * 100 / 6 / 2 = 100MHz */
[SYSTEM_CLOCK_REF_XOSC_12MHZ][SYSTEM_CLOCK_FREQ_120MHZ] = {1, 100, 5, 2, 1}, /* 12MHz / 1 * 100 / 5 / 2 = 120MHz */
[SYSTEM_CLOCK_REF_XOSC_12MHZ][SYSTEM_CLOCK_FREQ_125MHZ] = {1, 125, 6, 2, 1}, /* 12MHz / 1 * 125 / 6 / 2 = 125MHz */
[SYSTEM_CLOCK_REF_XOSC_12MHZ][SYSTEM_CLOCK_FREQ_144MHZ] = {1, 96, 4, 2, 1}, /* 12MHz / 1 * 96 / 4 / 2 = 144MHz */
[SYSTEM_CLOCK_REF_XOSC_12MHZ][SYSTEM_CLOCK_FREQ_150MHZ] = {1, 100, 4, 2, 1}, /* 12MHz / 1 * 100 / 4 / 2 = 150MHz */
[SYSTEM_CLOCK_REF_XOSC_12MHZ][SYSTEM_CLOCK_FREQ_192MHZ] = {1, 96, 6, 1, 1}, /* 12MHz / 1 * 96 / 6 / 1 = 192MHz */
[SYSTEM_CLOCK_REF_XOSC_12MHZ][SYSTEM_CLOCK_FREQ_200MHZ] = {1, 100, 6, 1, 1}, /* 12MHz / 1 * 100 / 6 / 1 = 200MHz */
[SYSTEM_CLOCK_REF_XOSC_12MHZ][SYSTEM_CLOCK_FREQ_240MHZ] = {1, 100, 5, 1, 1}, /* 12MHz / 1 * 100 / 5 / 1 = 240MHz */
[SYSTEM_CLOCK_REF_XOSC_12MHZ][SYSTEM_CLOCK_FREQ_250MHZ] = {1, 125, 6, 1, 1}, /* 12MHz / 1 * 125 / 6 / 1 = 250MHz */
[SYSTEM_CLOCK_REF_XOSC_12MHZ][SYSTEM_CLOCK_FREQ_320MHZ] = {1, 80, 3, 1, 1}, /* 12MHz / 1 * 80 / 3 / 1 = 320MHz */
[SYSTEM_CLOCK_REF_XOSC_12MHZ][SYSTEM_CLOCK_FREQ_384MHZ] = {1, 96, 3, 1, 1}, /* 12MHz / 1 * 96 / 3 / 1 = 384MHz */
[SYSTEM_CLOCK_REF_XOSC_12MHZ][SYSTEM_CLOCK_FREQ_400MHZ] = {1, 100, 3, 1, 1}, /* 12MHz / 1 * 100 / 3 / 1 = 400MHz */
[SYSTEM_CLOCK_REF_XOSC_24MHZ][SYSTEM_CLOCK_FREQ_48MHZ] = {1, 2, 3, 4, 5},
[SYSTEM_CLOCK_REF_XOSC_24MHZ][SYSTEM_CLOCK_FREQ_96MHZ] = {6, 7, 8, 9, 0},
[SYSTEM_CLOCK_REF_XOSC_24MHZ][SYSTEM_CLOCK_FREQ_100MHZ] = {0, 0, 0, 0, 0},
[SYSTEM_CLOCK_REF_XOSC_24MHZ][SYSTEM_CLOCK_FREQ_120MHZ] = {0, 0, 0, 0, 0},
[SYSTEM_CLOCK_REF_XOSC_24MHZ][SYSTEM_CLOCK_FREQ_125MHZ] = {0, 0, 0, 0, 0},
[SYSTEM_CLOCK_REF_XOSC_24MHZ][SYSTEM_CLOCK_FREQ_144MHZ] = {0, 0, 0, 0, 0},
[SYSTEM_CLOCK_REF_XOSC_24MHZ][SYSTEM_CLOCK_FREQ_150MHZ] = {0, 0, 0, 0, 0},
[SYSTEM_CLOCK_REF_XOSC_24MHZ][SYSTEM_CLOCK_FREQ_192MHZ] = {0, 0, 0, 0, 0},
[SYSTEM_CLOCK_REF_XOSC_24MHZ][SYSTEM_CLOCK_FREQ_200MHZ] = {0, 0, 0, 0, 0},
[SYSTEM_CLOCK_REF_XOSC_24MHZ][SYSTEM_CLOCK_FREQ_240MHZ] = {0, 0, 0, 0, 0},
[SYSTEM_CLOCK_REF_XOSC_24MHZ][SYSTEM_CLOCK_FREQ_250MHZ] = {0, 0, 0, 0, 0},
[SYSTEM_CLOCK_REF_XOSC_24MHZ][SYSTEM_CLOCK_FREQ_320MHZ] = {0, 0, 0, 0, 0},
[SYSTEM_CLOCK_REF_XOSC_24MHZ][SYSTEM_CLOCK_FREQ_384MHZ] = {0, 0, 0, 0, 0},
[SYSTEM_CLOCK_REF_XOSC_24MHZ][SYSTEM_CLOCK_FREQ_400MHZ] = {0, 0, 0, 0, 0},
[SYSTEM_CLOCK_REF_XOSC_32MHZ][SYSTEM_CLOCK_FREQ_48MHZ] = {1, 2, 3, 4, 5},
[SYSTEM_CLOCK_REF_XOSC_32MHZ][SYSTEM_CLOCK_FREQ_96MHZ] = {6, 7, 8, 9, 0},
[SYSTEM_CLOCK_REF_XOSC_32MHZ][SYSTEM_CLOCK_FREQ_100MHZ] = {0, 0, 0, 0, 0},
[SYSTEM_CLOCK_REF_XOSC_32MHZ][SYSTEM_CLOCK_FREQ_120MHZ] = {0, 0, 0, 0, 0},
[SYSTEM_CLOCK_REF_XOSC_32MHZ][SYSTEM_CLOCK_FREQ_125MHZ] = {0, 0, 0, 0, 0},
[SYSTEM_CLOCK_REF_XOSC_32MHZ][SYSTEM_CLOCK_FREQ_144MHZ] = {0, 0, 0, 0, 0},
[SYSTEM_CLOCK_REF_XOSC_32MHZ][SYSTEM_CLOCK_FREQ_150MHZ] = {0, 0, 0, 0, 0},
[SYSTEM_CLOCK_REF_XOSC_32MHZ][SYSTEM_CLOCK_FREQ_192MHZ] = {0, 0, 0, 0, 0},
[SYSTEM_CLOCK_REF_XOSC_32MHZ][SYSTEM_CLOCK_FREQ_200MHZ] = {0, 0, 0, 0, 0},
[SYSTEM_CLOCK_REF_XOSC_32MHZ][SYSTEM_CLOCK_FREQ_240MHZ] = {0, 0, 0, 0, 0},
[SYSTEM_CLOCK_REF_XOSC_32MHZ][SYSTEM_CLOCK_FREQ_250MHZ] = {0, 0, 0, 0, 0},
[SYSTEM_CLOCK_REF_XOSC_32MHZ][SYSTEM_CLOCK_FREQ_320MHZ] = {0, 0, 0, 0, 0},
[SYSTEM_CLOCK_REF_XOSC_32MHZ][SYSTEM_CLOCK_FREQ_384MHZ] = {0, 0, 0, 0, 0},
[SYSTEM_CLOCK_REF_XOSC_32MHZ][SYSTEM_CLOCK_FREQ_400MHZ] = {0, 0, 0, 0, 0},
[SYSTEM_CLOCK_REF_XOSC_40MHZ][SYSTEM_CLOCK_FREQ_48MHZ] = {1, 2, 3, 4, 5},
[SYSTEM_CLOCK_REF_XOSC_40MHZ][SYSTEM_CLOCK_FREQ_96MHZ] = {6, 7, 8, 9, 0},
[SYSTEM_CLOCK_REF_XOSC_40MHZ][SYSTEM_CLOCK_FREQ_100MHZ] = {0, 0, 0, 0, 0},
[SYSTEM_CLOCK_REF_XOSC_40MHZ][SYSTEM_CLOCK_FREQ_120MHZ] = {0, 0, 0, 0, 0},
[SYSTEM_CLOCK_REF_XOSC_40MHZ][SYSTEM_CLOCK_FREQ_125MHZ] = {0, 0, 0, 0, 0},
[SYSTEM_CLOCK_REF_XOSC_40MHZ][SYSTEM_CLOCK_FREQ_144MHZ] = {0, 0, 0, 0, 0},
[SYSTEM_CLOCK_REF_XOSC_40MHZ][SYSTEM_CLOCK_FREQ_150MHZ] = {0, 0, 0, 0, 0},
[SYSTEM_CLOCK_REF_XOSC_40MHZ][SYSTEM_CLOCK_FREQ_192MHZ] = {0, 0, 0, 0, 0},
[SYSTEM_CLOCK_REF_XOSC_40MHZ][SYSTEM_CLOCK_FREQ_200MHZ] = {0, 0, 0, 0, 0},
[SYSTEM_CLOCK_REF_XOSC_40MHZ][SYSTEM_CLOCK_FREQ_240MHZ] = {0, 0, 0, 0, 0},
[SYSTEM_CLOCK_REF_XOSC_40MHZ][SYSTEM_CLOCK_FREQ_250MHZ] = {0, 0, 0, 0, 0},
[SYSTEM_CLOCK_REF_XOSC_40MHZ][SYSTEM_CLOCK_FREQ_320MHZ] = {0, 0, 0, 0, 0},
[SYSTEM_CLOCK_REF_XOSC_40MHZ][SYSTEM_CLOCK_FREQ_384MHZ] = {0, 0, 0, 0, 0},
[SYSTEM_CLOCK_REF_XOSC_40MHZ][SYSTEM_CLOCK_FREQ_400MHZ] = {0, 0, 0, 0, 0},
[SYSTEM_CLOCK_REF_XOSC_50MHZ][SYSTEM_CLOCK_FREQ_48MHZ] = {1, 2, 3, 4, 5},
[SYSTEM_CLOCK_REF_XOSC_50MHZ][SYSTEM_CLOCK_FREQ_96MHZ] = {6, 7, 8, 9, 0},
[SYSTEM_CLOCK_REF_XOSC_50MHZ][SYSTEM_CLOCK_FREQ_100MHZ] = {0, 0, 0, 0, 0},
[SYSTEM_CLOCK_REF_XOSC_50MHZ][SYSTEM_CLOCK_FREQ_120MHZ] = {0, 0, 0, 0, 0},
[SYSTEM_CLOCK_REF_XOSC_50MHZ][SYSTEM_CLOCK_FREQ_125MHZ] = {0, 0, 0, 0, 0},
[SYSTEM_CLOCK_REF_XOSC_50MHZ][SYSTEM_CLOCK_FREQ_144MHZ] = {0, 0, 0, 0, 0},
[SYSTEM_CLOCK_REF_XOSC_50MHZ][SYSTEM_CLOCK_FREQ_150MHZ] = {0, 0, 0, 0, 0},
[SYSTEM_CLOCK_REF_XOSC_50MHZ][SYSTEM_CLOCK_FREQ_192MHZ] = {0, 0, 0, 0, 0},
[SYSTEM_CLOCK_REF_XOSC_50MHZ][SYSTEM_CLOCK_FREQ_200MHZ] = {0, 0, 0, 0, 0},
[SYSTEM_CLOCK_REF_XOSC_50MHZ][SYSTEM_CLOCK_FREQ_240MHZ] = {0, 0, 0, 0, 0},
[SYSTEM_CLOCK_REF_XOSC_50MHZ][SYSTEM_CLOCK_FREQ_250MHZ] = {0, 0, 0, 0, 0},
[SYSTEM_CLOCK_REF_XOSC_50MHZ][SYSTEM_CLOCK_FREQ_384MHZ] = {0, 0, 0, 0, 0},
[SYSTEM_CLOCK_REF_XOSC_50MHZ][SYSTEM_CLOCK_FREQ_320MHZ] = {0, 0, 0, 0, 0},
[SYSTEM_CLOCK_REF_XOSC_50MHZ][SYSTEM_CLOCK_FREQ_400MHZ] = {0, 0, 0, 0, 0},
};
void system_clock_config(uint8_t ref_xosc, uint8_t sys_freq)
{
system_regulator_set(SYSTEM_REGULATOR_VOLTAGE_1P30V);
clock_ref_set(CLOCK_REF_SRC_XOSC_GLITCHLESS, 1);
clock_sys_set(CLOCK_SYS_SRC_REF_GLITCHLESS, 1);
clock_syspll_init(system_clock_cfg_para[ref_xosc][sys_freq][0], \
system_clock_cfg_para[ref_xosc][sys_freq][1], \
system_clock_cfg_para[ref_xosc][sys_freq][2], \
system_clock_cfg_para[ref_xosc][sys_freq][3]);
clock_sys_set(CLOCK_SYS_SRC_SYSPLL, system_clock_cfg_para[ref_xosc][sys_freq][4]);
clock_peri_set(ENABLE, CLOCK_PERI_SRC_SYSPLL);
}