diff --git a/include/libopencm3/stm32/f7/flash.h b/include/libopencm3/stm32/f7/flash.h
new file mode 100644
index 00000000..f75fc525
--- /dev/null
+++ b/include/libopencm3/stm32/f7/flash.h
@@ -0,0 +1,37 @@
+/** @defgroup flash_defines FLASH Defines
+ *
+ * @ingroup STM32F7xx_defines
+ *
+ * @brief Defined Constants and Types for the STM32F7xx FLASH Memory
+ *
+ * @version 1.0.0
+ *
+ * @date 14 January 2014
+ *
+ * LGPL License Terms @ref lgpl_license
+ */
+
+/*
+ * This file is part of the libopencm3 project.
+ *
+ * This library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see .
+ */
+
+#ifndef LIBOPENCM3_FLASH_H
+#define LIBOPENCM3_FLASH_H
+
+#include
+
+#endif
+
diff --git a/include/libopencm3/stm32/f7/rcc.h b/include/libopencm3/stm32/f7/rcc.h
index 96c18d95..776cb69b 100644
--- a/include/libopencm3/stm32/f7/rcc.h
+++ b/include/libopencm3/stm32/f7/rcc.h
@@ -595,6 +595,39 @@
#define RCC_DCKCFGR2_UART1SEL_MASK 0x3
#define RCC_DCKCFGR2_UART1SEL_SHIFT 0
+extern uint32_t rcc_ahb_frequency;
+extern uint32_t rcc_apb1_frequency;
+extern uint32_t rcc_apb2_frequency;
+
+enum rcc_clock_3v3 {
+ RCC_CLOCK_3V3_216MHZ,
+ RCC_CLOCK_3V3_END
+};
+
+struct rcc_clock_scale {
+ uint8_t pllm;
+ uint16_t plln;
+ uint8_t pllp;
+ uint8_t pllq;
+ uint32_t flash_config;
+ uint8_t hpre;
+ uint8_t ppre1;
+ uint8_t ppre2;
+ uint8_t power_save;
+ uint32_t apb1_frequency;
+ uint32_t apb2_frequency;
+};
+
+extern const struct rcc_clock_scale rcc_hse_25mhz_3v3[RCC_CLOCK_3V3_END];
+
+enum rcc_osc {
+ RCC_PLL,
+ RCC_HSE,
+ RCC_HSI,
+ RCC_LSE,
+ RCC_LSI
+};
+
#define _REG_BIT(base, bit) (((base) << 5) + (bit))
enum rcc_periph_clken {
@@ -870,7 +903,31 @@ enum rcc_periph_rst {
#include
BEGIN_DECLS
-
+void rcc_osc_ready_int_clear(enum rcc_osc osc);
+void rcc_osc_ready_int_enable(enum rcc_osc osc);
+void rcc_osc_ready_int_disable(enum rcc_osc osc);
+int rcc_osc_ready_int_flag(enum rcc_osc osc);
+void rcc_css_int_clear(void);
+int rcc_css_int_flag(void);
+void rcc_wait_for_sysclk_status(enum rcc_osc osc);
+void rcc_osc_on(enum rcc_osc osc);
+void rcc_osc_off(enum rcc_osc osc);
+void rcc_css_enable(void);
+void rcc_css_disable(void);
+void rcc_osc_bypass_enable(enum rcc_osc osc);
+void rcc_osc_bypass_disable(enum rcc_osc osc);
+void rcc_set_sysclk_source(uint32_t clk);
+void rcc_set_pll_source(uint32_t pllsrc);
+void rcc_set_ppre2(uint32_t ppre2);
+void rcc_set_ppre1(uint32_t ppre1);
+void rcc_set_hpre(uint32_t hpre);
+void rcc_set_rtcpre(uint32_t rtcpre);
+void rcc_set_main_pll_hsi(uint32_t pllm, uint32_t plln, uint32_t pllp,
+ uint32_t pllq);
+void rcc_set_main_pll_hse(uint32_t pllm, uint32_t plln, uint32_t pllp,
+ uint32_t pllq);
+uint32_t rcc_system_clock_source(void);
+void rcc_clock_setup_hse_3v3(const struct rcc_clock_scale *clock);
END_DECLS
#endif
diff --git a/include/libopencm3/stm32/flash.h b/include/libopencm3/stm32/flash.h
index b9b53678..acaba1e2 100644
--- a/include/libopencm3/stm32/flash.h
+++ b/include/libopencm3/stm32/flash.h
@@ -30,6 +30,8 @@
# include
#elif defined(STM32F4)
# include
+#elif defined(STM32F7)
+# include
#elif defined(STM32L1)
# include
#elif defined(STM32L4)
diff --git a/lib/stm32/f7/Makefile b/lib/stm32/f7/Makefile
index 1d245172..29a6fc98 100644
--- a/lib/stm32/f7/Makefile
+++ b/lib/stm32/f7/Makefile
@@ -42,7 +42,7 @@ ARFLAGS = rcs
OBJS = rcc.o gpio.o gpio_common_all.o gpio_common_f0234.o
-OBJS += rcc_common_all.o
+OBJS += rcc_common_all.o flash_common_f234.o flash_common_f24.o
OBJS += rng_common_v1.o
diff --git a/lib/stm32/f7/rcc.c b/lib/stm32/f7/rcc.c
index 4698ac34..4039e713 100644
--- a/lib/stm32/f7/rcc.c
+++ b/lib/stm32/f7/rcc.c
@@ -1,11 +1,378 @@
+#include
#include
+#include
uint32_t rcc_ahb_frequency = 16000000;
uint32_t rcc_apb1_frequency = 16000000;
uint32_t rcc_apb2_frequency = 16000000;
+const struct rcc_clock_scale rcc_hse_25mhz_3v3[RCC_CLOCK_3V3_END] = {
+ { /* 216MHz */
+ .pllm = 25,
+ .plln = 432,
+ .pllp = 2,
+ .pllq = 9,
+ .hpre = RCC_CFGR_HPRE_DIV_NONE,
+ .ppre1 = RCC_CFGR_PPRE_DIV_4,
+ .ppre2 = RCC_CFGR_PPRE_DIV_2,
+ .flash_config = FLASH_ACR_ICE | FLASH_ACR_DCE |
+ FLASH_ACR_LATENCY_7WS,
+ .apb1_frequency = 108000000,
+ .apb2_frequency = 216000000,
+ },
+};
+
+void rcc_osc_ready_int_clear(enum rcc_osc osc)
+{
+ switch (osc) {
+ case RCC_PLL:
+ RCC_CIR |= RCC_CIR_PLLRDYC;
+ break;
+ case RCC_HSE:
+ RCC_CIR |= RCC_CIR_HSERDYC;
+ break;
+ case RCC_HSI:
+ RCC_CIR |= RCC_CIR_HSIRDYC;
+ break;
+ case RCC_LSE:
+ RCC_CIR |= RCC_CIR_LSERDYC;
+ break;
+ case RCC_LSI:
+ RCC_CIR |= RCC_CIR_LSIRDYC;
+ break;
+ }
+}
+
+void rcc_osc_ready_int_enable(enum rcc_osc osc)
+{
+ switch (osc) {
+ case RCC_PLL:
+ RCC_CIR |= RCC_CIR_PLLRDYIE;
+ break;
+ case RCC_HSE:
+ RCC_CIR |= RCC_CIR_HSERDYIE;
+ break;
+ case RCC_HSI:
+ RCC_CIR |= RCC_CIR_HSIRDYIE;
+ break;
+ case RCC_LSE:
+ RCC_CIR |= RCC_CIR_LSERDYIE;
+ break;
+ case RCC_LSI:
+ RCC_CIR |= RCC_CIR_LSIRDYIE;
+ break;
+ }
+}
+
+void rcc_osc_ready_int_disable(enum rcc_osc osc)
+{
+ switch (osc) {
+ case RCC_PLL:
+ RCC_CIR &= ~RCC_CIR_PLLRDYIE;
+ break;
+ case RCC_HSE:
+ RCC_CIR &= ~RCC_CIR_HSERDYIE;
+ break;
+ case RCC_HSI:
+ RCC_CIR &= ~RCC_CIR_HSIRDYIE;
+ break;
+ case RCC_LSE:
+ RCC_CIR &= ~RCC_CIR_LSERDYIE;
+ break;
+ case RCC_LSI:
+ RCC_CIR &= ~RCC_CIR_LSIRDYIE;
+ break;
+ }
+}
+
+int rcc_osc_ready_int_flag(enum rcc_osc osc)
+{
+ switch (osc) {
+ case RCC_PLL:
+ return ((RCC_CIR & RCC_CIR_PLLRDYF) != 0);
+ break;
+ case RCC_HSE:
+ return ((RCC_CIR & RCC_CIR_HSERDYF) != 0);
+ break;
+ case RCC_HSI:
+ return ((RCC_CIR & RCC_CIR_HSIRDYF) != 0);
+ break;
+ case RCC_LSE:
+ return ((RCC_CIR & RCC_CIR_LSERDYF) != 0);
+ break;
+ case RCC_LSI:
+ return ((RCC_CIR & RCC_CIR_LSIRDYF) != 0);
+ break;
+ }
+
+ cm3_assert_not_reached();
+}
+
+void rcc_css_int_clear(void)
+{
+ RCC_CIR |= RCC_CIR_CSSC;
+}
+
+int rcc_css_int_flag(void)
+{
+ return ((RCC_CIR & RCC_CIR_CSSF) != 0);
+}
+
+void rcc_wait_for_osc_ready(enum rcc_osc osc)
+{
+ switch (osc) {
+ case RCC_PLL:
+ while ((RCC_CR & RCC_CR_PLLRDY) == 0);
+ break;
+ case RCC_HSE:
+ while ((RCC_CR & RCC_CR_HSERDY) == 0);
+ break;
+ case RCC_HSI:
+ while ((RCC_CR & RCC_CR_HSIRDY) == 0);
+ break;
+ case RCC_LSE:
+ while ((RCC_BDCR & RCC_BDCR_LSERDY) == 0);
+ break;
+ case RCC_LSI:
+ while ((RCC_CSR & RCC_CSR_LSIRDY) == 0);
+ break;
+ }
+}
+
+void rcc_wait_for_sysclk_status(enum rcc_osc osc)
+{
+ switch (osc) {
+ case RCC_PLL:
+ while ((RCC_CFGR & ((1 << 1) | (1 << 0))) != RCC_CFGR_SWS_PLL);
+ break;
+ case RCC_HSE:
+ while ((RCC_CFGR & ((1 << 1) | (1 << 0))) != RCC_CFGR_SWS_HSE);
+ break;
+ case RCC_HSI:
+ while ((RCC_CFGR & ((1 << 1) | (1 << 0))) != RCC_CFGR_SWS_HSI);
+ break;
+ default:
+ /* Shouldn't be reached. */
+ break;
+ }
+}
+
+void rcc_osc_on(enum rcc_osc osc)
+{
+ switch (osc) {
+ case RCC_PLL:
+ RCC_CR |= RCC_CR_PLLON;
+ break;
+ case RCC_HSE:
+ RCC_CR |= RCC_CR_HSEON;
+ break;
+ case RCC_HSI:
+ RCC_CR |= RCC_CR_HSION;
+ break;
+ case RCC_LSE:
+ RCC_BDCR |= RCC_BDCR_LSEON;
+ break;
+ case RCC_LSI:
+ RCC_CSR |= RCC_CSR_LSION;
+ break;
+ }
+}
+
+void rcc_osc_off(enum rcc_osc osc)
+{
+ switch (osc) {
+ case RCC_PLL:
+ RCC_CR &= ~RCC_CR_PLLON;
+ break;
+ case RCC_HSE:
+ RCC_CR &= ~RCC_CR_HSEON;
+ break;
+ case RCC_HSI:
+ RCC_CR &= ~RCC_CR_HSION;
+ break;
+ case RCC_LSE:
+ RCC_BDCR &= ~RCC_BDCR_LSEON;
+ break;
+ case RCC_LSI:
+ RCC_CSR &= ~RCC_CSR_LSION;
+ break;
+ }
+}
+
+void rcc_css_enable(void)
+{
+ RCC_CR |= RCC_CR_CSSON;
+}
+
+void rcc_css_disable(void)
+{
+ RCC_CR &= ~RCC_CR_CSSON;
+}
+
+void rcc_osc_bypass_enable(enum rcc_osc osc)
+{
+ switch (osc) {
+ case RCC_HSE:
+ RCC_CR |= RCC_CR_HSEBYP;
+ break;
+ case RCC_LSE:
+ RCC_BDCR |= RCC_BDCR_LSEBYP;
+ break;
+ case RCC_PLL:
+ case RCC_HSI:
+ case RCC_LSI:
+ /* Do nothing, only HSE/LSE allowed here. */
+ break;
+ }
+}
+
+void rcc_osc_bypass_disable(enum rcc_osc osc)
+{
+ switch (osc) {
+ case RCC_HSE:
+ RCC_CR &= ~RCC_CR_HSEBYP;
+ break;
+ case RCC_LSE:
+ RCC_BDCR &= ~RCC_BDCR_LSEBYP;
+ break;
+ case RCC_PLL:
+ case RCC_HSI:
+ case RCC_LSI:
+ /* Do nothing, only HSE/LSE allowed here. */
+ break;
+ }
+}
+
+
+
+void rcc_set_sysclk_source(uint32_t clk)
+{
+ uint32_t reg32;
+
+ reg32 = RCC_CFGR;
+ reg32 &= ~((1 << 1) | (1 << 0));
+ RCC_CFGR = (reg32 | clk);
+}
+
+void rcc_set_pll_source(uint32_t pllsrc)
+{
+ uint32_t reg32;
+
+ reg32 = RCC_PLLCFGR;
+ reg32 &= ~(1 << 22);
+ RCC_PLLCFGR = (reg32 | (pllsrc << 22));
+}
+
+void rcc_set_ppre2(uint32_t ppre2)
+{
+ uint32_t reg32;
+
+ reg32 = RCC_CFGR;
+ reg32 &= ~((1 << 13) | (1 << 14) | (1 << 15));
+ RCC_CFGR = (reg32 | (ppre2 << 13));
+}
+
+void rcc_set_ppre1(uint32_t ppre1)
+{
+ uint32_t reg32;
+
+ reg32 = RCC_CFGR;
+ reg32 &= ~((1 << 10) | (1 << 11) | (1 << 12));
+ RCC_CFGR = (reg32 | (ppre1 << 10));
+}
+
+void rcc_set_hpre(uint32_t hpre)
+{
+ uint32_t reg32;
+
+ reg32 = RCC_CFGR;
+ reg32 &= ~((1 << 4) | (1 << 5) | (1 << 6) | (1 << 7));
+ RCC_CFGR = (reg32 | (hpre << 4));
+}
+
+void rcc_set_rtcpre(uint32_t rtcpre)
+{
+ uint32_t reg32;
+
+ reg32 = RCC_CFGR;
+ reg32 &= ~((1 << 16) | (1 << 17) | (1 << 18) | (1 << 19) | (1 << 20));
+ RCC_CFGR = (reg32 | (rtcpre << 16));
+}
+
+void rcc_set_main_pll_hsi(uint32_t pllm, uint32_t plln, uint32_t pllp,
+ uint32_t pllq)
+{
+ RCC_PLLCFGR = (pllm << RCC_PLLCFGR_PLLM_SHIFT) |
+ (plln << RCC_PLLCFGR_PLLN_SHIFT) |
+ (((pllp >> 1) - 1) << RCC_PLLCFGR_PLLP_SHIFT) |
+ (pllq << RCC_PLLCFGR_PLLQ_SHIFT);
+}
+
+void rcc_set_main_pll_hse(uint32_t pllm, uint32_t plln, uint32_t pllp,
+ uint32_t pllq)
+{
+ RCC_PLLCFGR = (pllm << RCC_PLLCFGR_PLLM_SHIFT) |
+ (plln << RCC_PLLCFGR_PLLN_SHIFT) |
+ (((pllp >> 1) - 1) << RCC_PLLCFGR_PLLP_SHIFT) |
+ RCC_PLLCFGR_PLLSRC |
+ (pllq << RCC_PLLCFGR_PLLQ_SHIFT);
+}
+
uint32_t rcc_system_clock_source(void)
{
/* Return the clock source which is used as system clock. */
return (RCC_CFGR >> RCC_CFGR_SWS_SHIFT) & RCC_CFGR_SWS_MASK;
}
+
+
+void rcc_clock_setup_hse_3v3(const struct rcc_clock_scale *clock)
+{
+ /* Enable internal high-speed oscillator. */
+ rcc_osc_on(RCC_HSI);
+ rcc_wait_for_osc_ready(RCC_HSI);
+
+ /* Select HSI as SYSCLK source. */
+ rcc_set_sysclk_source(RCC_CFGR_SW_HSI);
+
+ /* Enable external high-speed oscillator 8MHz. */
+ rcc_osc_on(RCC_HSE);
+ rcc_wait_for_osc_ready(RCC_HSE);
+
+ /* Enable/disable high performance mode */
+/* if (!clock->power_save) {
+ pwr_set_vos_scale(SCALE1);
+ } else {
+ pwr_set_vos_scale(SCALE2);
+ }
+*/
+ /*
+ * 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);
+
+ rcc_set_main_pll_hse(clock->pllm, clock->plln,
+ clock->pllp, clock->pllq);
+
+ /* Enable PLL oscillator and wait for it to stabilize. */
+ rcc_osc_on(RCC_PLL);
+ rcc_wait_for_osc_ready(RCC_PLL);
+
+ /* Configure flash settings. */
+ flash_set_ws(clock->flash_config);
+
+ /* Select PLL as SYSCLK source. */
+ rcc_set_sysclk_source(RCC_CFGR_SW_PLL);
+
+ /* Wait for PLL clock to be selected. */
+ rcc_wait_for_sysclk_status(RCC_PLL);
+
+ /* Set the peripheral clock frequencies used. */
+ rcc_apb1_frequency = clock->apb1_frequency;
+ rcc_apb2_frequency = clock->apb2_frequency;
+
+ /* Disable internal high-speed oscillator. */
+ rcc_osc_off(RCC_HSI);
+}