aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKarl Palsson2013-01-22 22:52:36 +0000
committerKarl Palsson2013-01-22 22:55:25 +0000
commitb6ee57a5b9fbac7fb1cfe62b6ed8a341bee5543e (patch)
tree86943b4511961e69b595e56c554c385f920c240e
parent2306c907abc5d7e0f54318a6c14bf198706cee0b (diff)
[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
-rw-r--r--include/libopencm3/stm32/l1/rcc.h44
-rw-r--r--lib/stm32/l1/rcc.c68
2 files changed, 105 insertions, 7 deletions
diff --git a/include/libopencm3/stm32/l1/rcc.h b/include/libopencm3/stm32/l1/rcc.h
index f301ce3..a751def 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 b2fce8c..c1d8fa9 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. */