From 400158537f197bd8cf6ef4b7074fa3f53fd2972c Mon Sep 17 00:00:00 2001 From: Vincent Dupont Date: Mon, 21 Aug 2017 16:57:15 +0200 Subject: [PATCH 1/4] cpu/stm32_common: add a tool to generate clock settings --- cpu/stm32_common/dist/.gitignore | 2 + cpu/stm32_common/dist/clk_conf/Makefile | 12 + cpu/stm32_common/dist/clk_conf/clk_conf.c | 483 ++++++++++++++++++++++ cpu/stm32_common/dist/clk_conf/clk_conf.h | 427 +++++++++++++++++++ 4 files changed, 924 insertions(+) create mode 100644 cpu/stm32_common/dist/.gitignore create mode 100644 cpu/stm32_common/dist/clk_conf/Makefile create mode 100644 cpu/stm32_common/dist/clk_conf/clk_conf.c create mode 100644 cpu/stm32_common/dist/clk_conf/clk_conf.h diff --git a/cpu/stm32_common/dist/.gitignore b/cpu/stm32_common/dist/.gitignore new file mode 100644 index 0000000000..e0afe360f4 --- /dev/null +++ b/cpu/stm32_common/dist/.gitignore @@ -0,0 +1,2 @@ +clk_conf +spi_divtable diff --git a/cpu/stm32_common/dist/clk_conf/Makefile b/cpu/stm32_common/dist/clk_conf/Makefile new file mode 100644 index 0000000000..bfe565640a --- /dev/null +++ b/cpu/stm32_common/dist/clk_conf/Makefile @@ -0,0 +1,12 @@ +NAME = clk_conf +CC = gcc +CFLAGS = -std=c99 -Wall +SRC = $(wildcard *.c) + +.PHONY: all clean + +all: + $(CC) $(CFLAGS) -o $(NAME) $(SRC) + +clean: + rm -f $(NAME) diff --git a/cpu/stm32_common/dist/clk_conf/clk_conf.c b/cpu/stm32_common/dist/clk_conf/clk_conf.c new file mode 100644 index 0000000000..6d51b487a1 --- /dev/null +++ b/cpu/stm32_common/dist/clk_conf/clk_conf.c @@ -0,0 +1,483 @@ +/* + * Copyright (C) 2017 OTA keys S.A. + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @brief Compute clock constants for STM32F[2|4|7] CPUs + * + * + * @author Vincent Dupont + * + * @} + */ + +#include +#include +#include +#include +#include +#include +#include "clk_conf.h" + +#define ENABLE_DEBUG (0) +#if ENABLE_DEBUG +#define DEBUG(...) fprintf(stderr, __VA_ARGS__) +#else +#define DEBUG(...) +#endif + +/** + * @brief Check if N/P pair is valid + * + * Check if N/P (alternatively N/Q or N/R) pair is valid with given @p vco_in and + * @p pll_out + * + * @param[in] n + * @param[in] p + * @param[in] vco_in + * @param[in] pll_out + * + * @return 1 if pair is valid, 0 otherwise + */ +static int is_n_ok(const pll_cfg_t *cfg, unsigned n, unsigned p, + unsigned vco_in, unsigned pll_out) +{ + if (n >= cfg->min_n && n <= cfg->max_n && + vco_in * n >= cfg->min_vco_output && vco_in * n <= cfg->max_vco_output && + vco_in * n / p == pll_out) { + return 1; + } + else { + return 0; + } +} + +/** + * @brief Compute PLL factors + * + * @param[in] pll_in PLL input frequency + * @param[in] pll_p_out PLL P output frequency (0 if P is not needed) + * @param[in] pll_q_out PLL Q output frequency (0 if Q is not needed) + * @param[in] pll_r_out PLL R output frequency (0 if R is not needed) + * @param[in,out] m M factor, can be preset (0, if it has to be calculated) + * @param[out] n N factor + * @param[out] p P factor + * @param[out] q Q factor + * @param[out] r R factor + * + * @return -1 if no P,N pair can be computed with given @p pll_in and @p pll_p_out + * @return 1 if no Q can be computed, M, N and P are valid + * @return 2 if no R can be computed, M, M and P are valid + * @return 3 if no Q nor R can be computed, M, M and P are valid + * @return 0 if M, N, P, Q, R are valid + */ +static int compute_pll(const pll_cfg_t *cfg, unsigned pll_in, + unsigned pll_p_out, unsigned pll_q_out, unsigned pll_r_out, + unsigned *m, unsigned *n, + unsigned *p, unsigned *q, unsigned *r) +{ + (void)pll_r_out; + (void)r; + + int res = 0; + unsigned vco_in; + + if (*m == 0) { + unsigned found_m = 0; + unsigned found_n; + unsigned found_p; + unsigned found_q; + unsigned found_r; + unsigned found_res; + *m = cfg->min_m; + while (*m <= cfg->max_m && (res = compute_pll(cfg, pll_in, pll_p_out, + pll_q_out, pll_r_out, + m, n, p, q, r)) != 0) { + if (res > 0 && !found_m) { + found_m = *m; + found_n = *n; + found_p = *p; + found_q = *q; + found_r = *r; + found_res = res; + } + *m += cfg->inc_m; + } + if (res == 0) { + return 0; + } + if (found_m) { + *m = found_m; + *n = found_n; + *p = found_p; + *q = found_q; + *r = found_r; + return found_res; + } + else { + return -1; + } + } + else { + vco_in = pll_in / *m; + DEBUG("M=%u, vco_in=%u\n", *m, vco_in); + } + + if (*m < cfg->min_m || *m > cfg->max_m || + vco_in < cfg->min_vco_input || vco_in > cfg->max_vco_input) { + DEBUG("Invalid M=%u\n", *m); + return -1; + } + + if (pll_p_out) { + DEBUG("Computing P for freq=%u\n", pll_p_out); + for (*p = cfg->max_p; *p >= cfg->min_p; *p -= cfg->inc_p) { + *n = *p * pll_p_out / vco_in; + DEBUG("Trying P=%u: N=%u\n", *p, *n); + if (is_n_ok(cfg, *n, *p, vco_in, pll_p_out)) { + DEBUG("Found M=%u, N=%u, P=%u\n", *m, *n, *p); + break; + } + } + if (*p < cfg->min_p) { + *p += cfg->inc_p; + } + if (!is_n_ok(cfg, *n, *p, vco_in, pll_p_out)) { + return -1; + } + } + + if (pll_q_out) { + DEBUG("Computing Q for freq=%u\n", pll_q_out); + for (*q = cfg->max_q; *q >= cfg->min_q; *q -= cfg->inc_q) { + if (!pll_p_out) { + *n = *q * pll_q_out / vco_in; + } + DEBUG("Trying Q=%u: N=%u\n", *q, *n); + if (is_n_ok(cfg, *n, *q, vco_in, pll_q_out)) { + DEBUG("Found M=%u, N=%u, Q=%u\n", *m, *n, *q); + break; + } + } + if (*q < cfg->min_q) { + *q += cfg->inc_q; + } + if (!is_n_ok(cfg, *n, *q, vco_in, pll_q_out)) { + *q = 0; + res |= 1; + } + } + + /* todo, compute r */ + + return res; +} + +static void usage(char **argv) +{ + fprintf(stderr, "usage: %s [pll_i2s_src] " + "[pll_i2s_q_out] [pll_sai_q_out]\n", argv[0]); +} + +#define HSI 0 +#define HSE 1 + +int main(int argc, char **argv) +{ + if (argc < 2) { + usage(argv); + return 1; + } + + if (strlen(argv[1]) < 9 + || !isdigit(argv[1][6]) + || !isdigit(argv[1][7]) + || !isdigit(argv[1][8]) + || ((argv[1][5] != 'f') && (argv[1][5] != 'F') + /* && (argv[1][5] != 'l') && (argv[1][5] != 'L') */)) { + fprintf(stderr, "Invalid model : %s\n", argv[1]); + return 1; + } + + int model = atoi(argv[1] + 6); + int i; + for (i = 0; i < MODEL_MAX; i++) { + if (stm32_model[i] == model) { + break; + } + } + if (i == MODEL_MAX) { + fprintf(stderr, "Unsupported CPU model %s\n", argv[1]); + return 1; + } + + const clk_cfg_t *cfg = &stm32_clk_cfg[i]; + + /* print help for given cpu */ + if (argc < 5) { + usage(argv); + fprintf(stderr, "Max values for stm32f%03d:\n", model); + fprintf(stderr, " Max coreclock: %u Hz\n" + " Max APB1: %u Hz\n" + " Max APB2: %u Hz\n", + cfg->max_coreclock, cfg->max_apb1, cfg->max_apb2); + fprintf(stderr, "Additional PLLs:\n" + " PLL I2S: %d\n" + " PLL SAI: %d\n" + " Alternate 48MHz source: ", + cfg->has_pll_i2s, cfg->has_pll_sai); + if (cfg->has_alt_48MHz & ALT_48MHZ_I2S) { + fprintf(stderr, "PLL I2S\n"); + } + else if (cfg->has_alt_48MHz & ALT_48MHZ_SAI) { + fprintf(stderr, "PLL SAI\n"); + } + else { + fprintf(stderr, "None\n"); + } + return 0; + } + + /* parse command line arguments */ + unsigned coreclock = atoi(argv[2]); + unsigned pll_in = atoi(argv[3]); + int pll_src; + if (pll_in == 0) { + pll_in = cfg->hsi; + pll_src = HSI; + } + else { + pll_src = HSE; + } + + unsigned is_lse = atoi(argv[4]) ? 1 : 0; + + unsigned pll_i2s_input = 0; + if (argc > 5) { + pll_i2s_input = atoi(argv[5]); + } + + unsigned pll_i2s_p_out = 0; + unsigned pll_i2s_q_out = 0; + if (argc > 6) { + pll_i2s_q_out = atoi(argv[6]); + } + + unsigned pll_sai_p_out = 0; + unsigned pll_sai_q_out = 0; + if (argc > 7) { + pll_sai_q_out = atoi(argv[7]); + } + + if (cfg->max_coreclock && coreclock > cfg->max_coreclock) { + fprintf(stderr, "Invalid coreclock (max=%u)\n", cfg->max_coreclock); + return 1; + } + + fprintf(stderr, "Computing settings for stm32f%03d CPU...\n", model); + + unsigned m = 0; + unsigned n = 0; + unsigned p = 0; + unsigned q = 0; + unsigned r = 0; + + unsigned m_i2s = 0; + unsigned n_i2s = 0; + unsigned p_i2s = 0; + unsigned q_i2s = 0; + unsigned r_i2s = 0; + + unsigned m_sai = 0; + unsigned n_sai = 0; + unsigned p_sai = 0; + unsigned q_sai = 0; + unsigned r_sai = 0; + + bool use_alt_48MHz = false; + unsigned clock_48MHz = cfg->need_48MHz ? 48000000U : 0; + + /* main PLL */ + /* try to match coreclock with P output and 48MHz for Q output (USB) */ + switch (compute_pll(&cfg->pll, pll_in, coreclock, clock_48MHz, 0, + &m, &n, &p, &q, &r)) { + case -1: + /* no config available */ + fprintf(stderr, "Unable to compute main PLL factors\n"); + return 1; + case 1: + /* Q not OK */ + fprintf(stderr, "Need to use an alternate 48MHz src..."); + if (cfg->has_pll_i2s && (cfg->has_alt_48MHz & ALT_48MHZ_I2S) == ALT_48MHZ_I2S) { + puts("PLL I2S"); + use_alt_48MHz = true; + if (pll_i2s_q_out != 0 && pll_i2s_q_out != 48000000U) { + fprintf(stderr, "Invalid PLL I2S Q output freq: %u\n", pll_i2s_q_out); + return 1; + } + pll_i2s_q_out = 48000000U; + } + else if (cfg->has_pll_sai && (cfg->has_alt_48MHz & ALT_48MHZ_SAI)) { + fprintf(stderr, "PLL SAI..."); + use_alt_48MHz = true; + if ((cfg->has_alt_48MHz & ALT_48MHZ_P) && + (pll_sai_p_out == 0 || pll_sai_p_out == 48000000U)) { + fprintf(stderr, "P\n"); + pll_sai_p_out = 48000000U; + } + else if (!(cfg->has_alt_48MHz & ALT_48MHZ_P) && + (pll_sai_q_out == 0 || pll_sai_q_out == 48000000U)) { + fprintf(stderr, "Q\n"); + pll_sai_q_out = 48000000U; + } + else { + if (cfg->has_alt_48MHz & ALT_48MHZ_P) { + fprintf(stderr, "Invalid PLL SAI P output freq: %u\n", pll_sai_p_out); + } else { + fprintf(stderr, "Invalid PLL SAI Q output freq: %u\n", pll_sai_q_out); + } + return 1; + } + } + else { + fprintf(stderr, "No other source available\n"); + return 1; + } + break; + default: + break; + } + + /* PLL I2S */ + if (pll_i2s_p_out || pll_i2s_q_out) { + unsigned *_m; + unsigned _in; + if (cfg->has_pll_i2s_m) { + _m = &m_i2s; + } + else { + _m = &m; + } + if (cfg->has_pll_i2s_alt_input && pll_i2s_input) { + _in = pll_i2s_input; + } + else { + _in = pll_in; + } + if (compute_pll(&cfg->pll, _in, pll_i2s_p_out, pll_i2s_q_out, 0, + _m, &n_i2s, &p_i2s, &q_i2s, &r_i2s) != 0) { + fprintf(stderr, "Unable to compute 48MHz output using PLL I2S\n"); + return 1; + } + } + + /* PLL SAI */ + if (pll_sai_p_out || pll_sai_q_out) { + if (compute_pll(&cfg->pll, pll_in, pll_sai_p_out, pll_sai_q_out, 0, + &m_sai, &n_sai, &p_sai, &q_sai, &r_sai) != 0) { + puts("Unable to compute 48MHz output using PLL I2S"); + return 1; + } + if (!cfg->has_pll_sai_m && m != m_sai) { + m = m_sai; + DEBUG("Retry to compute main PLL with M=%u\n", m); + if (compute_pll(&cfg->pll, pll_in, coreclock, clock_48MHz, 0, + &m, &n, &p, &q, &r) < 0) { + fprintf(stderr, "Unable to compute 48MHz output using PLL I2S\n"); + return 1; + } + } + } + + /* APB prescalers */ + unsigned apb1_pre; + unsigned apb2_pre; + + for (apb1_pre = 1; apb1_pre <= 16; apb1_pre <<= 1) { + if (coreclock / apb1_pre <= cfg->max_apb1) { + break; + } + } + for (apb2_pre = 1; apb2_pre <= 16; apb2_pre <<= 1) { + if (coreclock / apb2_pre <= cfg->max_apb2) { + break; + } + } + + + /* Print constants */ + fprintf(stderr, "==============================================================\n"); + fprintf(stderr, "Please copy the following code into your board's periph_conf.h\n\n"); + + printf("/**\n" + " * @name Clock settings\n" + " *\n" + " * @note This is auto-generated from\n" + " * `cpu/stm32_common/dist/clk_conf/clk_conf.c`\n" + " * @{\n" + " */\n"); + printf("/* give the target core clock (HCLK) frequency [in Hz],\n" + " * maximum: %uMHz */\n", cfg->max_coreclock / 1000000U); + printf("#define CLOCK_CORECLOCK (%uU)\n", coreclock); + printf("/* 0: no external high speed crystal available\n" + " * else: actual crystal frequency [in Hz] */\n" + "#define CLOCK_HSE (%uU)\n", pll_src ? pll_in : 0); + printf("/* 0: no external low speed crystal available,\n" + " * 1: external crystal available (always 32.768kHz) */\n" + "#define CLOCK_LSE (%uU)\n", is_lse); + printf("/* peripheral clock setup */\n"); + printf("#define CLOCK_AHB_DIV RCC_CFGR_HPRE_DIV1\n" + "#define CLOCK_AHB (CLOCK_CORECLOCK / 1)\n"); + printf("#define CLOCK_APB1_DIV RCC_CFGR_PPRE1_DIV%u /* max %uMHz */\n" + "#define CLOCK_APB1 (CLOCK_CORECLOCK / %u)\n", + apb1_pre, cfg->max_apb1 / 1000000U, apb1_pre); + printf("#define CLOCK_APB2_DIV RCC_CFGR_PPRE2_DIV%u /* max %uMHz */\n" + "#define CLOCK_APB2 (CLOCK_CORECLOCK / %u)\n", + apb2_pre, cfg->max_apb2 / 1000000U, apb2_pre); + printf("\n/* Main PLL factors */\n"); + printf("#define CLOCK_PLL_M (%u)\n", m); + printf("#define CLOCK_PLL_N (%u)\n", n); + printf("#define CLOCK_PLL_P (%u)\n", p); + printf("#define CLOCK_PLL_Q (%u)\n", q); + + + if (pll_i2s_p_out || pll_i2s_q_out) { + printf("\n/* PLL I2S configuration */\n"); + printf("#define CLOCK_ENABLE_PLL_I2S (1)\n"); + if (cfg->has_pll_i2s_alt_input && pll_i2s_input) { + printf("#define CLOCK_PLL_I2S_SRC (RCC_PLLI2SCFGR_PLLI2SSRC)\n"); + } + else { + printf("#define CLOCK_PLL_I2S_SRC (0)\n"); + } + if (cfg->has_pll_i2s_m) { + printf("#define CLOCK_PLL_I2S_M (%u)\n", m_i2s); + } + printf("#define CLOCK_PLL_I2S_N (%u)\n", n_i2s); + printf("#define CLOCK_PLL_I2S_P (%u)\n", p_i2s); + printf("#define CLOCK_PLL_I2S_Q (%u)\n", q_i2s); + } + + if (pll_sai_p_out || pll_sai_q_out) { + printf("\n/* PLL SAI configuration */\n"); + printf("#define CLOCK_ENABLE_PLL_SAI (1)\n"); + if (cfg->has_pll_sai_m) { + printf("#define CLOCK_PLL_SAI_M (%u)\n", m_sai); + } + printf("#define CLOCK_PLL_SAI_N (%u)\n", n_sai); + printf("#define CLOCK_PLL_SAI_P (%u)\n", p_sai); + printf("#define CLOCK_PLL_SAI_Q (%u)\n", q_sai); + } + + if (use_alt_48MHz) { + printf("\n/* Use alternative source for 48MHz clock */\n"); + printf("#define CLOCK_USE_ALT_48MHZ (1)\n"); + } + printf("/** @} */\n"); + + return 0; +} diff --git a/cpu/stm32_common/dist/clk_conf/clk_conf.h b/cpu/stm32_common/dist/clk_conf/clk_conf.h new file mode 100644 index 0000000000..d335fb3420 --- /dev/null +++ b/cpu/stm32_common/dist/clk_conf/clk_conf.h @@ -0,0 +1,427 @@ +/* + * Copyright (C) 2017 OTA keys S.A. + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @brief Compute clock constants for STM32F[2|4|7] CPUs + * + * + * @author Vincent Dupont + * + * @} + */ + +#ifndef CLK_CONF_H +#define CLK_CONF_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @name STM32 families + * @ { + */ +enum fam { + STM32F0, + STM32F1, + STM32F2, + STM32F3, + STM32F4, + STM32F7, + FAM_MAX, +}; +/** @} */ + +/** + * @name Supported models + * @{ + */ +enum { + STM32F205, + STM32F207, + STM32F215, + STM32F217, + + STM32F401, + STM32F405, + STM32F407, + STM32F410, + STM32F411, + STM32F412, + STM32F413, + STM32F415, + STM32F417, + STM32F423, + STM32F427, + STM32F429, + STM32F437, + STM32F439, + STM32F446, + STM32F469, + STM32F479, + + STM32F722, + STM32F732, + STM32F746, + STM32F756, + STM32F767, + STM32F769, + STM32F777, + STM32F779, + + MODEL_MAX, +}; +/** @} */ + +/** + * @brief PLL configuration parameters + * + * PLL configuration follows the model: + * ``` + * + * pll_in +----+ vco_in +------------------------------+ + * --------| /M |----------|\ +----+ vco_out +----+ | + * +----+ | --| xN |-------------| /P |--|-- pll_p_out + * | +----+ \ +----+ | + * | | +----+ | + * | ---| /Q |--|-- pll_q_out + * | | +----+ | + * | | +----+ | + * | ---| /R |--|-- pll_r_out + * | +----+ | + * +------------------------------+ + * ``` + * + * vco_in = pll_in / M; + * vco_out = vco_in * N; + * pll_p_out = vco_out / P; + * pll_q_out = vco_out / Q; + * pll_r_out = vco_out / R; + */ +typedef struct { + unsigned min_vco_input; /**< Min VCO input */ + unsigned max_vco_input; /**< Max VCO input */ + unsigned min_vco_output; /**< Min VCO output */ + unsigned max_vco_output; /**< Max VCO output */ + + unsigned min_n; /**< Min N */ + unsigned max_n; /**< Max N */ + unsigned inc_n; /**< Increment between two values of N */ + + unsigned min_m; /**< Min M */ + unsigned max_m; /**< Max M */ + unsigned inc_m; /**< Increment between two values of M */ + + unsigned min_p; /**< Min P */ + unsigned max_p; /**< Max P */ + unsigned inc_p; /**< Increment between two values of P */ + + unsigned min_q; /**< Min Q */ + unsigned max_q; /**< Max Q */ + unsigned inc_q; /**< Increment between two values of Q */ +} pll_cfg_t; + +/** + * @brief Clock configuration + */ +typedef struct { + enum fam family; /**< Family */ + + unsigned max_coreclock; /**< Max coreclock */ + unsigned max_apb1; /**< Max APB1 clock */ + unsigned max_apb2; /**< Max APB2 clock */ + + unsigned hsi; /**< HSI frequency */ + + pll_cfg_t pll; /**< PLL configuration */ + + bool has_pll_i2s; /**< PLL I2S available */ + bool has_pll_sai; /**< PLL SAI available */ + bool has_pll_i2s_m; /**< PLL I2S has a M factor */ + bool has_pll_sai_m; /**< PLL SAI has a M factor */ + bool has_pll_i2s_alt_input; /**< PLL I2S has an external input available */ + + int has_alt_48MHz; /**< 48MHz can be generated by an alternate source */ + bool need_48MHz; /**< 48MHz is needed */ +} clk_cfg_t; + +/** + * @name Alternative 48MHz sources + * @{ + */ +#define ALT_48MHZ_NO 0 +#define ALT_48MHZ_I2S 1 +#define ALT_48MHZ_SAI 2 + +#define ALT_48MHZ_Q 0 +#define ALT_48MHZ_P 4 +/** @} */ + +#define STM32F(x) [STM32F##x] = x + +/** List of supported models */ +static const unsigned stm32_model[] = { + STM32F(205), + STM32F(207), + STM32F(215), + STM32F(217), + + STM32F(401), + STM32F(405), + STM32F(407), + STM32F(410), + STM32F(411), + STM32F(412), + STM32F(413), + STM32F(415), + STM32F(417), + STM32F(423), + STM32F(427), + STM32F(429), + STM32F(437), + STM32F(439), + STM32F(446), + STM32F(469), + STM32F(479), + + STM32F(722), + STM32F(732), + STM32F(746), + STM32F(756), + STM32F(767), + STM32F(769), + STM32F(777), + STM32F(779), +}; + +/** STM32F2xx / STM32F401 PLL config */ +#define stm32f2_4_192_pll_cfg { \ + .min_vco_input = 1000000U, \ + .max_vco_input = 2000000U, \ + .min_vco_output = 192000000U, \ + .max_vco_output = 432000000U, \ + .min_n = 50, \ + .max_n = 432, \ + .inc_n = 1, \ + .min_m = 2, \ + .max_m = 63, \ + .inc_m = 1, \ + .min_p = 2, \ + .max_p = 8, \ + .inc_p = 2, \ + .min_q = 2, \ + .max_q = 15, \ + .inc_q = 1, \ +} + +/** STM32F4 (except 401) / STM32F7 PLL config */ +#define stm32f4_7_pll_cfg { \ + .min_vco_input = 1000000U, \ + .max_vco_input = 2000000U, \ + .min_vco_output = 192000000U, \ + .max_vco_output = 432000000U, \ + .min_n = 50, \ + .max_n = 432, \ + .inc_n = 1, \ + .min_m = 2, \ + .max_m = 63, \ + .inc_m = 1, \ + .min_p = 2, \ + .max_p = 8, \ + .inc_p = 2, \ + .min_q = 2, \ + .max_q = 15, \ + .inc_q = 1, \ +} + +/** + * @brief Clock config for supported cpu + */ +static const clk_cfg_t stm32_clk_cfg[] = { + [STM32F205 ... STM32F217] = { + .family = STM32F2, + .max_coreclock = 120000000U, + .max_apb1 = 30000000U, + .max_apb2 = 60000000U, + .hsi = 16000000U, + .pll = stm32f2_4_192_pll_cfg, + .has_pll_i2s = true, + .has_pll_sai = false, + .has_pll_i2s_alt_input = false, + .has_alt_48MHz = 0, + .need_48MHz = true, + }, + [STM32F401] = { + .family = STM32F4, + .max_coreclock = 84000000U, + .max_apb1 = 42000000U, + .max_apb2 = 84000000U, + .hsi = 16000000U, + .pll = stm32f2_4_192_pll_cfg, + .has_pll_i2s = true, + .has_pll_sai = false, + .has_pll_i2s_m = false, + .has_pll_i2s_alt_input = false, + .has_alt_48MHz = 0, + .need_48MHz = true, + }, + [STM32F405 ... STM32F407] = { + .family = STM32F4, + .max_coreclock = 168000000U, + .max_apb1 = 42000000U, + .max_apb2 = 84000000U, + .hsi = 16000000U, + .pll = stm32f4_7_pll_cfg, + .has_pll_i2s = true, + .has_pll_sai = false, + .has_pll_i2s_m = false, + .has_pll_i2s_alt_input = false, + .has_alt_48MHz = 0, + .need_48MHz = true, + }, + [STM32F410] = { + .family = STM32F4, + .max_coreclock = 100000000U, + .max_apb1 = 50000000U, + .max_apb2 = 100000000U, + .hsi = 16000000U, + .pll = stm32f4_7_pll_cfg, + .has_pll_i2s = false, + .has_pll_sai = false, + .has_pll_i2s_m = false, + .has_pll_i2s_alt_input = false, + .has_alt_48MHz = 0, + .need_48MHz = true, + }, + [STM32F411] = { + .family = STM32F4, + .max_coreclock = 100000000U, + .max_apb1 = 50000000U, + .max_apb2 = 100000000U, + .hsi = 16000000U, + .pll = stm32f4_7_pll_cfg, + .has_pll_i2s = true, + .has_pll_sai = false, + .has_pll_i2s_m = true, + .has_pll_i2s_alt_input = false, + .has_alt_48MHz = 0, + .need_48MHz = true, + }, + [STM32F412 ... STM32F413] = { + .family = STM32F4, + .max_coreclock = 100000000U, + .max_apb1 = 50000000U, + .max_apb2 = 100000000U, + .hsi = 16000000U, + .pll = stm32f4_7_pll_cfg, + .has_pll_i2s = true, + .has_pll_sai = true, + .has_pll_i2s_m = true, + .has_pll_sai_m = false, + .has_pll_i2s_alt_input = true, + .has_alt_48MHz = ALT_48MHZ_I2S, + .need_48MHz = true, + }, + [STM32F415 ... STM32F417] = { + .family = STM32F4, + .max_coreclock = 168000000U, + .max_apb1 = 42000000U, + .max_apb2 = 84000000U, + .hsi = 16000000U, + .pll = stm32f4_7_pll_cfg, + .has_pll_i2s = true, + .has_pll_sai = false, + .has_pll_i2s_m = false, + .has_pll_i2s_alt_input = false, + .has_alt_48MHz = 0, + .need_48MHz = true, + }, + [STM32F423] = { + .family = STM32F4, + .max_coreclock = 100000000U, + .max_apb1 = 50000000U, + .max_apb2 = 100000000U, + .hsi = 16000000U, + .pll = stm32f4_7_pll_cfg, + .has_pll_i2s = true, + .has_pll_sai = true, + .has_pll_i2s_m = true, + .has_pll_sai_m = false, + .has_pll_i2s_alt_input = true, + .has_alt_48MHz = ALT_48MHZ_I2S, + .need_48MHz = true, + }, + [STM32F427 ... STM32F439] = { + .family = STM32F4, + .max_coreclock = 180000000U, + .max_apb1 = 45000000U, + .max_apb2 = 90000000U, + .hsi = 16000000U, + .pll = stm32f4_7_pll_cfg, + .has_pll_i2s = true, + .has_pll_sai = true, + .has_pll_i2s_m = false, + .has_pll_sai_m = false, + .has_pll_i2s_alt_input = false, + .has_alt_48MHz = 0, + .need_48MHz = true, + }, + [STM32F446] = { + .family = STM32F4, + .max_coreclock = 180000000U, + .max_apb1 = 45000000U, + .max_apb2 = 90000000U, + .hsi = 16000000U, + .pll = stm32f4_7_pll_cfg, + .has_pll_i2s = true, + .has_pll_sai = true, + .has_pll_i2s_m = true, + .has_pll_sai_m = true, + .has_pll_i2s_alt_input = false, + .has_alt_48MHz = ALT_48MHZ_SAI | ALT_48MHZ_P, + .need_48MHz = true, + }, + [STM32F469 ... STM32F479] = { + .family = STM32F4, + .max_coreclock = 180000000U, + .max_apb1 = 45000000U, + .max_apb2 = 90000000U, + .hsi = 16000000U, + .pll = stm32f4_7_pll_cfg, + .has_pll_i2s = true, + .has_pll_sai = true, + .has_pll_i2s_m = false, + .has_pll_sai_m = false, + .has_pll_i2s_alt_input = false, + .has_alt_48MHz = ALT_48MHZ_SAI | ALT_48MHZ_P, + .need_48MHz = true, + }, + [STM32F722 ... STM32F779] = { + .family = STM32F7, + .max_coreclock = 216000000U, + .max_apb1 = 54000000U, + .max_apb2 = 108000000U, + .hsi = 16000000U, + .pll = stm32f4_7_pll_cfg, + .has_pll_i2s = true, + .has_pll_sai = true, + .has_pll_i2s_m = false, + .has_pll_sai_m = false, + .has_pll_i2s_alt_input = false, + .has_alt_48MHz = ALT_48MHZ_SAI | ALT_48MHZ_P, + .need_48MHz = true, + }, +}; + +#ifdef __cplusplus +} +#endif + +#endif /* CLK_CONF_H */ From d2a4acecd9ef754bb6ec5a03f4b0c302ff77a9b3 Mon Sep 17 00:00:00 2001 From: Vincent Dupont Date: Wed, 16 Aug 2017 12:47:38 +0200 Subject: [PATCH 2/4] cpu/stm32_common: unify stmclk for stm32f[2|4|7] and adapt to use clk_conf --- cpu/stm32_common/stmclk.c | 179 ++++++++++++++++++++++++++++++++++++++ cpu/stm32f2/stmclk.c | 147 ------------------------------- cpu/stm32f4/stmclk.c | 124 -------------------------- cpu/stm32f7/stmclk.c | 117 ------------------------- 4 files changed, 179 insertions(+), 388 deletions(-) create mode 100644 cpu/stm32_common/stmclk.c delete mode 100644 cpu/stm32f2/stmclk.c delete mode 100644 cpu/stm32f4/stmclk.c delete mode 100644 cpu/stm32f7/stmclk.c diff --git a/cpu/stm32_common/stmclk.c b/cpu/stm32_common/stmclk.c new file mode 100644 index 0000000000..96f7e75a18 --- /dev/null +++ b/cpu/stm32_common/stmclk.c @@ -0,0 +1,179 @@ +/* + * Copyright (C) 2017 Freie Universität Berlin + * 2017 OTA keys S.A. + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @ingroup cpu_stm32_common + * @{ + * + * @file + * @brief Implementation of STM32 clock configuration + * + * @author Hauke Petersen + * @author Vincent Dupont + * @} + */ + +#if defined(CPU_FAM_STM32F2) || defined(CPU_FAM_STM32F4) || defined(CPU_FAM_STM32F7) + +#include "cpu.h" +#include "stmclk.h" +#include "periph_conf.h" + +/* make sure we have all needed information about the clock configuration */ +#ifndef CLOCK_HSE +#error "Please provide CLOCK_HSE in your board's perhip_conf.h" +#endif +#ifndef CLOCK_LSE +#error "Please provide CLOCK_LSE in your board's periph_conf.h" +#endif +#ifndef CLOCK_CORECLOCK +#error "Please provide CLOCK_CORECLOCK in your board's periph_conf.h" +#endif + +/** + * @name PLL configuration + * @{ + */ +/* figure out which input to use */ +#if (CLOCK_HSE) +#define PLL_SRC RCC_PLLCFGR_PLLSRC_HSE +#else +#define PLL_SRC RCC_PLLCFGR_PLLSRC_HSI +#endif + +#if (CLOCK_ENABLE_PLL_I2S) +#ifdef RCC_PLLI2SCFGR_PLLI2SM_Pos +#define PLLI2S_M (CLOCK_PLL_I2S_M << RCC_PLLI2SCFGR_PLLI2SM_Pos) +#else +#define PLLI2S_M (0) +#endif +#define PLLI2S_N (CLOCK_PLL_I2S_N << RCC_PLLI2SCFGR_PLLI2SN_Pos) +#ifdef RCC_PLLI2SCFGR_PLLI2SP_Pos +#define PLLI2S_P (((CLOCK_PLL_I2S_P / 2) - 1) << RCC_PLLI2SCFGR_PLLI2SP_Pos) +#else +#define PLLI2S_P (0) +#endif +#define PLLI2S_Q (CLOCK_PLL_I2S_Q << RCC_PLLI2SCFGR_PLLI2SQ_Pos) +#endif /* CLOCK_ENABLE_PLLI_2S */ + +#if (CLOCK_ENABLE_PLL_SAI) +#ifdef RCC_PLLSAICFGR_PLLSAIN_Pos +#define PLLSAI_M (CLOCK_PLL_SAI_M << RCC_PLLSAICFGR_PLLSAIN_Pos) +#else +#define PLLSAI_M (0) +#endif +#define PLLSAI_N (CLOCK_PLL_SAI_N << RCC_PLLSAICFGR_PLLSAIN_Pos) +#ifdef RCC_PLLSAICFGR_PLLSAIP_Pos +#define PLLSAI_P (((CLOCK_PLL_SAI_P / 2) - 1) << RCC_PLLSAICFGR_PLLSAIP_Pos) +#else +#define PLLSAI_P (0) +#endif +#define PLLSAI_Q (CLOCK_PLL_SAI_Q << RCC_PLLSAICFGR_PLLSAIQ_Pos) +#endif /* CLOCK_ENABLE_PLL_SAI */ + +#if defined(CPU_FAM_STM32F2) +#define RCC_PLLCFGR_PLLP_Pos (16U) +#define RCC_PLLCFGR_PLLM_Pos (0U) +#define RCC_PLLCFGR_PLLN_Pos (6U) +#define RCC_PLLCFGR_PLLQ_Pos (24U) +#endif + +/* now we get the actual bitfields */ +#define PLL_P (((CLOCK_PLL_P / 2) - 1) << RCC_PLLCFGR_PLLP_Pos) +#define PLL_M (CLOCK_PLL_M << RCC_PLLCFGR_PLLM_Pos) +#define PLL_N (CLOCK_PLL_N << RCC_PLLCFGR_PLLN_Pos) +#define PLL_Q (CLOCK_PLL_Q << RCC_PLLCFGR_PLLQ_Pos) +/** @} */ + +/** + * @name Deduct the needed flash wait states from the core clock frequency + * @{ + */ +#define FLASH_WAITSTATES (CLOCK_CORECLOCK / 30000000U) +/* we enable I+D cashes, pre-fetch, and we set the actual number of + * needed flash wait states */ +#if defined(CPU_FAM_STM32F2) || defined(CPU_FAM_STM32F4) +#define FLASH_ACR_CONFIG (FLASH_ACR_ICEN | FLASH_ACR_DCEN | FLASH_ACR_PRFTEN | FLASH_WAITSTATES) +#elif defined(CPU_FAM_STM32F7) +#define FLASH_ACR_CONFIG (FLASH_ACR_ARTEN | FLASH_ACR_PRFTEN | FLASH_WAITSTATES) +#endif +/** @} */ + +void stmclk_init_sysclk(void) +{ + /* disable any interrupts. Global interrupts could be enabled if this is + * called from some kind of bootloader... */ + unsigned is = irq_disable(); + RCC->CIR = 0; + + /* enable HSI clock for the duration of initialization */ + stmclk_enable_hsi(); + + /* use HSI as system clock while we do any further configuration and + * configure the AHB and APB clock dividers as configure by the board */ + RCC->CFGR = (RCC_CFGR_SW_HSI | CLOCK_AHB_DIV | + CLOCK_APB1_DIV | CLOCK_APB2_DIV); + while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_HSI) {} + + /* Flash config */ + FLASH->ACR = FLASH_ACR_CONFIG; + + /* disable all active clocks except HSI -> resets the clk configuration */ + RCC->CR = (RCC_CR_HSION | RCC_CR_HSITRIM_4); + +#if (CLOCK_MCO1_SRC) +#ifndef RCC_CFGR_MCO1 +#error "stmclk: no MCO1 on this device" +#endif + RCC->CFGR |= CLOCK_MCO1_SRC | CLOCK_MCO1_PRE; +#endif +#if (CLOCK_MCO2_SRC) +#ifndef RCC_CFGR_MCO2 +#error "stmclk: no MCO2 on this device" +#endif + RCC->CFGR |= CLOCK_MCO2_SRC | CLOCK_MCO2_PRE; +#endif + + /* if configured, we need to enable the HSE clock now */ +#if (CLOCK_HSE) + RCC->CR |= (RCC_CR_HSEON); + while (!(RCC->CR & RCC_CR_HSERDY)) {} +#endif + +#if CLOCK_USE_ALT_48MHZ + RCC->DCKCFGR2 |= RCC_DCKCFGR2_CK48MSEL; +#endif + /* now we can safely configure and start the PLL */ + RCC->PLLCFGR = (PLL_SRC | PLL_M | PLL_N | PLL_P | PLL_Q); + RCC->CR |= (RCC_CR_PLLON); + while (!(RCC->CR & RCC_CR_PLLRDY)) {} + + /* now that the PLL is running, we use it as system clock */ + RCC->CFGR |= (RCC_CFGR_SW_PLL); + while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL) {} + + stmclk_disable_hsi(); + +#if (CLOCK_ENABLE_PLLI2S) + RCC->PLLI2SCFGR = (PLLI2S_SRC | PLLI2S_M | PLLI2S_N | PLLI2s_P | PLLI2S_Q); + RCC->CR |= (RCC_CR_PLLI2SON); + while (!(RCC->CR & RCC_CR_PLLI2SRDY)) {} +#endif /* CLOCK_ENABLE_PLLI2S */ + +#if (CLOCK_ENABLE_PLLSAI) + RCC->PLLSAICFGR = (PLLSAI_M | PLLSAI_N | PLLSAI_P | PLLSAI_Q); + RCC->CR |= (RCC_CR_PLLSAION); + while (!(RCC->CR & RCC_CR_PLLSAIRDY)) {} +#endif + + irq_restore(is); +} +#else +typedef int dont_be_pedantic; +#endif /* defined(CPU_FAM_STM32F2) || defined(CPU_FAM_STM32F4) || defined(CPU_FAM_STM32F7) */ diff --git a/cpu/stm32f2/stmclk.c b/cpu/stm32f2/stmclk.c deleted file mode 100644 index a32ca10e14..0000000000 --- a/cpu/stm32f2/stmclk.c +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Copyright (C) 2017 Freie Universität Berlin - * 2017 OTA keys S.A. - * - * This file is subject to the terms and conditions of the GNU Lesser - * General Public License v2.1. See the file LICENSE in the top level - * directory for more details. - */ - -/** - * @ingroup cpu_stm32f2 - * @{ - * - * @file - * @brief Implementation of STM32 clock configuration - * - * @author Hauke Petersen - * @author Vincent Dupont - * @} - */ - -#include "cpu.h" -#include "stmclk.h" -#include "periph_conf.h" - -/* make sure we have all needed information about the clock configuration */ -#ifndef CLOCK_HSE -#error "Please provide CLOCK_HSE in your board's perhip_conf.h" -#endif -#ifndef CLOCK_LSE -#error "Please provide CLOCK_LSE in your board's periph_conf.h" -#endif - -/** - * @name PLL configuration - * @{ - */ -/* figure out which input to use */ -#if (CLOCK_HSE) -#define PLL_IN CLOCK_HSE -#define PLL_SRC RCC_PLLCFGR_PLLSRC_HSE -#else -#define PLL_IN (16000000U) /* HSI fixed @ 16MHz */ -#define PLL_SRC RCC_PLLCFGR_PLLSRC_HSI -#endif - -#ifndef P -/* we fix P to 2 (so the PLL output equals 2 * CLOCK_CORECLOCK) */ -#define P (2U) -#if ((P != 2) && (P != 4) && (P != 6) && (P != 8)) -#error "PLL configuration: PLL P value is invalid" -#endif -#endif /* P */ -/* the recommended input clock for the PLL should be 2MHz */ -#define M (PLL_IN / 2000000U) -#if ((M < 2) || (M > 63)) -#error "PLL configuration: PLL M value is out of range" -#endif -/* next we multiply the input freq to 2 * CORECLOCK */ -#define N (P * CLOCK_CORECLOCK / 2000000U) -#if ((N < 50) || (N > 432)) -#error "PLL configuration: PLL N value is out of range" -#endif -/* finally we need to set Q, so that the USB clock is 48MHz */ -#define Q ((P * CLOCK_CORECLOCK) / 48000000U) -#if ((Q * 48000000U) != (P * CLOCK_CORECLOCK)) -#error "PLL configuration: USB frequency is not 48MHz" -#endif - -#define RCC_PLLCFGR_PLLP_Pos (16U) -#define RCC_PLLCFGR_PLLM_Pos (0U) -#define RCC_PLLCFGR_PLLN_Pos (6U) -#define RCC_PLLCFGR_PLLQ_Pos (24U) -/* now we get the actual bitfields */ -#define PLL_P (((P / 2) - 1) << RCC_PLLCFGR_PLLP_Pos) -#define PLL_M (M << RCC_PLLCFGR_PLLM_Pos) -#define PLL_N (N << RCC_PLLCFGR_PLLN_Pos) -#define PLL_Q (Q << RCC_PLLCFGR_PLLQ_Pos) -/** @} */ - -/** - * @name Deduct the needed flash wait states from the core clock frequency - * @{ - */ -#define FLASH_WAITSTATES (CLOCK_CORECLOCK / 30000000U) -/** @} */ - -void stmclk_init_sysclk(void) -{ - /* disable any interrupts. Global interrupts could be enabled if this is - * called from some kind of bootloader... */ - unsigned is = irq_disable(); - RCC->CIR = 0; - - /* enable HSI clock for the duration of initialization */ - stmclk_enable_hsi(); - - /* use HSI as system clock while we do any further configuration and - * configure the AHB and APB clock dividers as configure by the board */ - RCC->CFGR = (RCC_CFGR_SW_HSI | CLOCK_AHB_DIV | - CLOCK_APB1_DIV | CLOCK_APB2_DIV); - while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_HSI) {} - - /* we enable I+D cashes, pre-fetch, and we set the actual number of - * needed flash wait states */ - FLASH->ACR = (FLASH_ACR_ICEN | FLASH_ACR_DCEN | FLASH_ACR_PRFTEN | FLASH_WAITSTATES); - - /* disable all active clocks except HSI -> resets the clk configuration */ - RCC->CR = (RCC_CR_HSION | RCC_CR_HSITRIM_4); - - /* if configured, we need to enable the HSE clock now */ -#if (CLOCK_HSE) - RCC->CR |= (RCC_CR_HSEON); - while (!(RCC->CR & RCC_CR_HSERDY)) {} -#endif - -#ifdef ENABLE_PLLI2S_MCO2 - /* reset PLL I2S config register */ - RCC->PLLI2SCFGR = 0x00000000U; - /* set PLL I2S division factor */ - RCC->PLLI2SCFGR |= (CLOCK_PLL_I2S_R & 0x07) << 28; - /* set PLL I2S multiplication factor */ - RCC->PLLI2SCFGR |= (CLOCK_PLL_I2S_N & 0x1FF) << 6; - - /* MCO2 output is PLLI2S */ - RCC->CFGR |= (uint32_t) RCC_CFGR_MCO2_0; - RCC->CFGR &= ~(uint32_t) RCC_CFGR_MCO2_1; - /* MCO2 prescaler div by 5 */ - RCC->CFGR |= (uint32_t) ((CLOCK_MC02_PRE + 4 - 2) & 0x7) << 27; - /* enable PLL I2S clock */ - RCC->CR |= RCC_CR_PLLI2SON; - /* wait till PLL I2S clock is ready */ - while ((RCC->CR & RCC_CR_PLLI2SRDY) == 0) {} -#endif - - /* now we can safely configure and start the PLL */ - RCC->PLLCFGR = (PLL_SRC | PLL_M | PLL_N | PLL_P | PLL_Q); - RCC->CR |= (RCC_CR_PLLON); - while (!(RCC->CR & RCC_CR_PLLRDY)) {} - - /* now that the PLL is running, we use it as system clock */ - RCC->CFGR |= (RCC_CFGR_SW_PLL); - while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL) {} - - stmclk_disable_hsi(); - irq_restore(is); -} diff --git a/cpu/stm32f4/stmclk.c b/cpu/stm32f4/stmclk.c deleted file mode 100644 index ea2281f445..0000000000 --- a/cpu/stm32f4/stmclk.c +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright (C) 2017 Freie Universität Berlin - * 2017 OTA keys S.A. - * - * This file is subject to the terms and conditions of the GNU Lesser - * General Public License v2.1. See the file LICENSE in the top level - * directory for more details. - */ - -/** - * @ingroup cpu_stm32f4 - * @{ - * - * @file - * @brief Implementation of STM32 clock configuration - * - * @author Hauke Petersen - * @author Vincent Dupont - * @} - */ - -#include "cpu.h" -#include "stmclk.h" -#include "periph_conf.h" - -/* make sure we have all needed information about the clock configuration */ -#ifndef CLOCK_HSE -#error "Please provide CLOCK_HSE in your board's perhip_conf.h" -#endif -#ifndef CLOCK_LSE -#error "Please provide CLOCK_LSE in your board's periph_conf.h" -#endif - -/** - * @name PLL configuration - * @{ - */ -/* figure out which input to use */ -#if (CLOCK_HSE) -#define PLL_IN CLOCK_HSE -#define PLL_SRC RCC_PLLCFGR_PLLSRC_HSE -#else -#define PLL_IN (16000000U) /* HSI fixed @ 16MHz */ -#define PLL_SRC RCC_PLLCFGR_PLLSRC_HSI -#endif - -#ifndef P -/* we fix P to 2 (so the PLL output equals 2 * CLOCK_CORECLOCK) */ -#define P (2U) -#if ((P != 2) && (P != 4) && (P != 6) && (P != 8)) -#error "PLL configuration: PLL P value is invalid" -#endif -#endif /* P */ -/* the recommended input clock for the PLL should be 2MHz */ -#define M (PLL_IN / 2000000U) -#if ((M < 2) || (M > 63)) -#error "PLL configuration: PLL M value is out of range" -#endif -/* next we multiply the input freq to 2 * CORECLOCK */ -#define N (P * CLOCK_CORECLOCK / 2000000U) -#if ((N < 50) || (N > 432)) -#error "PLL configuration: PLL N value is out of range" -#endif -/* finally we need to set Q, so that the USB clock is 48MHz */ -#define Q ((P * CLOCK_CORECLOCK) / 48000000U) -#if ((Q * 48000000U) != (P * CLOCK_CORECLOCK)) -#error "PLL configuration: USB frequency is not 48MHz" -#endif - -/* now we get the actual bitfields */ -#define PLL_P (((P / 2) - 1) << RCC_PLLCFGR_PLLP_Pos) -#define PLL_M (M << RCC_PLLCFGR_PLLM_Pos) -#define PLL_N (N << RCC_PLLCFGR_PLLN_Pos) -#define PLL_Q (Q << RCC_PLLCFGR_PLLQ_Pos) -/** @} */ - -/** - * @name Deduct the needed flash wait states from the core clock frequency - * @{ - */ -#define FLASH_WAITSTATES (CLOCK_CORECLOCK / 30000000U) -/** @} */ - -void stmclk_init_sysclk(void) -{ - /* disable any interrupts. Global interrupts could be enabled if this is - * called from some kind of bootloader... */ - unsigned is = irq_disable(); - RCC->CIR = 0; - - /* enable HSI clock for the duration of initialization */ - stmclk_enable_hsi(); - - /* use HSI as system clock while we do any further configuration and - * configure the AHB and APB clock dividers as configure by the board */ - RCC->CFGR = (RCC_CFGR_SW_HSI | CLOCK_AHB_DIV | - CLOCK_APB1_DIV | CLOCK_APB2_DIV); - while ((RCC->CFGR & RCC_CFGR_SWS_Msk) != RCC_CFGR_SWS_HSI) {} - - /* we enable I+D cashes, pre-fetch, and we set the actual number of - * needed flash wait states */ - FLASH->ACR = (FLASH_ACR_ICEN | FLASH_ACR_DCEN | FLASH_ACR_PRFTEN | FLASH_WAITSTATES); - - /* disable all active clocks except HSI -> resets the clk configuration */ - RCC->CR = (RCC_CR_HSION | RCC_CR_HSITRIM_4); - - /* if configured, we need to enable the HSE clock now */ -#if (CLOCK_HSE) - RCC->CR |= (RCC_CR_HSEON); - while (!(RCC->CR & RCC_CR_HSERDY)) {} -#endif - - /* now we can safely configure and start the PLL */ - RCC->PLLCFGR = (PLL_SRC | PLL_M | PLL_N | PLL_P | PLL_Q); - RCC->CR |= (RCC_CR_PLLON); - while (!(RCC->CR & RCC_CR_PLLRDY)) {} - - /* now that the PLL is running, we use it as system clock */ - RCC->CFGR |= (RCC_CFGR_SW_PLL); - while ((RCC->CFGR & RCC_CFGR_SWS_Msk) != RCC_CFGR_SWS_PLL) {} - - stmclk_disable_hsi(); - irq_restore(is); -} diff --git a/cpu/stm32f7/stmclk.c b/cpu/stm32f7/stmclk.c deleted file mode 100644 index 4d00169390..0000000000 --- a/cpu/stm32f7/stmclk.c +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright (C) 2017 Freie Universität Berlin - * - * This file is subject to the terms and conditions of the GNU Lesser - * General Public License v2.1. See the file LICENSE in the top level - * directory for more details. - */ - -/** - * @ingroup cpu_stm32f7 - * @{ - * - * @file - * @brief Implementation of STM32 clock configuration - * - * @author Hauke Petersen - * @} - */ - -#include "cpu.h" -#include "stmclk.h" -#include "periph_conf.h" - -/* make sure we have all needed information about the clock configuration */ -#ifndef CLOCK_HSE -#error "Please provide CLOCK_HSE in your board's perhip_conf.h" -#endif -#ifndef CLOCK_LSE -#error "Please provide CLOCK_LSE in your board's periph_conf.h" -#endif - -/** - * @name PLL configuration - * @{ - */ -/* figure out which input to use */ -#if (CLOCK_HSE) -#define PLL_IN CLOCK_HSE -#define PLL_SRC RCC_PLLCFGR_PLLSRC_HSE -#else -#define PLL_IN (16000000U) /* HSI fixed @ 16MHz */ -#define PLL_SRC RCC_PLLCFGR_PLLSRC_HSI -#endif - -/* we fix P to 2 (so the PLL output equals 2 * CLOCK_CORECLOCK) */ -#define P (2U) -/* the recommended input clock for the PLL should be 2MHz > ref. man. p. 143 */ -#define M (PLL_IN / 2000000U) -#if ((M < 2) || (M > 63)) -#error "PLL configuration: PLL M value is out of range" -#endif -/* next we multiply the input freq to 2 * CORECLOCK */ -#define N (P * CLOCK_CORECLOCK / 2000000U) -#if ((N < 50) || (N > 432)) -#error "PLL configuration: PLL N value is out of range" -#endif -/* finally we need to set Q, so that the USB clock is 48MHz */ -#define Q ((P * CLOCK_CORECLOCK) / 48000000U) -#if ((Q * 48000000U) != (P * CLOCK_CORECLOCK)) -#error "PLL configuration: USB frequency is not 48MHz" -#endif - -/* now we get the actual bitfields */ -#define PLL_P (0) -#define PLL_M (M << RCC_PLLCFGR_PLLM_Pos) -#define PLL_N (N << RCC_PLLCFGR_PLLN_Pos) -#define PLL_Q (Q << RCC_PLLCFGR_PLLQ_Pos) -/** @} */ - -/** - * @name Deduct the needed flash wait states from the core clock frequency - * @{ - */ -#define FLASH_WAITSTATES (CLOCK_CORECLOCK / 30000000U) -/** @} */ - -void stmclk_init_sysclk(void) -{ - /* disable any interrupts. Global interrupts could be enabled if this is - * called from some kind of bootloader... */ - unsigned is = irq_disable(); - RCC->CIR = 0; - - /* enable HSI clock for the duration of initialization */ - stmclk_enable_hsi(); - - /* use HSI as system clock while we do any further configuration and - * configure the AHB and APB clock dividers as configure by the board */ - RCC->CFGR = (RCC_CFGR_SW_HSI | CLOCK_AHB_DIV | - CLOCK_APB1_DIV | CLOCK_APB2_DIV); - while ((RCC->CFGR & RCC_CFGR_SWS_Msk) != RCC_CFGR_SWS_HSI) {} - - /* we enable I+D cashes, pre-fetch, and we set the actual number of - * needed flash wait states */ - FLASH->ACR = (FLASH_ACR_ARTEN | FLASH_ACR_PRFTEN | FLASH_WAITSTATES); - - /* disable all active clocks except HSI -> resets the clk configuration */ - RCC->CR = (RCC_CR_HSION | RCC_CR_HSITRIM_4); - - /* if configured, we need to enable the HSE clock now */ -#if (CLOCK_HSE) - RCC->CR |= (RCC_CR_HSEON); - while (!(RCC->CR & RCC_CR_HSERDY)) {} -#endif - - /* now we can safely configure and start the PLL */ - RCC->PLLCFGR = (PLL_SRC | PLL_M | PLL_N | PLL_P | PLL_Q); - RCC->CR |= (RCC_CR_PLLON); - while (!(RCC->CR & RCC_CR_PLLRDY)) {} - - /* now that the PLL is running, we use it as system clock */ - RCC->CFGR |= (RCC_CFGR_SW_PLL); - while ((RCC->CFGR & RCC_CFGR_SWS_Msk) != RCC_CFGR_SWS_PLL) {} - - stmclk_disable_hsi(); - irq_restore(is); -} From 33e8a419be18e9d997142edc74aca16e484c9640 Mon Sep 17 00:00:00 2001 From: Vincent Dupont Date: Wed, 16 Aug 2017 19:20:28 +0200 Subject: [PATCH 3/4] cpu/stm32_common: add clock config documentation --- cpu/stm32_common/doc.txt | 37 ++++++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/cpu/stm32_common/doc.txt b/cpu/stm32_common/doc.txt index a39cb647eb..0827b1c627 100644 --- a/cpu/stm32_common/doc.txt +++ b/cpu/stm32_common/doc.txt @@ -7,4 +7,39 @@ * families supported by RIOT: @ref cpu_stm32f0, @ref cpu_stm32l0, * @ref cpu_stm32f1, @ref cpu_stm32f2, @ref cpu_stm32f3, @ref cpu_stm32f4, * @ref cpu_stm32l4, @ref cpu_stm32f7. - */ \ No newline at end of file + * + * STM32F[2|4|7] Clock configuration + * ================================= + * + * stm32f2, stm32f4 and stm32f7 cpus share clock configuration code and macro. + * It can be configured as described here. + * + * The following macro must be defined in the board's periph_conf.h: + * - CLOCK_HSE: 0 if HSI must be used as PLL source, frequency in Hz otherwise, + * - CLOCK_LSE: 0 if LSI must be used as low speed clock, 1 otherwise + * (the LSE is a 32.768kHz crytal) + * - CLOCK_CORECLOCK: desired main clock frequency + * - CLOCK_AHB_DIV, CLOCK_AHB: AHB prescaler in register value and AHB frequecny in Hz + * - CLOCK_APB1_DIV, CLOCK_APB1: APB1 prescaler in register value and APB1 frequecny in Hz + * - CLOCK_APB2_DIV, CLOCK_APB2: APB2 prescaler in register value and APB2 frequecny in Hz + * - CLOCK_PLL_M, CLOCK_PLL_N, CLOCK_PLL_P, CLOCK_PLL_Q: Main PLL factors + * + * The following macro are optional and can be defined depending on board config + * and application needs: + * - CLOCK_ENABLE_PLL_I2S: if a second PLL (PLL I2S) is available on the cpu, it + * can be activated with this macro, then CLOCK_PLL_I2S_M, CLOCK_PLL_I2S_N, + * CLOCK_PLL_I2S_P and CLOCK_PLL_I2S_Q need to be defined + * - CLOCK_ENABLE_PLL_SAI: if a second PLL (PLL SAI) is available on the cpu, it + * can be activated with this macro, then CLOCK_PLL_SAI_M, CLOCK_PLL_SAI_N, + * CLOCK_PLL_SAI_P and CLOCK_PLL_SAI_Q need to be defined + * - CLOCK_USE_ALT_48MHZ: if the 48MHz clock should be generated by the alternate + * source (PLL I2S or PLL SAI, depending on cpu) + * + * All the previous constants can be generated using the tool in + * `cpu/stm32_common/dist/clk_conf`. + * + * Clock outputs can also be setup with macro: + * - CLOCK_MCOx_SRC, CLOCK_MCOx_PRE, with x=1,2: MCO1 and MCO2 output configuration + * macros. CLOCK_MCOx_SRC defines the MCOx source, as a register value (see vendor header), + * CLOCK_MCOx_PRE defines the MCOx prescaler, as a register value. + */ From fc9fc57aa6e8f68a1bb385a12708bc4678596d6c Mon Sep 17 00:00:00 2001 From: Vincent Dupont Date: Wed, 16 Aug 2017 16:17:31 +0200 Subject: [PATCH 4/4] boards: adapt stm32f[2|4|7] boards clock config --- boards/f4vi1/include/periph_conf.h | 19 +++++--- boards/msbiot/include/periph_conf.h | 19 +++++--- boards/nucleo-f401/include/periph_conf.h | 21 ++++++--- boards/nucleo-f410/include/periph_conf.h | 43 +++++++++++-------- boards/nucleo-f411/include/periph_conf.h | 43 +++++++++++-------- boards/nucleo-f446/include/periph_conf.h | 29 ++++++++++--- boards/nucleo144-f207/include/periph_conf.h | 19 +++++--- boards/nucleo144-f412/include/periph_conf.h | 30 ++++++++++--- boards/nucleo144-f413/include/periph_conf.h | 30 ++++++++++--- boards/nucleo144-f429/include/periph_conf.h | 19 +++++--- boards/nucleo144-f446/include/periph_conf.h | 29 ++++++++++--- boards/nucleo144-f722/include/periph_conf.h | 19 +++++--- boards/nucleo144-f746/include/periph_conf.h | 19 +++++--- boards/nucleo144-f767/include/periph_conf.h | 19 +++++--- boards/stm32f4discovery/include/periph_conf.h | 19 +++++--- boards/stm32f7discovery/include/periph_conf.h | 19 +++++--- 16 files changed, 290 insertions(+), 106 deletions(-) diff --git a/boards/f4vi1/include/periph_conf.h b/boards/f4vi1/include/periph_conf.h index ccf2dbb455..1722444c1d 100644 --- a/boards/f4vi1/include/periph_conf.h +++ b/boards/f4vi1/include/periph_conf.h @@ -28,25 +28,34 @@ extern "C" { #endif /** - * @name Clock system configuration + * @name Clock settings + * + * @note This is auto-generated from + * `cpu/stm32_common/dist/clk_conf/clk_conf.c` * @{ */ +/* give the target core clock (HCLK) frequency [in Hz], + * maximum: 168MHz */ +#define CLOCK_CORECLOCK (168000000U) /* 0: no external high speed crystal available * else: actual crystal frequency [in Hz] */ #define CLOCK_HSE (16000000U) /* 0: no external low speed crystal available, * 1: external crystal available (always 32.768kHz) */ #define CLOCK_LSE (0) -/* give the target core clock (HCLK) frequency [in Hz], - * maximum: 168MHz */ -#define CLOCK_CORECLOCK (168000000U) /* peripheral clock setup */ -#define CLOCK_AHB_DIV RCC_CFGR_HPRE_DIV1 /* min 25MHz */ +#define CLOCK_AHB_DIV RCC_CFGR_HPRE_DIV1 #define CLOCK_AHB (CLOCK_CORECLOCK / 1) #define CLOCK_APB1_DIV RCC_CFGR_PPRE1_DIV4 /* max 42MHz */ #define CLOCK_APB1 (CLOCK_CORECLOCK / 4) #define CLOCK_APB2_DIV RCC_CFGR_PPRE2_DIV2 /* max 84MHz */ #define CLOCK_APB2 (CLOCK_CORECLOCK / 2) + +/* Main PLL factors */ +#define CLOCK_PLL_M (8) +#define CLOCK_PLL_N (168) +#define CLOCK_PLL_P (2) +#define CLOCK_PLL_Q (7) /** @} */ /** diff --git a/boards/msbiot/include/periph_conf.h b/boards/msbiot/include/periph_conf.h index e3045332e6..52629ab8d4 100644 --- a/boards/msbiot/include/periph_conf.h +++ b/boards/msbiot/include/periph_conf.h @@ -26,25 +26,34 @@ extern "C" { #endif /** - * @name Clock system configuration + * @name Clock settings + * + * @note This is auto-generated from + * `cpu/stm32_common/dist/clk_conf/clk_conf.c` * @{ */ +/* give the target core clock (HCLK) frequency [in Hz], + * maximum: 168MHz */ +#define CLOCK_CORECLOCK (168000000U) /* 0: no external high speed crystal available * else: actual crystal frequency [in Hz] */ #define CLOCK_HSE (16000000U) /* 0: no external low speed crystal available, * 1: external crystal available (always 32.768kHz) */ #define CLOCK_LSE (0) -/* give the target core clock (HCLK) frequency [in Hz], - * maximum: 168MHz */ -#define CLOCK_CORECLOCK (168000000U) /* peripheral clock setup */ -#define CLOCK_AHB_DIV RCC_CFGR_HPRE_DIV1 /* min 25MHz */ +#define CLOCK_AHB_DIV RCC_CFGR_HPRE_DIV1 #define CLOCK_AHB (CLOCK_CORECLOCK / 1) #define CLOCK_APB1_DIV RCC_CFGR_PPRE1_DIV4 /* max 42MHz */ #define CLOCK_APB1 (CLOCK_CORECLOCK / 4) #define CLOCK_APB2_DIV RCC_CFGR_PPRE2_DIV2 /* max 84MHz */ #define CLOCK_APB2 (CLOCK_CORECLOCK / 2) + +/* Main PLL factors */ +#define CLOCK_PLL_M (8) +#define CLOCK_PLL_N (168) +#define CLOCK_PLL_P (2) +#define CLOCK_PLL_Q (7) /** @} */ /** diff --git a/boards/nucleo-f401/include/periph_conf.h b/boards/nucleo-f401/include/periph_conf.h index ae5ce5ccfb..6bcfe0c610 100644 --- a/boards/nucleo-f401/include/periph_conf.h +++ b/boards/nucleo-f401/include/periph_conf.h @@ -26,27 +26,34 @@ extern "C" { #endif /** - * @name Clock system configuration + * @name Clock settings + * + * @note This is auto-generated from + * `cpu/stm32_common/dist/clk_conf/clk_conf.c` * @{ */ +/* give the target core clock (HCLK) frequency [in Hz], + * maximum: 84MHz */ +#define CLOCK_CORECLOCK (84000000U) /* 0: no external high speed crystal available * else: actual crystal frequency [in Hz] */ #define CLOCK_HSE (8000000U) /* 0: no external low speed crystal available, * 1: external crystal available (always 32.768kHz) */ #define CLOCK_LSE (1) -/* give the target core clock (HCLK) frequency [in Hz], - * maximum: 84MHz */ -#define CLOCK_CORECLOCK (84000000U) -/* PLL Output divisor */ -#define P (4U) /* peripheral clock setup */ -#define CLOCK_AHB_DIV RCC_CFGR_HPRE_DIV1 /* min 25MHz */ +#define CLOCK_AHB_DIV RCC_CFGR_HPRE_DIV1 #define CLOCK_AHB (CLOCK_CORECLOCK / 1) #define CLOCK_APB1_DIV RCC_CFGR_PPRE1_DIV2 /* max 42MHz */ #define CLOCK_APB1 (CLOCK_CORECLOCK / 2) #define CLOCK_APB2_DIV RCC_CFGR_PPRE2_DIV1 /* max 84MHz */ #define CLOCK_APB2 (CLOCK_CORECLOCK / 1) + +/* Main PLL factors */ +#define CLOCK_PLL_M (4) +#define CLOCK_PLL_N (168) +#define CLOCK_PLL_P (4) +#define CLOCK_PLL_Q (7) /** @} */ /** diff --git a/boards/nucleo-f410/include/periph_conf.h b/boards/nucleo-f410/include/periph_conf.h index 1f2f29edb8..0c8fb5a590 100644 --- a/boards/nucleo-f410/include/periph_conf.h +++ b/boards/nucleo-f410/include/periph_conf.h @@ -26,25 +26,34 @@ extern "C" { #endif /** - * @name Clock system configuration + * @name Clock settings + * + * @note This is auto-generated from + * `cpu/stm32_common/dist/clk_conf/clk_conf.c` * @{ */ +/* give the target core clock (HCLK) frequency [in Hz], + * maximum: 100MHz */ +#define CLOCK_CORECLOCK (96000000U) /* 0: no external high speed crystal available * else: actual crystal frequency [in Hz] */ #define CLOCK_HSE (8000000U) /* 0: no external low speed crystal available, * 1: external crystal available (always 32.768kHz) */ #define CLOCK_LSE (1) -/* give the target core clock (HCLK) frequency [in Hz], - * maximum: 100MHz */ -#define CLOCK_CORECLOCK (96000000U) /* peripheral clock setup */ -#define CLOCK_AHB_DIV RCC_CFGR_HPRE_DIV1 /* min 25MHz */ +#define CLOCK_AHB_DIV RCC_CFGR_HPRE_DIV1 #define CLOCK_AHB (CLOCK_CORECLOCK / 1) #define CLOCK_APB1_DIV RCC_CFGR_PPRE1_DIV2 /* max 50MHz */ #define CLOCK_APB1 (CLOCK_CORECLOCK / 2) #define CLOCK_APB2_DIV RCC_CFGR_PPRE2_DIV1 /* max 100MHz */ #define CLOCK_APB2 (CLOCK_CORECLOCK / 1) + +/* Main PLL factors */ +#define CLOCK_PLL_M (4) +#define CLOCK_PLL_N (192) +#define CLOCK_PLL_P (4) +#define CLOCK_PLL_Q (8) /** @} */ /** @@ -119,19 +128,19 @@ static const uart_conf_t uart_config[] = { * @{ */ static const uint8_t spi_divtable[2][5] = { - { /* for APB1 @ 50000000Hz */ - 7, /* -> 195312Hz */ - 6, /* -> 390625Hz */ - 5, /* -> 781250Hz */ - 2, /* -> 6250000Hz */ - 1 /* -> 12500000Hz */ + { /* for APB1 @ 48000000Hz */ + 7, /* -> 187500Hz */ + 6, /* -> 375000Hz */ + 5, /* -> 750000Hz */ + 2, /* -> 6000000Hz */ + 1 /* -> 12000000Hz */ }, - { /* for APB2 @ 100000000Hz */ - 7, /* -> 390625Hz */ - 7, /* -> 390625Hz */ - 6, /* -> 781250Hz */ - 3, /* -> 6250000Hz */ - 2 /* -> 12500000Hz */ + { /* for APB2 @ 96000000Hz */ + 7, /* -> 375000Hz */ + 7, /* -> 375000Hz */ + 6, /* -> 750000Hz */ + 3, /* -> 6000000Hz */ + 2 /* -> 12000000Hz */ } }; diff --git a/boards/nucleo-f411/include/periph_conf.h b/boards/nucleo-f411/include/periph_conf.h index 4ce6b7fb12..05077cc2c8 100644 --- a/boards/nucleo-f411/include/periph_conf.h +++ b/boards/nucleo-f411/include/periph_conf.h @@ -26,25 +26,34 @@ extern "C" { #endif /** - * @name Clock system configuration + * @name Clock settings + * + * @note This is auto-generated from + * `cpu/stm32_common/dist/clk_conf/clk_conf.c` * @{ */ +/* give the target core clock (HCLK) frequency [in Hz], + * maximum: 100MHz */ +#define CLOCK_CORECLOCK (96000000U) /* 0: no external high speed crystal available * else: actual crystal frequency [in Hz] */ #define CLOCK_HSE (8000000U) /* 0: no external low speed crystal available, * 1: external crystal available (always 32.768kHz) */ #define CLOCK_LSE (1) -/* give the target core clock (HCLK) frequency [in Hz], - * maximum: 100MHz */ -#define CLOCK_CORECLOCK (96000000U) /* peripheral clock setup */ -#define CLOCK_AHB_DIV RCC_CFGR_HPRE_DIV1 /* min 25MHz */ +#define CLOCK_AHB_DIV RCC_CFGR_HPRE_DIV1 #define CLOCK_AHB (CLOCK_CORECLOCK / 1) #define CLOCK_APB1_DIV RCC_CFGR_PPRE1_DIV2 /* max 50MHz */ #define CLOCK_APB1 (CLOCK_CORECLOCK / 2) #define CLOCK_APB2_DIV RCC_CFGR_PPRE2_DIV1 /* max 100MHz */ #define CLOCK_APB2 (CLOCK_CORECLOCK / 1) + +/* Main PLL factors */ +#define CLOCK_PLL_M (4) +#define CLOCK_PLL_N (192) +#define CLOCK_PLL_P (4) +#define CLOCK_PLL_Q (8) /** @} */ /** @@ -165,19 +174,19 @@ static const pwm_conf_t pwm_config[] = { * @{ */ static const uint8_t spi_divtable[2][5] = { - { /* for APB1 @ 50000000Hz */ - 7, /* -> 195312Hz */ - 6, /* -> 390625Hz */ - 5, /* -> 781250Hz */ - 2, /* -> 6250000Hz */ - 1 /* -> 12500000Hz */ + { /* for APB1 @ 48000000Hz */ + 7, /* -> 187500Hz */ + 6, /* -> 375000Hz */ + 5, /* -> 750000Hz */ + 2, /* -> 6000000Hz */ + 1 /* -> 12000000Hz */ }, - { /* for APB2 @ 100000000Hz */ - 7, /* -> 390625Hz */ - 7, /* -> 390625Hz */ - 6, /* -> 781250Hz */ - 3, /* -> 6250000Hz */ - 2 /* -> 12500000Hz */ + { /* for APB2 @ 96000000Hz */ + 7, /* -> 375000Hz */ + 7, /* -> 375000Hz */ + 6, /* -> 750000Hz */ + 3, /* -> 6000000Hz */ + 2 /* -> 12000000Hz */ } }; diff --git a/boards/nucleo-f446/include/periph_conf.h b/boards/nucleo-f446/include/periph_conf.h index 62ba179169..2ce1f9526a 100644 --- a/boards/nucleo-f446/include/periph_conf.h +++ b/boards/nucleo-f446/include/periph_conf.h @@ -26,25 +26,44 @@ extern "C" { #endif /** - * @name Clock system configuration + * @name Clock settings + * + * @note This is auto-generated from + * `cpu/stm32_common/dist/clk_conf/clk_conf.c` * @{ */ +/* give the target core clock (HCLK) frequency [in Hz], + * maximum: 180MHz */ +#define CLOCK_CORECLOCK (180000000U) /* 0: no external high speed crystal available * else: actual crystal frequency [in Hz] */ #define CLOCK_HSE (8000000U) /* 0: no external low speed crystal available, * 1: external crystal available (always 32.768kHz) */ #define CLOCK_LSE (1) -/* give the target core clock (HCLK) frequency [in Hz], - * maximum: 180MHz */ -#define CLOCK_CORECLOCK (168000000U) /* peripheral clock setup */ -#define CLOCK_AHB_DIV RCC_CFGR_HPRE_DIV1 /* min 25MHz */ +#define CLOCK_AHB_DIV RCC_CFGR_HPRE_DIV1 #define CLOCK_AHB (CLOCK_CORECLOCK / 1) #define CLOCK_APB1_DIV RCC_CFGR_PPRE1_DIV4 /* max 45MHz */ #define CLOCK_APB1 (CLOCK_CORECLOCK / 4) #define CLOCK_APB2_DIV RCC_CFGR_PPRE2_DIV2 /* max 90MHz */ #define CLOCK_APB2 (CLOCK_CORECLOCK / 2) + +/* Main PLL factors */ +#define CLOCK_PLL_M (4) +#define CLOCK_PLL_N (180) +#define CLOCK_PLL_P (2) +#define CLOCK_PLL_Q (0) + +/* PLL SAI configuration */ +#define CLOCK_ENABLE_PLL_SAI (1) +#define CLOCK_PLL_SAI_M (4) +#define CLOCK_PLL_SAI_N (192) +#define CLOCK_PLL_SAI_P (8) +#define CLOCK_PLL_SAI_Q (0) + +/* Use alternative source for 48MHz clock */ +#define CLOCK_USE_ALT_48MHZ (1) /** @} */ /** diff --git a/boards/nucleo144-f207/include/periph_conf.h b/boards/nucleo144-f207/include/periph_conf.h index 47b12acd23..9735c5d2cb 100644 --- a/boards/nucleo144-f207/include/periph_conf.h +++ b/boards/nucleo144-f207/include/periph_conf.h @@ -28,25 +28,34 @@ extern "C" { #endif /** - * @name Clock system configuration + * @name Clock settings + * + * @note This is auto-generated from + * `cpu/stm32_common/dist/clk_conf/clk_conf.c` * @{ */ +/* give the target core clock (HCLK) frequency [in Hz], + * maximum: 120MHz */ +#define CLOCK_CORECLOCK (120000000U) /* 0: no external high speed crystal available * else: actual crystal frequency [in Hz] */ #define CLOCK_HSE (8000000U) /* 0: no external low speed crystal available, * 1: external crystal available (always 32.768kHz) */ #define CLOCK_LSE (1) -/* give the target core clock (HCLK) frequency [in Hz], - * maximum: 120MHz */ -#define CLOCK_CORECLOCK (120000000U) /* peripheral clock setup */ -#define CLOCK_AHB_DIV RCC_CFGR_HPRE_DIV1 /* min 25MHz */ +#define CLOCK_AHB_DIV RCC_CFGR_HPRE_DIV1 #define CLOCK_AHB (CLOCK_CORECLOCK / 1) #define CLOCK_APB1_DIV RCC_CFGR_PPRE1_DIV4 /* max 30MHz */ #define CLOCK_APB1 (CLOCK_CORECLOCK / 4) #define CLOCK_APB2_DIV RCC_CFGR_PPRE2_DIV2 /* max 60MHz */ #define CLOCK_APB2 (CLOCK_CORECLOCK / 2) + +/* Main PLL factors */ +#define CLOCK_PLL_M (4) +#define CLOCK_PLL_N (120) +#define CLOCK_PLL_P (2) +#define CLOCK_PLL_Q (5) /** @} */ /** diff --git a/boards/nucleo144-f412/include/periph_conf.h b/boards/nucleo144-f412/include/periph_conf.h index 842baa7fb2..980ebd0629 100644 --- a/boards/nucleo144-f412/include/periph_conf.h +++ b/boards/nucleo144-f412/include/periph_conf.h @@ -28,25 +28,45 @@ extern "C" { #endif /** - * @name Clock system configuration + * @name Clock settings + * + * @note This is auto-generated from + * `cpu/stm32_common/dist/clk_conf/clk_conf.c` * @{ */ +/* give the target core clock (HCLK) frequency [in Hz], + * maximum: 100MHz */ +#define CLOCK_CORECLOCK (100000000U) /* 0: no external high speed crystal available * else: actual crystal frequency [in Hz] */ #define CLOCK_HSE (8000000U) /* 0: no external low speed crystal available, * 1: external crystal available (always 32.768kHz) */ #define CLOCK_LSE (1) -/* give the target core clock (HCLK) frequency [in Hz], - * maximum: 100MHz */ -#define CLOCK_CORECLOCK (96000000U) /* peripheral clock setup */ -#define CLOCK_AHB_DIV RCC_CFGR_HPRE_DIV1 /* min 25MHz */ +#define CLOCK_AHB_DIV RCC_CFGR_HPRE_DIV1 #define CLOCK_AHB (CLOCK_CORECLOCK / 1) #define CLOCK_APB1_DIV RCC_CFGR_PPRE1_DIV2 /* max 50MHz */ #define CLOCK_APB1 (CLOCK_CORECLOCK / 2) #define CLOCK_APB2_DIV RCC_CFGR_PPRE2_DIV1 /* max 100MHz */ #define CLOCK_APB2 (CLOCK_CORECLOCK / 1) + +/* Main PLL factors */ +#define CLOCK_PLL_M (4) +#define CLOCK_PLL_N (200) +#define CLOCK_PLL_P (4) +#define CLOCK_PLL_Q (0) + +/* PLL I2S configuration */ +#define CLOCK_ENABLE_PLL_I2S (1) +#define CLOCK_PLL_I2S_SRC (0) +#define CLOCK_PLL_I2S_M (4) +#define CLOCK_PLL_I2S_N (216) +#define CLOCK_PLL_I2S_P (0) +#define CLOCK_PLL_I2S_Q (9) + +/* Use alternative source for 48MHz clock */ +#define CLOCK_USE_ALT_48MHZ (1) /** @} */ /** diff --git a/boards/nucleo144-f413/include/periph_conf.h b/boards/nucleo144-f413/include/periph_conf.h index c478221890..69d4aed14d 100644 --- a/boards/nucleo144-f413/include/periph_conf.h +++ b/boards/nucleo144-f413/include/periph_conf.h @@ -28,25 +28,45 @@ extern "C" { #endif /** - * @name Clock system configuration + * @name Clock settings + * + * @note This is auto-generated from + * `cpu/stm32_common/dist/clk_conf/clk_conf.c` * @{ */ +/* give the target core clock (HCLK) frequency [in Hz], + * maximum: 100MHz */ +#define CLOCK_CORECLOCK (100000000U) /* 0: no external high speed crystal available * else: actual crystal frequency [in Hz] */ #define CLOCK_HSE (8000000U) /* 0: no external low speed crystal available, * 1: external crystal available (always 32.768kHz) */ #define CLOCK_LSE (1) -/* give the target core clock (HCLK) frequency [in Hz], - * maximum: 100MHz */ -#define CLOCK_CORECLOCK (96000000U) /* peripheral clock setup */ -#define CLOCK_AHB_DIV RCC_CFGR_HPRE_DIV1 /* min 25MHz */ +#define CLOCK_AHB_DIV RCC_CFGR_HPRE_DIV1 #define CLOCK_AHB (CLOCK_CORECLOCK / 1) #define CLOCK_APB1_DIV RCC_CFGR_PPRE1_DIV2 /* max 50MHz */ #define CLOCK_APB1 (CLOCK_CORECLOCK / 2) #define CLOCK_APB2_DIV RCC_CFGR_PPRE2_DIV1 /* max 100MHz */ #define CLOCK_APB2 (CLOCK_CORECLOCK / 1) + +/* Main PLL factors */ +#define CLOCK_PLL_M (4) +#define CLOCK_PLL_N (200) +#define CLOCK_PLL_P (4) +#define CLOCK_PLL_Q (0) + +/* PLL I2S configuration */ +#define CLOCK_ENABLE_PLL_I2S (1) +#define CLOCK_PLL_I2S_SRC (0) +#define CLOCK_PLL_I2S_M (4) +#define CLOCK_PLL_I2S_N (216) +#define CLOCK_PLL_I2S_P (0) +#define CLOCK_PLL_I2S_Q (9) + +/* Use alternative source for 48MHz clock */ +#define CLOCK_USE_ALT_48MHZ (1) /** @} */ /** diff --git a/boards/nucleo144-f429/include/periph_conf.h b/boards/nucleo144-f429/include/periph_conf.h index 3679d69232..230793cbc2 100644 --- a/boards/nucleo144-f429/include/periph_conf.h +++ b/boards/nucleo144-f429/include/periph_conf.h @@ -26,25 +26,34 @@ extern "C" { #endif /** - * @name Clock system configuration + * @name Clock settings + * + * @note This is auto-generated from + * `cpu/stm32_common/dist/clk_conf/clk_conf.c` * @{ */ +/* give the target core clock (HCLK) frequency [in Hz], + * maximum: 180MHz */ +#define CLOCK_CORECLOCK (168000000U) /* 0: no external high speed crystal available * else: actual crystal frequency [in Hz] */ #define CLOCK_HSE (8000000U) /* 0: no external low speed crystal available, * 1: external crystal available (always 32.768kHz) */ #define CLOCK_LSE (1) -/* give the target core clock (HCLK) frequency [in Hz], - * maximum: 180MHz */ -#define CLOCK_CORECLOCK (168000000U) /* peripheral clock setup */ -#define CLOCK_AHB_DIV RCC_CFGR_HPRE_DIV1 /* min 25MHz */ +#define CLOCK_AHB_DIV RCC_CFGR_HPRE_DIV1 #define CLOCK_AHB (CLOCK_CORECLOCK / 1) #define CLOCK_APB1_DIV RCC_CFGR_PPRE1_DIV4 /* max 45MHz */ #define CLOCK_APB1 (CLOCK_CORECLOCK / 4) #define CLOCK_APB2_DIV RCC_CFGR_PPRE2_DIV2 /* max 90MHz */ #define CLOCK_APB2 (CLOCK_CORECLOCK / 2) + +/* Main PLL factors */ +#define CLOCK_PLL_M (4) +#define CLOCK_PLL_N (168) +#define CLOCK_PLL_P (2) +#define CLOCK_PLL_Q (7) /** @} */ /** diff --git a/boards/nucleo144-f446/include/periph_conf.h b/boards/nucleo144-f446/include/periph_conf.h index 70905380ed..56d42da52d 100644 --- a/boards/nucleo144-f446/include/periph_conf.h +++ b/boards/nucleo144-f446/include/periph_conf.h @@ -26,25 +26,44 @@ extern "C" { #endif /** - * @name Clock system configuration + * @name Clock settings + * + * @note This is auto-generated from + * `cpu/stm32_common/dist/clk_conf/clk_conf.c` * @{ */ +/* give the target core clock (HCLK) frequency [in Hz], + * maximum: 180MHz */ +#define CLOCK_CORECLOCK (180000000U) /* 0: no external high speed crystal available * else: actual crystal frequency [in Hz] */ #define CLOCK_HSE (8000000U) /* 0: no external low speed crystal available, * 1: external crystal available (always 32.768kHz) */ #define CLOCK_LSE (1) -/* give the target core clock (HCLK) frequency [in Hz], - * maximum: 100MHz */ -#define CLOCK_CORECLOCK (168000000U) /* peripheral clock setup */ -#define CLOCK_AHB_DIV RCC_CFGR_HPRE_DIV1 /* min 25MHz */ +#define CLOCK_AHB_DIV RCC_CFGR_HPRE_DIV1 #define CLOCK_AHB (CLOCK_CORECLOCK / 1) #define CLOCK_APB1_DIV RCC_CFGR_PPRE1_DIV4 /* max 45MHz */ #define CLOCK_APB1 (CLOCK_CORECLOCK / 4) #define CLOCK_APB2_DIV RCC_CFGR_PPRE2_DIV2 /* max 90MHz */ #define CLOCK_APB2 (CLOCK_CORECLOCK / 2) + +/* Main PLL factors */ +#define CLOCK_PLL_M (4) +#define CLOCK_PLL_N (180) +#define CLOCK_PLL_P (2) +#define CLOCK_PLL_Q (0) + +/* PLL SAI configuration */ +#define CLOCK_ENABLE_PLL_SAI (1) +#define CLOCK_PLL_SAI_M (4) +#define CLOCK_PLL_SAI_N (192) +#define CLOCK_PLL_SAI_P (8) +#define CLOCK_PLL_SAI_Q (0) + +/* Use alternative source for 48MHz clock */ +#define CLOCK_USE_ALT_48MHZ (1) /** @} */ /** diff --git a/boards/nucleo144-f722/include/periph_conf.h b/boards/nucleo144-f722/include/periph_conf.h index e93c86811a..67f6b9cc81 100644 --- a/boards/nucleo144-f722/include/periph_conf.h +++ b/boards/nucleo144-f722/include/periph_conf.h @@ -26,25 +26,34 @@ extern "C" { #endif /** - * @name Clock system configuration + * @name Clock settings + * + * @note This is auto-generated from + * `cpu/stm32_common/dist/clk_conf/clk_conf.c` * @{ */ +/* give the target core clock (HCLK) frequency [in Hz], + * maximum: 216MHz */ +#define CLOCK_CORECLOCK (216000000U) /* 0: no external high speed crystal available * else: actual crystal frequency [in Hz] */ #define CLOCK_HSE (8000000U) /* 0: no external low speed crystal available, * 1: external crystal available (always 32.768kHz) */ #define CLOCK_LSE (1) -/* give the target core clock (HCLK) frequency [in Hz], - * maximum: 216MHz, min: 96MHz, must be multiple of 24MHz */ -#define CLOCK_CORECLOCK (216000000U) /* peripheral clock setup */ -#define CLOCK_AHB_DIV RCC_CFGR_HPRE_DIV1 /* min 25MHz */ +#define CLOCK_AHB_DIV RCC_CFGR_HPRE_DIV1 #define CLOCK_AHB (CLOCK_CORECLOCK / 1) #define CLOCK_APB1_DIV RCC_CFGR_PPRE1_DIV4 /* max 54MHz */ #define CLOCK_APB1 (CLOCK_CORECLOCK / 4) #define CLOCK_APB2_DIV RCC_CFGR_PPRE2_DIV2 /* max 108MHz */ #define CLOCK_APB2 (CLOCK_CORECLOCK / 2) + +/* Main PLL factors */ +#define CLOCK_PLL_M (4) +#define CLOCK_PLL_N (216) +#define CLOCK_PLL_P (2) +#define CLOCK_PLL_Q (9) /** @} */ /** diff --git a/boards/nucleo144-f746/include/periph_conf.h b/boards/nucleo144-f746/include/periph_conf.h index 46cc3540c6..b74fc07806 100644 --- a/boards/nucleo144-f746/include/periph_conf.h +++ b/boards/nucleo144-f746/include/periph_conf.h @@ -26,25 +26,34 @@ extern "C" { #endif /** - * @name Clock system configuration + * @name Clock settings + * + * @note This is auto-generated from + * `cpu/stm32_common/dist/clk_conf/clk_conf.c` * @{ */ +/* give the target core clock (HCLK) frequency [in Hz], + * maximum: 216MHz */ +#define CLOCK_CORECLOCK (216000000U) /* 0: no external high speed crystal available * else: actual crystal frequency [in Hz] */ #define CLOCK_HSE (8000000U) /* 0: no external low speed crystal available, * 1: external crystal available (always 32.768kHz) */ #define CLOCK_LSE (1) -/* give the target core clock (HCLK) frequency [in Hz], - * maximum: 216MHz, min: 96MHz, must be multiple of 24MHz */ -#define CLOCK_CORECLOCK (216000000U) /* peripheral clock setup */ -#define CLOCK_AHB_DIV RCC_CFGR_HPRE_DIV1 /* min 25MHz */ +#define CLOCK_AHB_DIV RCC_CFGR_HPRE_DIV1 #define CLOCK_AHB (CLOCK_CORECLOCK / 1) #define CLOCK_APB1_DIV RCC_CFGR_PPRE1_DIV4 /* max 54MHz */ #define CLOCK_APB1 (CLOCK_CORECLOCK / 4) #define CLOCK_APB2_DIV RCC_CFGR_PPRE2_DIV2 /* max 108MHz */ #define CLOCK_APB2 (CLOCK_CORECLOCK / 2) + +/* Main PLL factors */ +#define CLOCK_PLL_M (4) +#define CLOCK_PLL_N (216) +#define CLOCK_PLL_P (2) +#define CLOCK_PLL_Q (9) /** @} */ /** diff --git a/boards/nucleo144-f767/include/periph_conf.h b/boards/nucleo144-f767/include/periph_conf.h index 0242bc2c45..ec67f3c8a8 100644 --- a/boards/nucleo144-f767/include/periph_conf.h +++ b/boards/nucleo144-f767/include/periph_conf.h @@ -26,25 +26,34 @@ extern "C" { #endif /** - * @name Clock system configuration + * @name Clock settings + * + * @note This is auto-generated from + * `cpu/stm32_common/dist/clk_conf/clk_conf.c` * @{ */ +/* give the target core clock (HCLK) frequency [in Hz], + * maximum: 216MHz */ +#define CLOCK_CORECLOCK (216000000U) /* 0: no external high speed crystal available * else: actual crystal frequency [in Hz] */ #define CLOCK_HSE (8000000U) /* 0: no external low speed crystal available, * 1: external crystal available (always 32.768kHz) */ #define CLOCK_LSE (1) -/* give the target core clock (HCLK) frequency [in Hz], - * maximum: 216MHz, min: 96MHz, must be multiple of 24MHz */ -#define CLOCK_CORECLOCK (216000000U) /* peripheral clock setup */ -#define CLOCK_AHB_DIV RCC_CFGR_HPRE_DIV1 /* min 25MHz */ +#define CLOCK_AHB_DIV RCC_CFGR_HPRE_DIV1 #define CLOCK_AHB (CLOCK_CORECLOCK / 1) #define CLOCK_APB1_DIV RCC_CFGR_PPRE1_DIV4 /* max 54MHz */ #define CLOCK_APB1 (CLOCK_CORECLOCK / 4) #define CLOCK_APB2_DIV RCC_CFGR_PPRE2_DIV2 /* max 108MHz */ #define CLOCK_APB2 (CLOCK_CORECLOCK / 2) + +/* Main PLL factors */ +#define CLOCK_PLL_M (4) +#define CLOCK_PLL_N (216) +#define CLOCK_PLL_P (2) +#define CLOCK_PLL_Q (9) /** @} */ /** diff --git a/boards/stm32f4discovery/include/periph_conf.h b/boards/stm32f4discovery/include/periph_conf.h index c1ab8c8afb..9bc1f93e2d 100644 --- a/boards/stm32f4discovery/include/periph_conf.h +++ b/boards/stm32f4discovery/include/periph_conf.h @@ -27,25 +27,34 @@ extern "C" { #endif /** - * @name Clock system configuration + * @name Clock settings + * + * @note This is auto-generated from + * `cpu/stm32_common/dist/clk_conf/clk_conf.c` * @{ */ +/* give the target core clock (HCLK) frequency [in Hz], + * maximum: 168MHz */ +#define CLOCK_CORECLOCK (168000000U) /* 0: no external high speed crystal available * else: actual crystal frequency [in Hz] */ #define CLOCK_HSE (8000000U) /* 0: no external low speed crystal available, * 1: external crystal available (always 32.768kHz) */ #define CLOCK_LSE (1) -/* give the target core clock (HCLK) frequency [in Hz], - * maximum: 168MHz */ -#define CLOCK_CORECLOCK (168000000U) /* peripheral clock setup */ -#define CLOCK_AHB_DIV RCC_CFGR_HPRE_DIV1 /* min 25MHz */ +#define CLOCK_AHB_DIV RCC_CFGR_HPRE_DIV1 #define CLOCK_AHB (CLOCK_CORECLOCK / 1) #define CLOCK_APB1_DIV RCC_CFGR_PPRE1_DIV4 /* max 42MHz */ #define CLOCK_APB1 (CLOCK_CORECLOCK / 4) #define CLOCK_APB2_DIV RCC_CFGR_PPRE2_DIV2 /* max 84MHz */ #define CLOCK_APB2 (CLOCK_CORECLOCK / 2) + +/* Main PLL factors */ +#define CLOCK_PLL_M (4) +#define CLOCK_PLL_N (168) +#define CLOCK_PLL_P (2) +#define CLOCK_PLL_Q (7) /** @} */ /** diff --git a/boards/stm32f7discovery/include/periph_conf.h b/boards/stm32f7discovery/include/periph_conf.h index 95eaaf5f98..759d56aced 100644 --- a/boards/stm32f7discovery/include/periph_conf.h +++ b/boards/stm32f7discovery/include/periph_conf.h @@ -26,25 +26,34 @@ extern "C" { #endif /** - * @name Clock system configuration + * @name Clock settings + * + * @note This is auto-generated from + * `cpu/stm32_common/dist/clk_conf/clk_conf.c` * @{ */ +/* give the target core clock (HCLK) frequency [in Hz], + * maximum: 216MHz */ +#define CLOCK_CORECLOCK (216000000U) /* 0: no external high speed crystal available * else: actual crystal frequency [in Hz] */ #define CLOCK_HSE (25000000U) /* 0: no external low speed crystal available, * 1: external crystal available (always 32.768kHz) */ #define CLOCK_LSE (1) -/* give the target core clock (HCLK) frequency [in Hz], - * maximum: 216MHz, min: 96MHz, must be multiple of 48MHz */ -#define CLOCK_CORECLOCK (216000000U) /* peripheral clock setup */ -#define CLOCK_AHB_DIV RCC_CFGR_HPRE_DIV1 /* min 25MHz */ +#define CLOCK_AHB_DIV RCC_CFGR_HPRE_DIV1 #define CLOCK_AHB (CLOCK_CORECLOCK / 1) #define CLOCK_APB1_DIV RCC_CFGR_PPRE1_DIV4 /* max 54MHz */ #define CLOCK_APB1 (CLOCK_CORECLOCK / 4) #define CLOCK_APB2_DIV RCC_CFGR_PPRE2_DIV2 /* max 108MHz */ #define CLOCK_APB2 (CLOCK_CORECLOCK / 2) + +/* Main PLL factors */ +#define CLOCK_PLL_M (25) +#define CLOCK_PLL_N (432) +#define CLOCK_PLL_P (2) +#define CLOCK_PLL_Q (9) /** @} */ /**