aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libmaple/include/libmaple/rcc.h18
-rw-r--r--libmaple/stm32f1/include/series/rcc.h11
-rw-r--r--libmaple/stm32f1/rcc.c19
-rw-r--r--libmaple/stm32f2/include/series/rcc.h66
-rw-r--r--libmaple/stm32f2/rcc.c34
5 files changed, 126 insertions, 22 deletions
diff --git a/libmaple/include/libmaple/rcc.h b/libmaple/include/libmaple/rcc.h
index 4a22b5e..2c8776b 100644
--- a/libmaple/include/libmaple/rcc.h
+++ b/libmaple/include/libmaple/rcc.h
@@ -80,12 +80,30 @@ typedef enum rcc_sysclk_src {
*/
/* Clock prescaler management. */
+
void rcc_set_prescaler(rcc_prescaler prescaler, uint32 divider);
/* SYSCLK. */
+
void rcc_switch_sysclk(rcc_sysclk_src sysclk_src);
+/* PLL configuration */
+
+/**
+ * @brief Specifies a configuration for the main PLL.
+ */
+typedef struct rcc_pll_cfg {
+ rcc_pllsrc pllsrc; /**< PLL source */
+ void *data; /**< Series-specific configuration
+ * data. See the <series/rcc.h> for your
+ * MCU for more information on what to put
+ * here. */
+} rcc_pll_cfg;
+
+void rcc_configure_pll(rcc_pll_cfg *pll_cfg);
+
/* System and secondary clock sources. */
+
void rcc_turn_on_clk(rcc_clk clock);
void rcc_turn_off_clk(rcc_clk clock);
int rcc_is_clk_ready(rcc_clk clock);
diff --git a/libmaple/stm32f1/include/series/rcc.h b/libmaple/stm32f1/include/series/rcc.h
index 68a79d4..b72c5cf 100644
--- a/libmaple/stm32f1/include/series/rcc.h
+++ b/libmaple/stm32f1/include/series/rcc.h
@@ -576,6 +576,17 @@ void rcc_clk_init(rcc_sysclk_src sysclk_src,
rcc_pllsrc pll_src,
rcc_pll_multiplier pll_mul);
+/**
+ * @brief STM32F1-specific PLL configuration values.
+ *
+ * Use this as the "data" field in a struct rcc_pll_cfg.
+ *
+ * @see struct rcc_pll_cfg.
+ */
+typedef struct stm32f1_rcc_pll_data {
+ rcc_pll_multiplier pll_mul; /**< PLL multiplication factor. */
+} stm32f1_rcc_pll_data;
+
#ifdef __cplusplus
}
#endif
diff --git a/libmaple/stm32f1/rcc.c b/libmaple/stm32f1/rcc.c
index 2d31482..a9c9c3a 100644
--- a/libmaple/stm32f1/rcc.c
+++ b/libmaple/stm32f1/rcc.c
@@ -127,6 +127,25 @@ void rcc_clk_init(rcc_sysclk_src sysclk_src,
}
/**
+ * @brief Configure the main PLL.
+ *
+ * You may only call this function while the PLL is disabled.
+ *
+ * @param pll_cfg Desired PLL configuration. The data field must point
+ * to a valid struct stm32f1_rcc_pll_data.
+ */
+void rcc_configure_pll(rcc_pll_cfg *pll_cfg) {
+ stm32f1_rcc_pll_data *data = pll_cfg->data;
+ rcc_pll_multiplier pll_mul = data->pll_mul;
+ uint32 cfgr;
+
+ cfgr = RCC_BASE->CFGR;
+ cfgr &= ~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLMUL);
+ cfgr |= pll_cfg->pllsrc | pll_mul;
+ RCC_BASE->CFGR = cfgr;
+}
+
+/**
* @brief Turn on the clock line on a peripheral
* @param id Clock ID of the peripheral to turn on.
*/
diff --git a/libmaple/stm32f2/include/series/rcc.h b/libmaple/stm32f2/include/series/rcc.h
index 89fed1d..019bb3e 100644
--- a/libmaple/stm32f2/include/series/rcc.h
+++ b/libmaple/stm32f2/include/series/rcc.h
@@ -738,12 +738,30 @@ typedef struct rcc_reg_map {
#define RCC_PLLI2SCFGR_PLLI2SN (0x1FF << 6)
/*
- * Other types
+ * Clock sources, domains, and peripheral clock IDs.
*/
-/*
- * Clock sources, domains, and peripheral clock IDs.
+/**
+ * @brief Available clock sources.
*/
+typedef enum rcc_clk {
+ RCC_CLK_PLLI2S = (uint16)((offsetof(struct rcc_reg_map, CR) << 8) |
+ RCC_CR_PLLI2SON_BIT), /**< Dedicated PLL
+ for I2S. */
+ RCC_CLK_PLL = (uint16)((offsetof(struct rcc_reg_map, CR) << 8) |
+ RCC_CR_PLLON_BIT), /**< Main PLL, clocked by
+ HSI or HSE. */
+ RCC_CLK_HSE = (uint16)((offsetof(struct rcc_reg_map, CR) << 8) |
+ RCC_CR_HSEON_BIT), /**< High speed external. */
+ RCC_CLK_HSI = (uint16)((offsetof(struct rcc_reg_map, CR) << 8) |
+ RCC_CR_HSION_BIT), /**< High speed internal. */
+ RCC_CLK_LSE = (uint16)((offsetof(struct rcc_reg_map, BDCR) << 8) |
+ RCC_BDCR_LSEON_BIT), /**< Low-speed external
+ * (32.768 KHz). */
+ RCC_CLK_LSI = (uint16)((offsetof(struct rcc_reg_map, CSR) << 8) |
+ RCC_CSR_LSION_BIT), /**< Low-speed internal
+ * (approximately 32 KHz). */
+} rcc_clk;
/**
* @brief Identifies bus and clock line for a peripheral or peripheral
@@ -915,27 +933,31 @@ typedef enum rcc_ahb_divider {
RCC_AHB_SYSCLK_DIV_512 = RCC_CFGR_HPRE_SYSCLK_DIV_512,
} rcc_ahb_divider;
+/*
+ * Series-specific PLL configuration.
+ */
+
/**
- * @brief Available clock sources.
+ * @brief STM32F2-specific PLL configuration values.
+ *
+ * Use this as the "data" field in a struct rcc_pll_cfg.
+ *
+ * @see struct rcc_pll_cfg.
*/
-typedef enum rcc_clk {
- RCC_CLK_PLLI2S = (uint16)((offsetof(struct rcc_reg_map, CR) << 8) |
- RCC_CR_PLLI2SON_BIT), /**< Dedicated PLL
- for I2S. */
- RCC_CLK_PLL = (uint16)((offsetof(struct rcc_reg_map, CR) << 8) |
- RCC_CR_PLLON_BIT), /**< Main PLL, clocked by
- HSI or HSE. */
- RCC_CLK_HSE = (uint16)((offsetof(struct rcc_reg_map, CR) << 8) |
- RCC_CR_HSEON_BIT), /**< High speed external. */
- RCC_CLK_HSI = (uint16)((offsetof(struct rcc_reg_map, CR) << 8) |
- RCC_CR_HSION_BIT), /**< High speed internal. */
- RCC_CLK_LSE = (uint16)((offsetof(struct rcc_reg_map, BDCR) << 8) |
- RCC_BDCR_LSEON_BIT), /**< Low-speed external
- * (32.768 KHz). */
- RCC_CLK_LSI = (uint16)((offsetof(struct rcc_reg_map, CSR) << 8) |
- RCC_CSR_LSION_BIT), /**< Low-speed internal
- * (approximately 32 KHz). */
-} rcc_clk;
+typedef struct stm32f2_rcc_pll_data {
+ uint8 pllq; /**<
+ * @brief PLLQ value.
+ * Allowed values: 4, 5, ..., 15. */
+ uint8 pllp; /**<
+ * @brief PLLP value.
+ * Allowed values: 2, 4, 6, 8. */
+ uint16 plln; /**<
+ * @brief PLLN value.
+ * Allowed values: 192, 193, ..., 432. */
+ uint8 pllm; /**<
+ * @brief PLLM value.
+ * Allowed values: 2, 3, ..., 63. */
+} stm32f2_rcc_pll_data;
#ifdef __cplusplus
}
diff --git a/libmaple/stm32f2/rcc.c b/libmaple/stm32f2/rcc.c
index 7bc220d..b94f2e6 100644
--- a/libmaple/stm32f2/rcc.c
+++ b/libmaple/stm32f2/rcc.c
@@ -160,3 +160,37 @@ void rcc_set_prescaler(rcc_prescaler prescaler, uint32 divider) {
};
rcc_do_set_prescaler(masks, prescaler, divider);
}
+
+/**
+ * @brief Configure the main PLL.
+ *
+ * You may only call this function while the PLL is disabled.
+ *
+ * @param pll_cfg Desired PLL configuration. The data field must point
+ * to a valid struct stm32f2_rcc_pll_data.
+ */
+void rcc_configure_pll(rcc_pll_cfg *pll_cfg) {
+ stm32f2_rcc_pll_data *data = pll_cfg->data;
+ uint32 pllcfgr;
+
+ /* Sanity-check all the parameters */
+ ASSERT_FAULT((data->pllq >= 4) && (data->pllq <= 15));
+ ASSERT_FAULT((data->pllp >= 2) && (data->pllp <= 8));
+ ASSERT_FAULT(!(data->pllp & 1));
+ ASSERT_FAULT((data->plln >= 192) && (data->plln <= 432));
+ ASSERT_FAULT((data->pllm >= 2) && (data->pllm <= 63));
+
+ /* Update RCC_PLLCFGR to reflect new values. */
+ pllcfgr = RCC_BASE->PLLCFGR;
+ pllcfgr &= ~(RCC_PLLCFGR_PLLQ |
+ RCC_PLLCFGR_PLLP |
+ RCC_PLLCFGR_PLLN |
+ RCC_PLLCFGR_PLLM |
+ RCC_PLLCFGR_PLLSRC);
+ pllcfgr |= (pll_cfg->pllsrc |
+ (data->pllq << 24) |
+ (((data->pllp >> 1) - 1) << 16) |
+ (data->plln << 6) |
+ data->pllm);
+ RCC_BASE->PLLCFGR = pllcfgr;
+}