From b6ee57a5b9fbac7fb1cfe62b6ed8a341bee5543e Mon Sep 17 00:00:00 2001 From: Karl Palsson Date: Tue, 22 Jan 2013 22:52:36 +0000 Subject: [PATCH] [l1] rcc: support MSI clocking Some new definitions and helpers. Main change really that the list of preconfigured clock configs is no longer restricted to HSI/PLL --- include/libopencm3/stm32/l1/rcc.h | 44 +++++++++++++++++--- lib/stm32/l1/rcc.c | 68 ++++++++++++++++++++++++++++++- 2 files changed, 105 insertions(+), 7 deletions(-) diff --git a/include/libopencm3/stm32/l1/rcc.h b/include/libopencm3/stm32/l1/rcc.h index f301ce3d..a751def2 100644 --- a/include/libopencm3/stm32/l1/rcc.h +++ b/include/libopencm3/stm32/l1/rcc.h @@ -82,11 +82,31 @@ LGPL License Terms @ref lgpl_license #define RCC_CR_RTCPRE_DIV2 0 #define RCC_CR_RTCPRE_DIV4 1 #define RCC_CR_RTCPRE_DIV8 2 -#define RCC_CR_RTCPRE_DIV18 3 +#define RCC_CR_RTCPRE_DIV16 3 +#define RCC_CR_RTCPRE_SHIFT 29 +#define RCC_CR_RTCPRE_MASK 0x3 /* --- RCC_ICSCR values ---------------------------------------------------- */ -// TODO +#define RCC_ICSCR_MSITRIM_SHIFT 24 +#define RCC_ICSCR_MSITRIM_MASK 0xff +#define RCC_ICSCR_MSICAL_SHIFT 16 +#define RCC_ICSCR_MSICAL_MASK 0xff + +#define RCC_ICSCR_MSIRANGE_SHIFT 13 +#define RCC_ICSCR_MSIRANGE_MASK 0x7 +#define RCC_ICSCR_MSIRANGE_65KHZ 0x0 +#define RCC_ICSCR_MSIRANGE_131KHZ 0x1 +#define RCC_ICSCR_MSIRANGE_262KHZ 0x2 +#define RCC_ICSCR_MSIRANGE_524KHZ 0x3 +#define RCC_ICSCR_MSIRANGE_1MHZ 0x4 +#define RCC_ICSCR_MSIRANGE_2MHZ 0x5 +#define RCC_ICSCR_MSIRANGE_4MHZ 0x6 + +#define RCC_ICSCR_HSITRIM_SHIFT 8 +#define RCC_ICSCR_HSITRIM_MASK 0x1f +#define RCC_ICSCR_HSICAL_SHIFT 0 +#define RCC_ICSCR_HSICAL_MASK 0xff /* --- RCC_CFGR values ----------------------------------------------------- */ @@ -347,7 +367,14 @@ LGPL License Terms @ref lgpl_license #define RCC_CSR_RMVF (1 << 24) #define RCC_CSR_RTCRST (1 << 23) #define RCC_CSR_RTCEN (1 << 22) -/* RTCSEL[1:0] */ +#define RCC_CSR_RTCSEL_SHIFT (16) +#define RCC_CSR_RTCSEL_MASK (0x3) +#define RCC_CSR_RTCSEL_NONE (0x0) +#define RCC_CSR_RTCSEL_LSE (0x1) +#define RCC_CSR_RTCSEL_LSI (0x2) +#define RCC_CSR_RTCSEL_HSI (0x3) +#define RCC_CSR_LSECSSD (1 << 12) +#define RCC_CSR_LSECSSON (1 << 11) #define RCC_CSR_LSEBYP (1 << 10) #define RCC_CSR_LSERDY (1 << 9) #define RCC_CSR_LSEON (1 << 8) @@ -365,16 +392,20 @@ typedef struct { vos_scale_t voltage_scale; uint32_t apb1_frequency; uint32_t apb2_frequency; + uint8_t msi_range; } clock_scale_t; typedef enum { CLOCK_VRANGE1_HSI_PLL_24MHZ, CLOCK_VRANGE1_HSI_PLL_32MHZ, CLOCK_VRANGE1_HSI_RAW_16MHZ, - CLOCK_VRANGE1_END -} clock_volt_range1_t; + CLOCK_VRANGE1_HSI_RAW_4MHZ, + CLOCK_VRANGE1_MSI_RAW_4MHZ, + CLOCK_VRANGE1_MSI_RAW_2MHZ, + CLOCK_CONFIG_END +} clock_config_entry_t; -extern const clock_scale_t clock_vrange1_config[CLOCK_VRANGE1_END]; +extern const clock_scale_t clock_config[CLOCK_CONFIG_END]; /* --- Variable definitions ------------------------------------------------ */ @@ -413,6 +444,7 @@ void rcc_set_ppre1(u32 ppre1); void rcc_set_hpre(u32 hpre); void rcc_set_usbpre(u32 usbpre); u32 rcc_get_system_clock_source(int i); +void rcc_clock_setup_msi(const clock_scale_t *clock); void rcc_clock_setup_hsi(const clock_scale_t *clock); void rcc_clock_setup_pll(const clock_scale_t *clock); void rcc_backupdomain_reset(void); diff --git a/lib/stm32/l1/rcc.c b/lib/stm32/l1/rcc.c index b2fce8c2..c1d8fa9c 100644 --- a/lib/stm32/l1/rcc.c +++ b/lib/stm32/l1/rcc.c @@ -29,7 +29,8 @@ u32 rcc_ppre1_frequency = 2097000; u32 rcc_ppre2_frequency = 2097000; -const clock_scale_t clock_vrange1_config[CLOCK_VRANGE1_END] ={ +const clock_scale_t clock_config[CLOCK_CONFIG_END] = +{ { /* 24MHz PLL from HSI */ .pll_source = RCC_CFGR_PLLSRC_HSI_CLK, .pll_mul = RCC_CFGR_PLLMUL_MUL3, @@ -63,6 +64,35 @@ const clock_scale_t clock_vrange1_config[CLOCK_VRANGE1_END] ={ .apb1_frequency = 16000000, .apb2_frequency = 16000000, }, + { /* 4MHz HSI raw */ + .hpre = RCC_CFGR_HPRE_SYSCLK_DIV4, + .ppre1 = RCC_CFGR_PPRE1_HCLK_NODIV, + .ppre2 = RCC_CFGR_PPRE2_HCLK_NODIV, + .voltage_scale = RANGE1, + .flash_config = FLASH_LATENCY_0WS, + .apb1_frequency = 4000000, + .apb2_frequency = 4000000, + }, + { /* 4MHz MSI raw */ + .hpre = RCC_CFGR_HPRE_SYSCLK_NODIV, + .ppre1 = RCC_CFGR_PPRE1_HCLK_NODIV, + .ppre2 = RCC_CFGR_PPRE2_HCLK_NODIV, + .voltage_scale = RANGE1, + .flash_config = FLASH_LATENCY_0WS, + .apb1_frequency = 4194000, + .apb2_frequency = 4194000, + .msi_range = RCC_ICSCR_MSIRANGE_4MHZ, + }, + { /* 2MHz MSI raw */ + .hpre = RCC_CFGR_HPRE_SYSCLK_NODIV, + .ppre1 = RCC_CFGR_PPRE1_HCLK_NODIV, + .ppre2 = RCC_CFGR_PPRE2_HCLK_NODIV, + .voltage_scale = RANGE1, + .flash_config = FLASH_LATENCY_0WS, + .apb1_frequency = 2097000, + .apb2_frequency = 2097000, + .msi_range = RCC_ICSCR_MSIRANGE_2MHZ, + }, }; void rcc_osc_ready_int_clear(osc_t osc) @@ -407,6 +437,42 @@ u32 rcc_system_clock_source(void) return ((RCC_CFGR & 0x000c) >> 2); } +void rcc_clock_setup_msi(const clock_scale_t *clock) +{ + /* Enable internal multi-speed oscillator. */ + + u32 reg = RCC_ICSCR; + reg &= ~(RCC_ICSCR_MSIRANGE_MASK << RCC_ICSCR_MSIRANGE_SHIFT); + reg |= (clock->msi_range << RCC_ICSCR_MSIRANGE_SHIFT); + RCC_ICSCR = reg; + + rcc_osc_on(MSI); + rcc_wait_for_osc_ready(MSI); + + /* Select MSI as SYSCLK source. */ + rcc_set_sysclk_source(RCC_CFGR_SW_SYSCLKSEL_MSICLK); + + /* + * Set prescalers for AHB, ADC, ABP1, ABP2. + * Do this before touching the PLL (TODO: why?). + */ + rcc_set_hpre(clock->hpre); + rcc_set_ppre1(clock->ppre1); + rcc_set_ppre2(clock->ppre2); + + pwr_set_vos_scale(clock->voltage_scale); + + // I guess this should be in the settings? + flash_64bit_enable(); + flash_prefetch_enable(); + /* Configure flash settings. */ + flash_set_ws(clock->flash_config); + + /* Set the peripheral clock frequencies used. */ + rcc_ppre1_frequency = clock->apb1_frequency; + rcc_ppre2_frequency = clock->apb2_frequency; +} + void rcc_clock_setup_hsi(const clock_scale_t *clock) { /* Enable internal high-speed oscillator. */