#include <stdint.h> | #include <stdint.h> | ||||
#include "imxrt.h" | |||||
#include "wiring.h" | |||||
#include "debug/printf.h" | |||||
volatile uint32_t F_CPU_ACTUAL = 396000000; | volatile uint32_t F_CPU_ACTUAL = 396000000; | ||||
volatile uint32_t F_BUS_ACTUAL = 132000000; | volatile uint32_t F_BUS_ACTUAL = 132000000; | ||||
// Define these to increase the voltage when attempting overclocking | |||||
// The frequency step is how quickly to increase voltage per frequency | |||||
// The datasheet says 1300 is the absolute maximum voltage. The hardware | |||||
// can actually create up to 1575, but going over 1300 risks damage! | |||||
#define OVERCLOCK_STEPSIZE 28000000 | |||||
#define OVERCLOCK_MAX_VOLT 1300 | |||||
//#define OVERCLOCK_MAX_VOLT 1575 // Danger Will Robinson! | |||||
uint32_t set_arm_clock(uint32_t frequency); | |||||
// stuff needing wait handshake: | |||||
// CCM_CACRR ARM_PODF | |||||
// CCM_CBCDR PERIPH_CLK_SEL | |||||
// CCM_CBCMR PERIPH2_CLK_SEL | |||||
// CCM_CBCDR AHB_PODF | |||||
// CCM_CBCDR SEMC_PODF | |||||
uint32_t set_arm_clock(uint32_t frequency) | |||||
{ | |||||
uint32_t cbcdr = CCM_CBCDR; // pg 1021 | |||||
uint32_t cbcmr = CCM_CBCMR; // pg 1023 | |||||
uint32_t dcdc = DCDC_REG3; | |||||
// compute required voltage | |||||
uint32_t voltage = 1150; // default = 1.15V | |||||
if (frequency > 528000000) { | |||||
voltage = 1250; // 1.25V | |||||
#if defined(OVERCLOCK_STEPSIZE) && defined(OVERCLOCK_MAX_VOLT) | |||||
if (frequency > 600000000) { | |||||
voltage += ((frequency - 600000000) / OVERCLOCK_STEPSIZE) * 25; | |||||
if (voltage > OVERCLOCK_MAX_VOLT) voltage = OVERCLOCK_MAX_VOLT; | |||||
} | |||||
#endif | |||||
} else if (frequency <= 24) { | |||||
voltage = 950; // 0.95 | |||||
} | |||||
// if voltage needs to increase, do it before switch clock speed | |||||
CCM_CCGR6 |= CCM_CCGR6_DCDC(CCM_CCGR_ON); | |||||
if ((dcdc & DCDC_REG3_TRG_MASK) < DCDC_REG3_TRG((voltage - 800) / 25)) { | |||||
printf("Increasing voltage to %u mV\n", voltage); | |||||
dcdc &= ~DCDC_REG3_TRG_MASK; | |||||
dcdc |= DCDC_REG3_TRG((voltage - 800) / 25); | |||||
DCDC_REG3 = dcdc; | |||||
while (!(DCDC_REG0 & DCDC_REG0_STS_DC_OK)) ; // wait voltage settling | |||||
} | |||||
if (!(cbcdr & CCM_CBCDR_PERIPH_CLK_SEL)) { | |||||
printf("need to switch to alternate clock during reconfigure of ARM PLL\n"); | |||||
const uint32_t need1s = CCM_ANALOG_PLL_USB1_ENABLE | CCM_ANALOG_PLL_USB1_POWER | | |||||
CCM_ANALOG_PLL_USB1_LOCK | CCM_ANALOG_PLL_USB1_EN_USB_CLKS; | |||||
uint32_t sel, div; | |||||
if ((CCM_ANALOG_PLL_USB1 & need1s) == need1s) { | |||||
printf("USB PLL is running, so we can use 120 MHz\n"); | |||||
sel = 0; | |||||
div = 3; // divide down to 120 MHz, so IPG is ok even if IPG_PODF=0 | |||||
} else { | |||||
printf("USB PLL is off, use 24 MHz crystal\n"); | |||||
sel = 1; | |||||
div = 0; | |||||
} | |||||
if ((cbcdr & CCM_CBCDR_PERIPH_CLK2_PODF_MASK) != CCM_CBCDR_PERIPH_CLK2_PODF(div)) { | |||||
// PERIPH_CLK2 divider needs to be changed | |||||
cbcdr &= ~CCM_CBCDR_PERIPH_CLK2_PODF_MASK; | |||||
cbcdr |= CCM_CBCDR_PERIPH_CLK2_PODF(div); | |||||
CCM_CBCDR = cbcdr; | |||||
} | |||||
if ((cbcmr & CCM_CBCMR_PERIPH_CLK2_SEL_MASK) != CCM_CBCMR_PERIPH_CLK2_SEL(sel)) { | |||||
// PERIPH_CLK2 source select needs to be changed | |||||
cbcmr &= ~CCM_CBCMR_PERIPH_CLK2_SEL_MASK; | |||||
cbcmr |= CCM_CBCMR_PERIPH_CLK2_SEL(sel); | |||||
CCM_CBCMR = cbcmr; | |||||
while (CCM_CDHIPR & CCM_CDHIPR_PERIPH2_CLK_SEL_BUSY) ; // wait | |||||
} | |||||
// switch over to PERIPH_CLK2 | |||||
cbcdr |= CCM_CBCDR_PERIPH_CLK_SEL; | |||||
CCM_CBCDR = cbcdr; | |||||
while (CCM_CDHIPR & CCM_CDHIPR_PERIPH_CLK_SEL_BUSY) ; // wait | |||||
} else { | |||||
printf("already running from PERIPH_CLK2, safe to mess with ARM PLL\n"); | |||||
} | |||||
// TODO: check if PLL2 running, can 352, 396 or 528 can work? (no need for ARM PLL) | |||||
// DIV_SELECT: 54-108 = official range 648 to 1296 in 12 MHz steps | |||||
uint32_t div_arm = 1; | |||||
uint32_t div_ahb = 1; | |||||
while (frequency * div_arm * div_ahb < 648000000) { | |||||
if (div_arm < 8) { | |||||
div_arm = div_arm + 1; | |||||
} else { | |||||
if (div_ahb < 5) { | |||||
div_ahb = div_ahb + 1; | |||||
div_arm = 1; | |||||
} else { | |||||
break; | |||||
} | |||||
} | |||||
} | |||||
uint32_t mult = (frequency * div_arm * div_ahb + 6000000) / 12000000; | |||||
if (mult > 108) mult = 108; | |||||
if (mult < 54) mult = 54; | |||||
printf("Freq: 12 MHz * %u / %u / %u\n", mult, div_arm, div_ahb); | |||||
frequency = mult * 12000000 / div_arm / div_ahb; | |||||
printf("ARM PLL=%x\n", CCM_ANALOG_PLL_ARM); | |||||
const uint32_t arm_pll_mask = CCM_ANALOG_PLL_ARM_LOCK | CCM_ANALOG_PLL_ARM_BYPASS | | |||||
CCM_ANALOG_PLL_ARM_ENABLE | CCM_ANALOG_PLL_ARM_POWERDOWN | | |||||
CCM_ANALOG_PLL_ARM_DIV_SELECT_MASK; | |||||
if ((CCM_ANALOG_PLL_ARM & arm_pll_mask) != (CCM_ANALOG_PLL_ARM_LOCK | |||||
| CCM_ANALOG_PLL_ARM_ENABLE | CCM_ANALOG_PLL_ARM_DIV_SELECT(mult))) { | |||||
printf("ARM PLL needs reconfigure\n"); | |||||
CCM_ANALOG_PLL_ARM = CCM_ANALOG_PLL_ARM_POWERDOWN; | |||||
// TODO: delay needed? | |||||
CCM_ANALOG_PLL_ARM = CCM_ANALOG_PLL_ARM_ENABLE | |||||
| CCM_ANALOG_PLL_ARM_DIV_SELECT(mult); | |||||
while (!(CCM_ANALOG_PLL_ARM & CCM_ANALOG_PLL_ARM_LOCK)) ; // wait for lock | |||||
printf("ARM PLL=%x\n", CCM_ANALOG_PLL_ARM); | |||||
} else { | |||||
printf("ARM PLL already running at required frequency\n"); | |||||
} | |||||
if ((CCM_CACRR & CCM_CACRR_ARM_PODF_MASK) != (div_arm - 1)) { | |||||
CCM_CACRR = CCM_CACRR_ARM_PODF(div_arm - 1); | |||||
while (CCM_CDHIPR & CCM_CDHIPR_ARM_PODF_BUSY) ; // wait | |||||
} | |||||
if ((cbcdr & CCM_CBCDR_AHB_PODF_MASK) != CCM_CBCDR_AHB_PODF(div_ahb - 1)) { | |||||
cbcdr &= ~CCM_CBCDR_AHB_PODF_MASK; | |||||
cbcdr |= CCM_CBCDR_AHB_PODF(div_ahb - 1); | |||||
CCM_CBCDR = cbcdr; | |||||
while (CCM_CDHIPR & CCM_CDHIPR_AHB_PODF_BUSY); // wait | |||||
} | |||||
uint32_t div_ipg = (frequency + 149999999) / 150000000; | |||||
if (div_ipg > 4) div_ipg = 4; | |||||
if ((cbcdr & CCM_CBCDR_IPG_PODF_MASK) != (CCM_CBCDR_IPG_PODF(div_ipg - 1))) { | |||||
cbcdr &= ~CCM_CBCDR_IPG_PODF_MASK; | |||||
cbcdr |= CCM_CBCDR_IPG_PODF(div_ipg - 1); | |||||
// TODO: how to safely change IPG_PODF ?? | |||||
CCM_CBCDR = cbcdr; | |||||
} | |||||
cbcdr &= ~CCM_CBCDR_PERIPH_CLK_SEL; | |||||
CCM_CBCDR = cbcdr; | |||||
while (CCM_CDHIPR & CCM_CDHIPR_PERIPH_CLK_SEL_BUSY) ; // wait | |||||
F_CPU_ACTUAL = frequency; | |||||
F_BUS_ACTUAL = frequency / div_ipg; | |||||
printf("New Frequency: ARM=%u, IPG=%u\n", frequency, frequency / div_ipg); | |||||
// if voltage needs to decrease, do it after switch clock speed | |||||
if ((dcdc & DCDC_REG3_TRG_MASK) > DCDC_REG3_TRG((voltage - 800) / 25)) { | |||||
printf("Decreasing voltage to %u mV\n", voltage); | |||||
dcdc &= ~DCDC_REG3_TRG_MASK; | |||||
dcdc |= DCDC_REG3_TRG((voltage - 800) / 25); | |||||
DCDC_REG3 = dcdc; | |||||
while (!(DCDC_REG0 & DCDC_REG0_STS_DC_OK)) ; // wait voltage settling | |||||
} | |||||
return frequency; | |||||
} | |||||
#ifdef __cplusplus | #ifdef __cplusplus | ||||
extern "C" { | extern "C" { | ||||
#endif | #endif | ||||
void print_debug_init(void); | |||||
void printf_debug_init(void); | |||||
void printf_debug(const char *format, ...); | void printf_debug(const char *format, ...); | ||||
#ifdef __cplusplus | #ifdef __cplusplus | ||||
} | } |
#define CCM_CSR_REF_EN_B ((uint32_t)(1<<0)) | #define CCM_CSR_REF_EN_B ((uint32_t)(1<<0)) | ||||
#define CCM_CCSR_PLL3_SW_CLK_SEL ((uint32_t)(1<<0)) | #define CCM_CCSR_PLL3_SW_CLK_SEL ((uint32_t)(1<<0)) | ||||
#define CCM_CACRR_ARM_PODF(n) ((uint32_t)(((n) & 0x07) << 0)) | #define CCM_CACRR_ARM_PODF(n) ((uint32_t)(((n) & 0x07) << 0)) | ||||
#define CCM_CACRR_ARM_PODF_MASK ((uint32_t)(0x07 << 0)) | |||||
#define CCM_CBCDR_PERIPH_CLK2_PODF(n) ((uint32_t)(((n) & 0x07) << 27)) | #define CCM_CBCDR_PERIPH_CLK2_PODF(n) ((uint32_t)(((n) & 0x07) << 27)) | ||||
#define CCM_CBCDR_PERIPH_CLK2_PODF_MASK ((uint32_t)(0x07 << 27)) | |||||
#define CCM_CBCDR_PERIPH_CLK_SEL ((uint32_t)(1<<25)) | #define CCM_CBCDR_PERIPH_CLK_SEL ((uint32_t)(1<<25)) | ||||
#define CCM_CBCDR_SEMC_PODF(n) ((uint32_t)(((n) & 0x07) << 16)) | #define CCM_CBCDR_SEMC_PODF(n) ((uint32_t)(((n) & 0x07) << 16)) | ||||
#define CCM_CBCDR_AHB_PODF(n) ((uint32_t)(((n) & 0x07) << 10)) | #define CCM_CBCDR_AHB_PODF(n) ((uint32_t)(((n) & 0x07) << 10)) | ||||
#define CCM_CBCDR_AHB_PODF_MASK ((uint32_t)(0x07 << 10)) | |||||
#define CCM_CBCDR_IPG_PODF(n) ((uint32_t)(((n) & 0x03) << 8)) | #define CCM_CBCDR_IPG_PODF(n) ((uint32_t)(((n) & 0x03) << 8)) | ||||
#define CCM_CBCDR_IPG_PODF_MASK ((uint32_t)(0x03 << 8)) | #define CCM_CBCDR_IPG_PODF_MASK ((uint32_t)(0x03 << 8)) | ||||
#define CCM_CBCDR_SEMC_ALT_CLK_SEL ((uint32_t)(1<<7)) | #define CCM_CBCDR_SEMC_ALT_CLK_SEL ((uint32_t)(1<<7)) | ||||
#define CCM_CBCMR_PRE_PERIPH_CLK_SEL(n) ((uint32_t)(((n) & 0x03) << 18)) | #define CCM_CBCMR_PRE_PERIPH_CLK_SEL(n) ((uint32_t)(((n) & 0x03) << 18)) | ||||
#define CCM_CBCMR_TRACE_CLK_SEL(n) ((uint32_t)(((n) & 0x03) << 14)) | #define CCM_CBCMR_TRACE_CLK_SEL(n) ((uint32_t)(((n) & 0x03) << 14)) | ||||
#define CCM_CBCMR_PERIPH_CLK2_SEL(n) ((uint32_t)(((n) & 0x03) << 12)) | #define CCM_CBCMR_PERIPH_CLK2_SEL(n) ((uint32_t)(((n) & 0x03) << 12)) | ||||
#define CCM_CBCMR_PERIPH_CLK2_SEL_MASK ((uint32_t)(0x03 << 12)) | |||||
#define CCM_CBCMR_LPSPI_CLK_SEL(n) ((uint32_t)(((n) & 0x03) << 4)) | #define CCM_CBCMR_LPSPI_CLK_SEL(n) ((uint32_t)(((n) & 0x03) << 4)) | ||||
#define CCM_CBCMR_LPSPI_PODF_MASK ((uint32_t)(0x07 << 26)) | #define CCM_CBCMR_LPSPI_PODF_MASK ((uint32_t)(0x07 << 26)) | ||||
#define CCM_CBCMR_LCDIF_PODF_MASK ((uint32_t)(0x07 << 23)) | #define CCM_CBCMR_LCDIF_PODF_MASK ((uint32_t)(0x07 << 23)) | ||||
#define CCM_ANALOG_MISC2_CLR (IMXRT_CCM_ANALOG.offset178) | #define CCM_ANALOG_MISC2_CLR (IMXRT_CCM_ANALOG.offset178) | ||||
#define CCM_ANALOG_MISC2_TOG (IMXRT_CCM_ANALOG.offset17C) | #define CCM_ANALOG_MISC2_TOG (IMXRT_CCM_ANALOG.offset17C) | ||||
#define CCM_ANALOG_PLL_ARM_LOCK ((uint32_t)(1<<31)) | #define CCM_ANALOG_PLL_ARM_LOCK ((uint32_t)(1<<31)) | ||||
#define CCM_ANALOG_PLL_ARM_BYPASS ((uint32_t)(1<<11)) | |||||
#define CCM_ANALOG_PLL_ARM_ENABLE ((uint32_t)(1<<11)) | |||||
#define CCM_ANALOG_PLL_ARM_POWERDOWN ((uint32_t)(1<<11)) | |||||
#define CCM_ANALOG_PLL_ARM_DIV_SELECT(n) ((uint32_t)(((n) & 0x3F) << 0)) | |||||
#define CCM_ANALOG_PLL_ARM_DIV_SELECT_MASK ((uint32_t)(0x3F << 0)) | |||||
#define CCM_ANALOG_PLL_ARM_BYPASS ((uint32_t)(1<<16)) | |||||
#define CCM_ANALOG_PLL_ARM_ENABLE ((uint32_t)(1<<13)) | |||||
#define CCM_ANALOG_PLL_ARM_POWERDOWN ((uint32_t)(1<<12)) | |||||
#define CCM_ANALOG_PLL_ARM_DIV_SELECT(n) ((uint32_t)(((n) & 0x7F) << 0)) | |||||
#define CCM_ANALOG_PLL_ARM_DIV_SELECT_MASK ((uint32_t)(0x7F << 0)) | |||||
#define CCM_ANALOG_PLL_USB1_LOCK ((uint32_t)(1<<31)) | #define CCM_ANALOG_PLL_USB1_LOCK ((uint32_t)(1<<31)) | ||||
#define CCM_ANALOG_PLL_USB1_BYPASS ((uint32_t)(1<<16)) | #define CCM_ANALOG_PLL_USB1_BYPASS ((uint32_t)(1<<16)) | ||||
#define CCM_ANALOG_PLL_USB1_ENABLE ((uint32_t)(1<<13)) | #define CCM_ANALOG_PLL_USB1_ENABLE ((uint32_t)(1<<13)) | ||||
#define DCDC_REG1 (IMXRT_DCDC.offset004) | #define DCDC_REG1 (IMXRT_DCDC.offset004) | ||||
#define DCDC_REG2 (IMXRT_DCDC.offset008) | #define DCDC_REG2 (IMXRT_DCDC.offset008) | ||||
#define DCDC_REG3 (IMXRT_DCDC.offset00C) | #define DCDC_REG3 (IMXRT_DCDC.offset00C) | ||||
#define DCDC_REG0_STS_DC_OK ((uint32_t)(1<<31)) | |||||
#define DCDC_REG0_XTAL_24M_OK ((uint32_t)(1<<29)) | |||||
#define DCDC_REG0_CURRENT_ALERT_RESET ((uint32_t)(1<<28)) | |||||
#define DCDC_REG0_XTALOK_DISABLE ((uint32_t)(1<<27)) | |||||
#define DCDC_REG0_PWD_CMP_OFFSET ((uint32_t)(1<<26)) | |||||
#define DCDC_REG0_LP_HIGH_HYS ((uint32_t)(1<<21)) | |||||
#define DCDC_REG0_LP_OVERLOAD_FREQ_SEL ((uint32_t)(1<<20)) | |||||
#define DCDC_REG0_LP_OVERLOAD_THRSH(n) ((uint32_t)(((n) & 0x03) << 18)) | |||||
#define DCDC_REG0_PWD_HIGH_VOLT_DET ((uint32_t)(1<<17)) | |||||
#define DCDC_REG0_EN_LP_OVERLOAD_SNS ((uint32_t)(1<<16)) | |||||
#define DCDC_REG0_ADJ_POSLIMIT_BUCK(n) ((uint32_t)(((n) & 0x0F) << 12)) | |||||
#define DCDC_REG0_PWD_CMP_BATT_DET ((uint32_t)(1<<11)) | |||||
#define DCDC_REG0_OVERCUR_TRIG_ADJ(n) ((uint32_t)(((n) & 0x03) << 9)) | |||||
#define DCDC_REG0_PWD_OVERCUR_DET ((uint32_t)(1<<8)) | |||||
#define DCDC_REG0_CUR_SNS_THRSH(n) ((uint32_t)(((n) & 0x07) << 5)) | |||||
#define DCDC_REG0_PWD_CUR_SNS_CMP ((uint32_t)(1<<4)) | |||||
#define DCDC_REG0_PWD_OSC_INT ((uint32_t)(1<<3)) | |||||
#define DCDC_REG0_SEL_CLK ((uint32_t)(1<<2)) | |||||
#define DCDC_REG0_DISABLE_AUTO_CLK_SWITCH ((uint32_t)(1<<1)) | |||||
#define DCDC_REG0_PWD_ZCD ((uint32_t)(1<<0)) | |||||
#define DCDC_REG1_VBG_TRIM(n) ((uint32_t)(((n) & 0x1F) << 24)) | |||||
#define DCDC_REG1_LOOPCTRL_EN_HYST ((uint32_t)(1<<23)) | |||||
#define DCDC_REG1_LOOPCTRL_HST_THRESH ((uint32_t)(1<<21)) | |||||
#define DCDC_REG1_LP_CMP_ISRC_SEL(n) ((uint32_t)(((n) & 0x03) << 12)) | |||||
#define DCDC_REG1_REG_RLOAD_SW ((uint32_t)(1<<9)) | |||||
#define DCDC_REG1_REG_FBK_SEL(n) ((uint32_t)(((n) & 0x03) << 7)) | |||||
#define DCDC_REG2_DCM_SET_CTRL ((uint32_t)(1<<28)) | |||||
#define DCDC_REG2_DISABLE_PULSE_SKIP ((uint32_t)(1<<27)) | |||||
#define DCDC_REG2_LOOPCTRL_HYST_SIGN ((uint32_t)(1<<13)) | |||||
#define DCDC_REG2_LOOPCTRL_RCSCALE_THRSH ((uint32_t)(1<<12)) | |||||
#define DCDC_REG2_LOOPCTRL_EN_RCSCALE ((uint32_t)(((n) & 0x07) << 9)) | |||||
#define DCDC_REG2_LOOPCTRL_DC_FF ((uint32_t)(((n) & 0x07) << 6)) | |||||
#define DCDC_REG2_LOOPCTRL_DC_R ((uint32_t)(((n) & 0x0F) << 2)) | |||||
#define DCDC_REG2_LOOPCTRL_DC_C ((uint32_t)(((n) & 0x03) << 0)) | |||||
#define DCDC_REG3_DISABLE_STEP ((uint32_t)(1<<30)) | |||||
#define DCDC_REG3_MISC_DISABLEFET_LOGIC ((uint32_t)(1<<28)) | |||||
#define DCDC_REG3_MISC_DELAY_TIMING ((uint32_t)(1<<27)) | |||||
#define DCDC_REG3_MINPWR_DC_HALFCLK ((uint32_t)(1<<24)) | |||||
#define DCDC_REG3_TARGET_LP(n) ((uint32_t)(((n) & 0x07) << 8)) | |||||
#define DCDC_REG3_TRG(n) ((uint32_t)(((n) & 0x1F) << 0)) | |||||
#define DCDC_REG3_TRG_MASK ((uint32_t)(0x1F << 0)) | |||||
// 21.4.1.1: page 849 | // 21.4.1.1: page 849 | ||||
#define IMXRT_DMAMUX (*(IMXRT_REGISTER32_t *)0x400EC000) | #define IMXRT_DMAMUX (*(IMXRT_REGISTER32_t *)0x400EC000) | ||||
#define SCB_SCR_SLEEPDEEP ((uint8_t)0x04) // Sleep or Deep Sleep | #define SCB_SCR_SLEEPDEEP ((uint8_t)0x04) // Sleep or Deep Sleep | ||||
#define SCB_SCR_SLEEPONEXIT ((uint8_t)0x02) // Sleep-on-exit | #define SCB_SCR_SLEEPONEXIT ((uint8_t)0x02) // Sleep-on-exit | ||||
#define SCB_CCR (*(volatile uint32_t *)0xE000ED14) // Configuration and Control | #define SCB_CCR (*(volatile uint32_t *)0xE000ED14) // Configuration and Control | ||||
#define SCB_CCR_BP ((uint32_t)(1<<18)) // Branch prediction enable | |||||
#define SCB_CCR_BP ((uint32_t)(1<<18)) // Branch prediction enable | |||||
#define SCB_CCR_IC ((uint32_t)(1<<17)) // Instruction caches enable | #define SCB_CCR_IC ((uint32_t)(1<<17)) // Instruction caches enable | ||||
#define SCB_CCR_DC ((uint32_t)(1<<16)) | #define SCB_CCR_DC ((uint32_t)(1<<16)) | ||||
#define SCB_CCR_STKALIGN ((uint32_t)(1<<9)) | #define SCB_CCR_STKALIGN ((uint32_t)(1<<9)) |
void usb_pll_start(); | void usb_pll_start(); | ||||
extern void analog_init(void); | extern void analog_init(void); | ||||
extern void pwm_init(void); | extern void pwm_init(void); | ||||
uint32_t set_arm_clock(uint32_t frequency); | |||||
__attribute__((section(".startup"))) | __attribute__((section(".startup"))) | ||||
configure_cache(); | configure_cache(); | ||||
configure_systick(); | configure_systick(); | ||||
usb_pll_start(); | usb_pll_start(); | ||||
#if 1 | |||||
//uint32_t pll1; | |||||
//uint32_t n = | |||||
//pll = CCM_ANALOG_PLL_ARM; | |||||
printf("ARM PLL = %08lX\n", CCM_ANALOG_PLL_ARM); | |||||
set_arm_clock(600000000); | |||||
//set_arm_clock(984000000); Ludicrous Speed | |||||
uint32_t cdcdr = CCM_CBCDR; | |||||
uint32_t armpll = CCM_ANALOG_PLL_ARM; | |||||
uint32_t armdiv = CCM_CACRR; | |||||
uint32_t cbcdr = CCM_CBCDR; | |||||
uint32_t cbcmr = CCM_CBCMR; | uint32_t cbcmr = CCM_CBCMR; | ||||
printf("AHB divisor = %ld\n", ((cdcdr >> 10) & 7) + 1); | |||||
printf("IPG divisor = %ld\n", ((cdcdr >> 8) & 3) + 1); | |||||
if (cdcdr & CCM_CBCDR_PERIPH_CLK_SEL) { | |||||
printf("using periph_clk2_clk_divided\n"); | |||||
} else { | |||||
printf("using pre_periph_clk_sel\n"); | |||||
uint32_t n = (cbcmr >> 19) & 3; | |||||
if (n == 0) { | |||||
printf("using PLL2\n"); | |||||
} else if (n == 1) { | |||||
printf("using PLL2 PFD2\n"); | |||||
} else if (n == 2) { | |||||
printf("using PLL2 PFD0\n"); | |||||
} else { | |||||
printf("using PLL1\n"); | |||||
} | |||||
} | |||||
//set_arm_clock(300000000); | |||||
#endif | |||||
printf("ARM PLL = %u MHz\n", (armpll & 0x7F) * 12); | |||||
printf("ARM divisor = %u\n", armdiv + 1); | |||||
printf("AHB divisor = %u\n", ((cbcdr >> 10) & 7) + 1); | |||||
printf("IPG divisor = %u\n", ((cbcdr >> 8) & 3) + 1); | |||||
// TODO: wait at least 20ms before starting USB | // TODO: wait at least 20ms before starting USB | ||||
usb_init(); | usb_init(); | ||||
} | } | ||||
uint32_t set_arm_clock(uint32_t frequency) | |||||
{ | |||||
if (!(CCM_CBCDR & CCM_CBCDR_PERIPH_CLK_SEL)) { | |||||
//print("need to switch to stable clock while reconfigure of ARM PLL\n"); | |||||
const uint32_t need1s = CCM_ANALOG_PLL_USB1_ENABLE | CCM_ANALOG_PLL_USB1_POWER | | |||||
CCM_ANALOG_PLL_USB1_LOCK | CCM_ANALOG_PLL_USB1_EN_USB_CLKS; | |||||
if ((CCM_ANALOG_PLL_USB1 & need1s) == need1s) { | |||||
//print(" run temporarily from USB/4 (120 MHz)\n"); | |||||
} else { | |||||
//print(" run temporarily from crystal (24 MHz)\n"); | |||||
} | |||||
} else { | |||||
//print("already running from an alternate clock, ok to mess with ARM PLL\n"); | |||||
} | |||||
// if SYS PLL running at 528 MHz | |||||
// if frequency == 528 | |||||
// if frequency == 396 | |||||
// if frequency == 352 | |||||
// | |||||
return frequency; | |||||
} | |||||
__attribute__((section(".progmem"))) | __attribute__((section(".progmem"))) | ||||
void usb_pll_start() | void usb_pll_start() | ||||
{ | { |