diff --git a/include/libopencm3/stm32/f1/rcc.h b/include/libopencm3/stm32/f1/rcc.h index 855e43bb..52b3469c 100644 --- a/include/libopencm3/stm32/f1/rcc.h +++ b/include/libopencm3/stm32/f1/rcc.h @@ -86,7 +86,7 @@ LGPL License Terms @ref lgpl_license #define RCC_CFGR_MCO_SYSCLK 0x4 #define RCC_CFGR_MCO_HSICLK 0x5 #define RCC_CFGR_MCO_HSECLK 0x6 -#define RCC_CFGR_RMCO_PLLCLK_DIV2 0x7 +#define RCC_CFGR_MCO_PLLCLK_DIV2 0x7 #define RCC_CFGR_MCO_PLL2CLK 0x8 /* (**) */ #define RCC_CFGR_MCO_PLL3CLK_DIV2 0x9 /* (**) */ #define RCC_CFGR_MCO_XT1 0xa /* (**) */ @@ -448,6 +448,24 @@ LGPL License Terms @ref lgpl_license #define RCC_CFGR2_PLL2MUL_PLL2_CLK_MUL16 0xe #define RCC_CFGR2_PLL2MUL_PLL2_CLK_MUL20 0xf +/* PREDIV: PREDIV division factor */ +#define RCC_CFGR2_PREDIV_NODIV 0x0 +#define RCC_CFGR2_PREDIV_DIV2 0x1 +#define RCC_CFGR2_PREDIV_DIV3 0x2 +#define RCC_CFGR2_PREDIV_DIV4 0x3 +#define RCC_CFGR2_PREDIV_DIV5 0x4 +#define RCC_CFGR2_PREDIV_DIV6 0x5 +#define RCC_CFGR2_PREDIV_DIV7 0x6 +#define RCC_CFGR2_PREDIV_DIV8 0x7 +#define RCC_CFGR2_PREDIV_DIV9 0x8 +#define RCC_CFGR2_PREDIV_DIV10 0x9 +#define RCC_CFGR2_PREDIV_DIV11 0xa +#define RCC_CFGR2_PREDIV_DIV12 0xb +#define RCC_CFGR2_PREDIV_DIV13 0xc +#define RCC_CFGR2_PREDIV_DIV14 0xd +#define RCC_CFGR2_PREDIV_DIV15 0xe +#define RCC_CFGR2_PREDIV_DIV16 0xf + /* PREDIV2: PREDIV2 division factor */ #define RCC_CFGR2_PREDIV2_NODIV 0x0 #define RCC_CFGR2_PREDIV2_DIV2 0x1 @@ -473,7 +491,7 @@ extern u32 rcc_ppre2_frequency; /* --- Function prototypes ------------------------------------------------- */ typedef enum { - PLL, HSE, HSI, LSE, LSI + PLL, PLL2, PLL3, HSE, HSI, LSE, LSI } osc_t; BEGIN_DECLS @@ -497,6 +515,7 @@ void rcc_peripheral_reset(volatile u32 *reg, u32 reset); void rcc_peripheral_clear_reset(volatile u32 *reg, u32 clear_reset); void rcc_set_sysclk_source(u32 clk); void rcc_set_pll_multiplication_factor(u32 mul); +void rcc_set_pll2_multiplication_factor(u32 mul); void rcc_set_pll_source(u32 pllsrc); void rcc_set_pllxtpre(u32 pllxtpre); void rcc_set_adcpre(u32 adcpre); @@ -512,6 +531,7 @@ void rcc_clock_setup_in_hse_8mhz_out_24mhz(void); void rcc_clock_setup_in_hse_8mhz_out_72mhz(void); void rcc_clock_setup_in_hse_12mhz_out_72mhz(void); void rcc_clock_setup_in_hse_16mhz_out_72mhz(void); +void rcc_clock_setup_in_hse_25mhz_out_72mhz(void); void rcc_backupdomain_reset(void); END_DECLS diff --git a/lib/stm32/f1/rcc.c b/lib/stm32/f1/rcc.c index ab3350b2..9cd86588 100644 --- a/lib/stm32/f1/rcc.c +++ b/lib/stm32/f1/rcc.c @@ -71,6 +71,12 @@ void rcc_osc_ready_int_clear(osc_t osc) case PLL: RCC_CIR |= RCC_CIR_PLLRDYC; break; + case PLL2: + RCC_CIR |= RCC_CIR_PLL2RDYC; + break; + case PLL3: + RCC_CIR |= RCC_CIR_PLL3RDYC; + break; case HSE: RCC_CIR |= RCC_CIR_HSERDYC; break; @@ -98,6 +104,12 @@ void rcc_osc_ready_int_enable(osc_t osc) case PLL: RCC_CIR |= RCC_CIR_PLLRDYIE; break; + case PLL2: + RCC_CIR |= RCC_CIR_PLL2RDYIE; + break; + case PLL3: + RCC_CIR |= RCC_CIR_PLL3RDYIE; + break; case HSE: RCC_CIR |= RCC_CIR_HSERDYIE; break; @@ -125,6 +137,12 @@ void rcc_osc_ready_int_disable(osc_t osc) case PLL: RCC_CIR &= ~RCC_CIR_PLLRDYIE; break; + case PLL2: + RCC_CIR &= ~RCC_CIR_PLL2RDYIE; + break; + case PLL3: + RCC_CIR &= ~RCC_CIR_PLL3RDYIE; + break; case HSE: RCC_CIR &= ~RCC_CIR_HSERDYIE; break; @@ -153,6 +171,12 @@ int rcc_osc_ready_int_flag(osc_t osc) case PLL: return ((RCC_CIR & RCC_CIR_PLLRDYF) != 0); break; + case PLL2: + return ((RCC_CIR & RCC_CIR_PLL2RDYF) != 0); + break; + case PLL3: + return ((RCC_CIR & RCC_CIR_PLL3RDYF) != 0); + break; case HSE: return ((RCC_CIR & RCC_CIR_HSERDYF) != 0); break; @@ -203,6 +227,12 @@ void rcc_wait_for_osc_ready(osc_t osc) case PLL: while ((RCC_CR & RCC_CR_PLLRDY) == 0); break; + case PLL2: + while ((RCC_CR & RCC_CR_PLL2RDY) == 0); + break; + case PLL3: + while ((RCC_CR & RCC_CR_PLL3RDY) == 0); + break; case HSE: while ((RCC_CR & RCC_CR_HSERDY) == 0); break; @@ -238,6 +268,12 @@ void rcc_osc_on(osc_t osc) case PLL: RCC_CR |= RCC_CR_PLLON; break; + case PLL2: + RCC_CR |= RCC_CR_PLL2ON; + break; + case PLL3: + RCC_CR |= RCC_CR_PLL3ON; + break; case HSE: RCC_CR |= RCC_CR_HSEON; break; @@ -273,6 +309,12 @@ void rcc_osc_off(osc_t osc) case PLL: RCC_CR &= ~RCC_CR_PLLON; break; + case PLL2: + RCC_CR &= ~RCC_CR_PLL2ON; + break; + case PLL3: + RCC_CR &= ~RCC_CR_PLL3ON; + break; case HSE: RCC_CR &= ~RCC_CR_HSEON; break; @@ -331,6 +373,8 @@ void rcc_osc_bypass_enable(osc_t osc) RCC_BDCR |= RCC_BDCR_LSEBYP; break; case PLL: + case PLL2: + case PLL3: case HSI: case LSI: /* Do nothing, only HSE/LSE allowed here. */ @@ -361,6 +405,8 @@ void rcc_osc_bypass_disable(osc_t osc) RCC_BDCR &= ~RCC_BDCR_LSEBYP; break; case PLL: + case PLL2: + case PLL3: case HSI: case LSI: /* Do nothing, only HSE/LSE allowed here. */ @@ -484,6 +530,40 @@ void rcc_set_pll_multiplication_factor(u32 mul) RCC_CFGR = (reg32 | (mul << 18)); } +/*-----------------------------------------------------------------------------*/ +/** @brief RCC Set the PLL2 Multiplication Factor. + +@note This only has effect when the PLL is disabled. + +@param[in] mul Unsigned int32. PLL multiplication factor @ref rcc_cfgr_pmf +*/ + +void rcc_set_pll2_multiplication_factor(u32 mul) +{ + u32 reg32; + + reg32 = RCC_CFGR2; + reg32 &= ~((1 << 11) | (1 << 10) | (1 << 9) | (1 << 8)); + RCC_CFGR2 = (reg32 | (mul << 8)); +} + +/*-----------------------------------------------------------------------------*/ +/** @brief RCC Set the PLL3 Multiplication Factor. + +@note This only has effect when the PLL is disabled. + +@param[in] mul Unsigned int32. PLL multiplication factor @ref rcc_cfgr_pmf +*/ + +void rcc_set_pll3_multiplication_factor(u32 mul) +{ + u32 reg32; + + reg32 = RCC_CFGR2; + reg32 &= ~((1 << 15) | (1 << 14) | (1 << 13) | (1 << 12)); + RCC_CFGR2 = (reg32 | (mul << 12)); +} + /*-----------------------------------------------------------------------------*/ /** @brief RCC Set the PLL Clock Source. @@ -602,6 +682,36 @@ void rcc_set_usbpre(u32 usbpre) RCC_CFGR = (reg32 | (usbpre << 22)); } +void rcc_set_prediv1(u32 prediv) +{ + u32 reg32; + reg32 = RCC_CFGR2; + reg32 &= ~(1 << 3) | (1 << 2) | (1 << 1) | (1 << 0); + RCC_CFGR2 |= (reg32 | prediv); +} + +void rcc_set_prediv2(u32 prediv) +{ + u32 reg32; + reg32 = RCC_CFGR2; + reg32 &= ~(1 << 7) | (1 << 6) | (1 << 5) | (1 << 4); + RCC_CFGR2 |= (reg32 | (prediv << 4)); +} + +void rcc_set_prediv1_source(u32 rccsrc) +{ + RCC_CFGR2 &= ~(1 << 16); + RCC_CFGR2 |= (rccsrc << 16); +} + +void rcc_set_mco(u32 mcosrc) +{ + u32 reg32; + reg32 = RCC_CFGR; + reg32 &= ~((1 << 27) | (1 << 26) | (1 << 25) | (1 << 24)); + RCC_CFGR |= (reg32 | (mcosrc << 24)); +} + /*-----------------------------------------------------------------------------*/ /** @brief RCC Get the System Clock Source. @@ -1030,6 +1140,63 @@ void rcc_clock_setup_in_hse_16mhz_out_72mhz(void) rcc_ppre2_frequency = 72000000; } +/*-----------------------------------------------------------------------------*/ +/** @brief RCC Set System Clock PLL at 72MHz from HSE at 25MHz + +*/ + +void rcc_clock_setup_in_hse_25mhz_out_72mhz(void) +{ + /* Enable external high-speed oscillator 25MHz. */ + rcc_osc_on(HSE); + rcc_wait_for_osc_ready(HSE); + rcc_set_sysclk_source(RCC_CFGR_SW_SYSCLKSEL_HSECLK); + + /* + * Sysclk runs with 72MHz -> 2 waitstates. + * 0WS from 0-24MHz + * 1WS from 24-48MHz + * 2WS from 48-72MHz + */ + flash_set_ws(FLASH_LATENCY_2WS); + + /* + * Set prescalers for AHB, ADC, ABP1, ABP2. + * Do this before touching the PLL (TODO: why?). + */ + rcc_set_hpre(RCC_CFGR_HPRE_SYSCLK_NODIV); /* Set. 72MHz Max. 72MHz */ + rcc_set_adcpre(RCC_CFGR_ADCPRE_PCLK2_DIV6); /* Set. 12MHz Max. 14MHz */ + rcc_set_ppre1(RCC_CFGR_PPRE1_HCLK_DIV2); /* Set. 36MHz Max. 36MHz */ + rcc_set_ppre2(RCC_CFGR_PPRE2_HCLK_NODIV); /* Set. 72MHz Max. 72MHz */ + + /* Set pll2 prediv and multiplier */ + rcc_set_prediv2(RCC_CFGR2_PREDIV2_DIV5); + rcc_set_pll2_multiplication_factor(RCC_CFGR2_PLL2MUL_PLL2_CLK_MUL8); + + /* Enable PLL2 oscillator and wait for it to stabilize */ + rcc_osc_on(PLL2); + rcc_wait_for_osc_ready(PLL2); + + /* Set pll1 prediv/multiplier, prediv1 src, and usb predivider */ + rcc_set_pllxtpre(RCC_CFGR_PLLXTPRE_HSE_CLK); + rcc_set_prediv1_source(RCC_CFGR2_PREDIV1SRC_PLL2_CLK); + rcc_set_prediv1(RCC_CFGR2_PREDIV_DIV5); + rcc_set_pll_multiplication_factor(RCC_CFGR_PLLMUL_PLL_CLK_MUL9); + rcc_set_pll_source(RCC_CFGR_PLLSRC_PREDIV1_CLK); + rcc_set_usbpre(RCC_CFGR_USBPRE_PLL_VCO_CLK_DIV3); + + /* enable PLL1 and wait for it to stabilize */ + rcc_osc_on(PLL); + rcc_wait_for_osc_ready(PLL); + + /* Select PLL as SYSCLK source. */ + rcc_set_sysclk_source(RCC_CFGR_SW_SYSCLKSEL_PLLCLK); + + /* Set the peripheral clock frequencies used */ + rcc_ppre1_frequency = 36000000; + rcc_ppre2_frequency = 72000000; +} + /*-----------------------------------------------------------------------------*/ /** @brief RCC Reset the backup domain