Browse Source

[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
pull/79/head
Karl Palsson 12 years ago
parent
commit
b6ee57a5b9
  1. 44
      include/libopencm3/stm32/l1/rcc.h
  2. 68
      lib/stm32/l1/rcc.c

44
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);

68
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. */

Loading…
Cancel
Save