stm32f1: rcc: provide struct based clock helpers
As on every other family. Fixes: https://github.com/libopencm3/libopencm3/issues/1172
This commit is contained in:
parent
a7902aa4d0
commit
5f051241a8
|
@ -704,6 +704,45 @@ enum rcc_periph_rst {
|
|||
|
||||
#include <libopencm3/stm32/common/rcc_common_all.h>
|
||||
|
||||
enum rcc_clock_hsi {
|
||||
RCC_CLOCK_HSI_24MHZ,
|
||||
RCC_CLOCK_HSI_48MHZ,
|
||||
RCC_CLOCK_HSI_64MHZ,
|
||||
RCC_CLOCK_HSI_END
|
||||
};
|
||||
|
||||
enum rcc_clock_hse {
|
||||
RCC_CLOCK_HSE12_72MHZ,
|
||||
RCC_CLOCK_HSE16_72MHZ,
|
||||
RCC_CLOCK_HSE25_72MHZ,
|
||||
RCC_CLOCK_HSE8_24MHZ,
|
||||
RCC_CLOCK_HSE8_72MHZ,
|
||||
RCC_CLOCK_HSE_END
|
||||
};
|
||||
|
||||
/* Union of all options for f100 through to f107 */
|
||||
struct rcc_clock_scale {
|
||||
uint8_t pll_mul;
|
||||
uint8_t pll_source;
|
||||
uint8_t hpre;
|
||||
uint8_t ppre1;
|
||||
uint8_t ppre2;
|
||||
uint8_t adcpre;
|
||||
uint8_t flash_waitstates;
|
||||
uint8_t prediv1; /* aka xtpre, only one bit on smaller parts */
|
||||
uint8_t prediv1_source;
|
||||
uint8_t prediv2;
|
||||
uint8_t pll2_mul;
|
||||
uint8_t pll3_mul;
|
||||
uint8_t usbpre;
|
||||
uint32_t ahb_frequency;
|
||||
uint32_t apb1_frequency;
|
||||
uint32_t apb2_frequency;
|
||||
};
|
||||
|
||||
extern const struct rcc_clock_scale rcc_hsi_configs[RCC_CLOCK_HSI_END];
|
||||
extern const struct rcc_clock_scale rcc_hse_configs[RCC_CLOCK_HSE_END];
|
||||
|
||||
BEGIN_DECLS
|
||||
|
||||
void rcc_osc_ready_int_clear(enum rcc_osc osc);
|
||||
|
@ -742,6 +781,14 @@ 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);
|
||||
|
||||
/**
|
||||
* Switch sysclock to PLL with the given parameters.
|
||||
* This should be usable from any point in time, but only if you have used
|
||||
* library functions to manage clocks.
|
||||
* @param clock full struct with desired parameters
|
||||
*/
|
||||
void rcc_clock_setup_pll(const struct rcc_clock_scale *clock);
|
||||
void rcc_backupdomain_reset(void);
|
||||
|
||||
END_DECLS
|
||||
|
|
|
@ -58,6 +58,129 @@ uint32_t rcc_apb1_frequency = 8000000;
|
|||
uint32_t rcc_apb2_frequency = 8000000;
|
||||
uint32_t rcc_ahb_frequency = 8000000;
|
||||
|
||||
const struct rcc_clock_scale rcc_hse_configs[RCC_CLOCK_HSE_END] = {
|
||||
{
|
||||
/* hse-12, pll to 72 */
|
||||
.pll_source = RCC_CFGR_PLLSRC_HSE_CLK,
|
||||
.pll_mul = RCC_CFGR_PLLMUL_PLL_CLK_MUL6,
|
||||
.prediv1 = RCC_CFGR2_PREDIV_NODIV,
|
||||
.hpre = RCC_CFGR_HPRE_NODIV,
|
||||
.ppre1 = RCC_CFGR_PPRE_DIV2,
|
||||
.ppre2 = RCC_CFGR_PPRE_NODIV,
|
||||
.adcpre = RCC_CFGR_ADCPRE_DIV6,
|
||||
.flash_waitstates = 2,
|
||||
.ahb_frequency = 72000000,
|
||||
.apb1_frequency = 36000000,
|
||||
.apb2_frequency = 72000000,
|
||||
},
|
||||
{
|
||||
/* hse16, pll to 72 */
|
||||
.pll_mul = RCC_CFGR_PLLMUL_PLL_CLK_MUL9,
|
||||
.pll_source = RCC_CFGR_PLLSRC_HSE_CLK,
|
||||
.hpre = RCC_CFGR_HPRE_NODIV,
|
||||
.ppre1 = RCC_CFGR_PPRE_DIV2,
|
||||
.ppre2 = RCC_CFGR_PPRE_NODIV,
|
||||
.adcpre = RCC_CFGR_ADCPRE_DIV6,
|
||||
.flash_waitstates = 2,
|
||||
.prediv1 = RCC_CFGR2_PREDIV_DIV2,
|
||||
.ahb_frequency = 72e6,
|
||||
.apb1_frequency = 36e6,
|
||||
.apb2_frequency = 72e6,
|
||||
},
|
||||
{
|
||||
/* hse25 to 72, this was a f105 config originally! intention preserved */
|
||||
.pll_mul = RCC_CFGR_PLLMUL_PLL_CLK_MUL9,
|
||||
.pll_source = RCC_CFGR_PLLSRC_PREDIV1_CLK,
|
||||
.hpre = RCC_CFGR_HPRE_NODIV,
|
||||
.ppre1 = RCC_CFGR_PPRE_DIV2,
|
||||
.ppre2 = RCC_CFGR_PPRE_NODIV,
|
||||
.adcpre = RCC_CFGR_ADCPRE_DIV6,
|
||||
.flash_waitstates = 2,
|
||||
.prediv1 = RCC_CFGR2_PREDIV_DIV5,
|
||||
.prediv1_source = RCC_CFGR2_PREDIV1SRC_PLL2_CLK,
|
||||
.pll2_mul = RCC_CFGR2_PLL2MUL_PLL2_CLK_MUL8,
|
||||
.prediv2 = RCC_CFGR2_PREDIV2_DIV5,
|
||||
.usbpre = RCC_CFGR_USBPRE_PLL_VCO_CLK_DIV3,
|
||||
.ahb_frequency = 72e6,
|
||||
.apb1_frequency = 36e6,
|
||||
.apb2_frequency = 72e6,
|
||||
},
|
||||
{
|
||||
/* hse8, pll to 24 (f100 value line max) */
|
||||
.pll_mul = RCC_CFGR_PLLMUL_PLL_CLK_MUL3,
|
||||
.pll_source = RCC_CFGR_PLLSRC_HSE_CLK,
|
||||
.hpre = RCC_CFGR_HPRE_NODIV,
|
||||
.ppre1 = RCC_CFGR_PPRE_NODIV,
|
||||
.ppre2 = RCC_CFGR_PPRE_NODIV,
|
||||
.adcpre = RCC_CFGR_ADCPRE_DIV2,
|
||||
.flash_waitstates = 0,
|
||||
.prediv1 = RCC_CFGR2_PREDIV_NODIV,
|
||||
.ahb_frequency = 24e6,
|
||||
.apb1_frequency = 24e6,
|
||||
.apb2_frequency = 24e6,
|
||||
},
|
||||
{
|
||||
/* hse8, pll to 72 */
|
||||
.pll_mul = RCC_CFGR_PLLMUL_PLL_CLK_MUL9,
|
||||
.pll_source = RCC_CFGR_PLLSRC_HSE_CLK,
|
||||
.hpre = RCC_CFGR_HPRE_NODIV,
|
||||
.ppre1 = RCC_CFGR_PPRE_DIV2,
|
||||
.ppre2 = RCC_CFGR_PPRE_NODIV,
|
||||
.adcpre = RCC_CFGR_ADCPRE_DIV8,
|
||||
.flash_waitstates = 2,
|
||||
.prediv1 = RCC_CFGR2_PREDIV_NODIV,
|
||||
.ahb_frequency = 72e6,
|
||||
.apb1_frequency = 36e6,
|
||||
.apb2_frequency = 72e6,
|
||||
},
|
||||
};
|
||||
|
||||
const struct rcc_clock_scale rcc_hsi_configs[RCC_CLOCK_HSI_END] = {
|
||||
{
|
||||
/* hsi to 24Mhz, max for f100 */
|
||||
.pll_source = RCC_CFGR_PLLSRC_HSI_CLK_DIV2,
|
||||
.pll_mul = RCC_CFGR_PLLMUL_PLL_CLK_MUL6,
|
||||
.prediv1 = RCC_CFGR2_PREDIV_NODIV,
|
||||
.hpre = RCC_CFGR_HPRE_NODIV,
|
||||
.ppre1 = RCC_CFGR_PPRE_NODIV,
|
||||
.ppre2 = RCC_CFGR_PPRE_NODIV,
|
||||
.adcpre = RCC_CFGR_ADCPRE_DIV2,
|
||||
.flash_waitstates = 0,
|
||||
.ahb_frequency = 24e6,
|
||||
.apb1_frequency = 24e6,
|
||||
.apb2_frequency = 24e6,
|
||||
},
|
||||
{
|
||||
/* hsi to 48Mhz, allows usb, but out of spec */
|
||||
.pll_source = RCC_CFGR_PLLSRC_HSI_CLK_DIV2,
|
||||
.pll_mul = RCC_CFGR_PLLMUL_PLL_CLK_MUL12,
|
||||
.prediv1 = RCC_CFGR2_PREDIV_NODIV,
|
||||
.hpre = RCC_CFGR_HPRE_NODIV,
|
||||
.ppre1 = RCC_CFGR_PPRE_DIV2,
|
||||
.ppre2 = RCC_CFGR_PPRE_NODIV,
|
||||
.adcpre = RCC_CFGR_ADCPRE_DIV8,
|
||||
.usbpre = RCC_CFGR_USBPRE_PLL_CLK_NODIV,
|
||||
.flash_waitstates = 1,
|
||||
.ahb_frequency = 48e6,
|
||||
.apb1_frequency = 24e6,
|
||||
.apb2_frequency = 48e6,
|
||||
},
|
||||
{
|
||||
/* hsi to 64Mhz, max possible from hsi */
|
||||
.pll_source = RCC_CFGR_PLLSRC_HSI_CLK_DIV2,
|
||||
.pll_mul = RCC_CFGR_PLLMUL_PLL_CLK_MUL16,
|
||||
.prediv1 = RCC_CFGR2_PREDIV_NODIV,
|
||||
.hpre = RCC_CFGR_HPRE_NODIV,
|
||||
.ppre1 = RCC_CFGR_PPRE_DIV2,
|
||||
.ppre2 = RCC_CFGR_PPRE_NODIV,
|
||||
.adcpre = RCC_CFGR_ADCPRE_DIV8,
|
||||
.flash_waitstates = 2,
|
||||
.ahb_frequency = 64e6,
|
||||
.apb1_frequency = 32e6,
|
||||
.apb2_frequency = 64e6,
|
||||
},
|
||||
};
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @brief RCC Clear the Oscillator Ready Interrupt Flag
|
||||
|
||||
|
@ -1087,6 +1210,69 @@ void rcc_clock_setup_in_hse_25mhz_out_72mhz(void)
|
|||
rcc_apb2_frequency = 72000000;
|
||||
}
|
||||
|
||||
void rcc_clock_setup_pll(const struct rcc_clock_scale *clock)
|
||||
{
|
||||
if (clock->pll_source == RCC_CFGR_PLLSRC_HSE_CLK) {
|
||||
rcc_osc_on(RCC_HSE);
|
||||
rcc_wait_for_osc_ready(RCC_HSE);
|
||||
} else {
|
||||
rcc_osc_on(RCC_HSI);
|
||||
rcc_wait_for_osc_ready(RCC_HSI);
|
||||
}
|
||||
rcc_set_hpre(clock->hpre);
|
||||
rcc_set_ppre1(clock->ppre1);
|
||||
rcc_set_ppre2(clock->ppre2);
|
||||
rcc_set_adcpre(clock->adcpre);
|
||||
rcc_set_usbpre(clock->usbpre);
|
||||
flash_set_ws(clock->flash_waitstates);
|
||||
|
||||
rcc_set_pll_multiplication_factor(clock->pll_mul);
|
||||
rcc_set_pll_source(clock->pll_source);
|
||||
|
||||
/*
|
||||
* Magically handle F105/7 parts too.
|
||||
* xtpre == prediv1 bit 0.
|
||||
*/
|
||||
if (clock->prediv1 > RCC_CFGR2_PREDIV_DIV2) {
|
||||
rcc_set_prediv1(clock->prediv1);
|
||||
} else {
|
||||
rcc_set_pllxtpre(clock->prediv1);
|
||||
}
|
||||
if (clock->prediv1_source) {
|
||||
rcc_set_prediv1_source(clock->prediv1_source);
|
||||
}
|
||||
|
||||
/*
|
||||
* Magically handle other plls/prescalers on other parts
|
||||
*/
|
||||
if (clock->prediv2) {
|
||||
rcc_set_prediv2(clock->prediv2);
|
||||
}
|
||||
if (clock->pll2_mul) {
|
||||
rcc_set_pll2_multiplication_factor(clock->pll2_mul);
|
||||
rcc_osc_on(RCC_PLL2);
|
||||
rcc_wait_for_osc_ready(RCC_PLL2);
|
||||
}
|
||||
if (clock->pll3_mul) {
|
||||
rcc_set_pll3_multiplication_factor(clock->pll3_mul);
|
||||
rcc_osc_on(RCC_PLL3);
|
||||
rcc_wait_for_osc_ready(RCC_PLL3);
|
||||
}
|
||||
|
||||
/* Enable PLL oscillator and wait for it to stabilize. */
|
||||
rcc_osc_on(RCC_PLL);
|
||||
rcc_wait_for_osc_ready(RCC_PLL);
|
||||
|
||||
/* Select PLL as SYSCLK source. */
|
||||
rcc_set_sysclk_source(RCC_CFGR_SW_SYSCLKSEL_PLLCLK);
|
||||
|
||||
/* Set the peripheral clock frequencies used. */
|
||||
rcc_ahb_frequency = clock->ahb_frequency;
|
||||
rcc_apb1_frequency = clock->apb1_frequency;
|
||||
rcc_apb2_frequency = clock->apb2_frequency;
|
||||
}
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @brief RCC Reset the Backup Domain
|
||||
|
||||
|
|
Loading…
Reference in New Issue