[PATCH] bsp/stm32f4XXXX: System clock configuration

tomasz.gregorek at gmail.com tomasz.gregorek at gmail.com
Sun Sep 21 18:07:41 UTC 2014


From: Tomasz Gregorek <tomasz.gregorek at gmail.com>

Added simple math to caclulate register values for the PLL
and for the prescalers. It will try to keep 48MHz for the USB OTG FS.
Also it will set latency on the Flash memory for the high speeds.

Limitations:
It is assumed that 1MHz resolution is enough.
Best fits for the clocks are achieved with multiplies of 42MHz.
Even though APB1, APB2 and AHB are calculated user is still required
to provide correct values for the bsp configuration for the:
STM32F4_PCLK1
STM32F4_PCLK2
STM32F4_HCLK (= system clock)
as those are used for the peripheral clocking calculations.
---
 c/src/lib/libbsp/arm/stm32f4/Makefile.am           |   1 +
 c/src/lib/libbsp/arm/stm32f4/include/stm32f4.h     |  10 +
 .../libbsp/arm/stm32f4/include/stm32f4xxxx_flash.h |  54 ++++
 .../libbsp/arm/stm32f4/include/stm32f4xxxx_rcc.h   | 150 +++++++++--
 c/src/lib/libbsp/arm/stm32f4/preinstall.am         |   4 +
 c/src/lib/libbsp/arm/stm32f4/startup/bspstart.c    | 280 ++++++++++++++++++++-
 6 files changed, 475 insertions(+), 24 deletions(-)
 create mode 100644 c/src/lib/libbsp/arm/stm32f4/include/stm32f4xxxx_flash.h

diff --git a/c/src/lib/libbsp/arm/stm32f4/Makefile.am b/c/src/lib/libbsp/arm/stm32f4/Makefile.am
index 027fcad..055a0b1 100644
--- a/c/src/lib/libbsp/arm/stm32f4/Makefile.am
+++ b/c/src/lib/libbsp/arm/stm32f4/Makefile.am
@@ -51,6 +51,7 @@ include_bsp_HEADERS += include/stm32f10xxx_rcc.h
 include_bsp_HEADERS += include/stm32f10xxx_exti.h
 include_bsp_HEADERS += include/stm32f4xxxx_gpio.h
 include_bsp_HEADERS += include/stm32f4xxxx_rcc.h
+include_bsp_HEADERS += include/stm32f4xxxx_flash.h
 include_bsp_HEADERS += include/stm32_i2c.h
 include_bsp_HEADERS += include/i2c.h
 include_bsp_HEADERS += include/stm32_usart.h
diff --git a/c/src/lib/libbsp/arm/stm32f4/include/stm32f4.h b/c/src/lib/libbsp/arm/stm32f4/include/stm32f4.h
index 59d13ef..d26f914 100644
--- a/c/src/lib/libbsp/arm/stm32f4/include/stm32f4.h
+++ b/c/src/lib/libbsp/arm/stm32f4/include/stm32f4.h
@@ -55,6 +55,16 @@
 
 /** @} */
 
+/**
+ * @name STM32F4XXXX FLASH
+ * @{
+ */
+
+#include <bsp/stm32f4xxxx_flash.h>
+#define STM32F4_FLASH ((volatile stm32f4_flash *) (STM32F4_BASE + 0x40023C00))
+
+/** @} */
+
 #include <bsp/stm32_i2c.h>
 
 /**
diff --git a/c/src/lib/libbsp/arm/stm32f4/include/stm32f4xxxx_flash.h b/c/src/lib/libbsp/arm/stm32f4/include/stm32f4xxxx_flash.h
new file mode 100644
index 0000000..55d9dc6
--- /dev/null
+++ b/c/src/lib/libbsp/arm/stm32f4/include/stm32f4xxxx_flash.h
@@ -0,0 +1,54 @@
+/**
+ * @file
+ *
+ * @ingroup stm32f4_flash
+ *
+ * @brief STM32F4XXXX FLASH support.
+ *
+ * Contains structure desribing registers responsible for the flash memory
+ * configuration.
+ */
+
+/*
+ * Copyright (c) 2014 Tomasz Gregorek.  All rights reserved.
+ *
+ *  <tomasz.gregorek at gmail.com>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+#ifndef LIBBSP_ARM_STM32F4_STM32F4XXXX_FLASH_H
+#define LIBBSP_ARM_STM32F4_STM32F4XXXX_FLASH_H
+
+#include <bsp/utility.h>
+
+/**
+ * @defgroup stm32f10xxx_flash STM32F4XXXX FLASH Support
+ * @ingroup stm32f4_flash
+ * @brief STM32F4FXXX FLASH Support
+ * @{
+ */
+
+typedef struct {
+  uint32_t acr;
+  uint32_t keyr;
+  uint32_t optkeyr;
+  uint32_t sr;
+  uint32_t cr;
+  uint32_t optcr;
+  uint32_t optcr1;
+} stm32f4_flash;
+
+/** @} */
+
+#define FLASH_ACR_LATENCY( val ) BSP_FLD32( val, 0, 3 )
+#define FLASH_ACR_LATENCY_MSK BSP_MSK32( 0, 3 )
+#define FLASH_ACR_PRFTEN BSP_BIT32( 8 )
+#define FLASH_ACR_ICEN BSP_BIT32( 9 )
+#define FLASH_ACR_DCEN BSP_BIT32( 10 )
+#define FLASH_ACR_ICRST BSP_BIT32( 11 )
+#define FLASH_ACR_DCRST BSP_BIT32( 12 )
+
+#endif /* LIBBSP_ARM_STM32F4_STM32F4XXXX_FLASH_H */
\ No newline at end of file
diff --git a/c/src/lib/libbsp/arm/stm32f4/include/stm32f4xxxx_rcc.h b/c/src/lib/libbsp/arm/stm32f4/include/stm32f4xxxx_rcc.h
index 8126340..311e484 100644
--- a/c/src/lib/libbsp/arm/stm32f4/include/stm32f4xxxx_rcc.h
+++ b/c/src/lib/libbsp/arm/stm32f4/include/stm32f4xxxx_rcc.h
@@ -31,29 +31,135 @@
  */
 
 typedef struct {
-	uint32_t cr;
-	uint32_t pllcfgr;
-	uint32_t cfgr;
-	uint32_t cir;
-	uint32_t ahbrstr [3];
-	uint32_t reserved_1c;
-	uint32_t apbrstr [2];
-	uint32_t reserved_28 [2];
-	uint32_t ahbenr [3];
-	uint32_t reserved_3c;
-	uint32_t apbenr [2];
-	uint32_t reserved_48 [2];
-	uint32_t ahblpenr [3];
-	uint32_t reserved_5c;
-	uint32_t apblpenr [2];
-	uint32_t reserved_68 [2];
-	uint32_t bdcr;
-	uint32_t csr;
-	uint32_t reserved_78 [2];
-	uint32_t sscgr;
-	uint32_t plli2scfgr;
+  uint32_t cr;
+  uint32_t pllcfgr;
+  uint32_t cfgr;
+  uint32_t cir;
+  uint32_t ahbrstr[ 3 ];
+  uint32_t reserved_1c;
+  uint32_t apbrstr[ 2 ];
+  uint32_t reserved_28[ 2 ];
+  uint32_t ahbenr[ 3 ];
+  uint32_t reserved_3c;
+  uint32_t apbenr[ 2 ];
+  uint32_t reserved_48[ 2 ];
+  uint32_t ahblpenr[ 3 ];
+  uint32_t reserved_5c;
+  uint32_t apblpenr[ 2 ];
+  uint32_t reserved_68[ 2 ];
+  uint32_t bdcr;
+  uint32_t csr;
+  uint32_t reserved_78[ 2 ];
+  uint32_t sscgr;
+  uint32_t plli2scfgr;
 } stm32f4_rcc;
 
 /** @} */
 
-#endif /* LIBBSP_ARM_STM32F4_STM32F4XXXX_RCC_H */
+#define RCC_CR_HSION BSP_BIT32( 0 )
+#define RCC_CR_HSIRDY BSP_BIT32( 1 )
+#define RCC_CR_HSITRIM( val ) BSP_FLD32( val, 3, 7 )
+#define RCC_CR_HSITRIM_MSK BSP_MSK32( 3, 7 )
+#define RCC_CR_HSICAL( val ) BSP_FLD32( val, 8, 15 )
+#define RCC_CR_HSICAL_MSK BSP_MSK32( 8, 15 )
+#define RCC_CR_HSEON BSP_BIT32( 16 )
+#define RCC_CR_HSERDY BSP_BIT32( 17 )
+#define RCC_CR_HSEBYP BSP_BIT32( 18 )
+#define RCC_CR_CSSON BSP_BIT32( 19 )
+#define RCC_CR_PLLON BSP_BIT32( 24 )
+#define RCC_CR_PLLRDY BSP_BIT32( 25 )
+#define RCC_CR_PLLI2SON BSP_BIT32( 26 )
+#define RCC_CR_PLLI2SRDY BSP_BIT32( 27 )
+
+#define RCC_PLLCFGR_PLLM( val ) BSP_FLD32( val, 0, 5 )
+#define RCC_PLLCFGR_PLLM_MSK BSP_MSK32( 0, 5 )
+#define RCC_PLLCFGR_PLLN( val ) BSP_FLD32( val, 6, 14 )
+#define RCC_PLLCFGR_PLLN_MSK BSP_MSK32( 6, 14 )
+
+#define RCC_PLLCFGR_PLLP 16
+#define RCC_PLLCFGR_PLLP_MSK BSP_MSK32( 16, 17 )
+#define RCC_PLLCFGR_PLLP_BY_2 0
+#define RCC_PLLCFGR_PLLP_BY_4 BSP_FLD32( 1, 16, 17 )
+#define RCC_PLLCFGR_PLLP_BY_6 BSP_FLD32( 2, 16, 17 )
+#define RCC_PLLCFGR_PLLP_BY_8 BSP_FLD32( 3, 16, 17 )
+
+#define RCC_PLLCFGR_PLLSRC_HSE BSP_BIT32( 22 )
+#define RCC_PLLCFGR_PLLSRC_HSI 0
+
+#define RCC_PLLCFGR_PLLQ( val ) BSP_FLD32( val, 24, 27 )
+#define RCC_PLLCFGR_PLLQ_MSK BSP_MSK32( 24, 27 )
+
+#define RCC_CFGR_SW 0
+#define RCC_CFGR_SW_MSK BSP_MSK32( 0, 1 )
+#define RCC_CFGR_SW_HSI 0
+#define RCC_CFGR_SW_HSE 1
+#define RCC_CFGR_SW_PLL 2
+
+#define RCC_CFGR_SWS 2
+#define RCC_CFGR_SWS_MSK BSP_MSK32( 2, 3 )
+#define RCC_CFGR_SWS_HSI 0
+#define RCC_CFGR_SWS_HSE BSP_FLD32( 1, 2, 3 )
+#define RCC_CFGR_SWS_PLL BSP_FLD32( 2, 2, 3 )
+
+#define RCC_CFGR_HPRE 4
+#define RCC_CFGR_HPRE_BY_1 0
+#define RCC_CFGR_HPRE_BY_2 BSP_FLD32( 8, 4, 7 )
+#define RCC_CFGR_HPRE_BY_4 BSP_FLD32( 9, 4, 7 )
+#define RCC_CFGR_HPRE_BY_8 BSP_FLD32( 10, 4, 7 )
+#define RCC_CFGR_HPRE_BY_16 BSP_FLD32( 11, 4, 7 )
+#define RCC_CFGR_HPRE_BY_64 BSP_FLD32( 12, 4, 7 )
+#define RCC_CFGR_HPRE_BY_128 BSP_FLD32( 13, 4, 7 )
+#define RCC_CFGR_HPRE_BY_256 BSP_FLD32( 14, 4, 7 )
+#define RCC_CFGR_HPRE_BY_512 BSP_FLD32( 15, 4, 7 )
+
+#define RCC_CFGR_PPRE1 10
+#define RCC_CFGR_PPRE1_BY_1 0
+#define RCC_CFGR_PPRE1_BY_2 BSP_FLD32( 4, 10, 12 )
+#define RCC_CFGR_PPRE1_BY_4 BSP_FLD32( 5, 10, 12 )
+#define RCC_CFGR_PPRE1_BY_8 BSP_FLD32( 6, 10, 12 )
+#define RCC_CFGR_PPRE1_BY_16 BSP_FLD32( 7, 10, 12 )
+
+#define RCC_CFGR_PPRE2 13
+#define RCC_CFGR_PPRE2 BSP_MSK32( 13, 15 )
+#define RCC_CFGR_PPRE2_BY_1 0
+#define RCC_CFGR_PPRE2_BY_2 BSP_FLD32( 4, 13, 15 )
+#define RCC_CFGR_PPRE2_BY_4 BSP_FLD32( 5, 13, 15 )
+#define RCC_CFGR_PPRE2_BY_8 BSP_FLD32( 6, 13, 15 )
+#define RCC_CFGR_PPRE2_BY_16 BSP_FLD32( 7, 13, 15 )
+
+#define RCC_CFGR_RTCPRE( val ) BSP_FLD32( val, 16, 20 )
+#define RCC_CFGR_RTCPRE_MSK BSP_MSK32( 16, 20 )
+
+#define RCC_CFGR_MCO1 21
+#define RCC_CFGR_MCO1_MSK BSP_MSK32( 21, 22 )
+#define RCC_CFGR_MCO1_HSI 0
+#define RCC_CFGR_MCO1_LSE BSP_FLD32( 1, 21, 22 )
+#define RCC_CFGR_MCO1_HSE BSP_FLD32( 2, 21, 22 )
+#define RCC_CFGR_MCO1_PLL BSP_FLD32( 3, 21, 22 )
+
+#define RCC_CFGR_I2SSRC BSP_BIT32( 23 )
+
+#define RCC_CFGR_MCO1PRE 24
+#define RCC_CFGR_MCO1PRE_MSK BSP_MSK32( 24, 26 )
+#define RCC_CFGR_MCO1PRE_BY_1 0
+#define RCC_CFGR_MCO1PRE_BY_2 BSP_FLD32( 4, 24, 26 )
+#define RCC_CFGR_MCO1PRE_BY_3 BSP_FLD32( 5, 24, 26 )
+#define RCC_CFGR_MCO1PRE_BY_4 BSP_FLD32( 6, 24, 26 )
+#define RCC_CFGR_MCO1PRE_BY_5 BSP_FLD32( 7, 24, 26 )
+
+#define RCC_CFGR_MCO2PRE 27
+#define RCC_CFGR_MCO2PRE_MSK BSP_MSK32( 27, 29 )
+#define RCC_CFGR_MCO2PRE_BY_1 0
+#define RCC_CFGR_MCO2PRE_BY_2 BSP_FLD32( 4, 27, 29 )
+#define RCC_CFGR_MCO2PRE_BY_3 BSP_FLD32( 5, 27, 29 )
+#define RCC_CFGR_MCO2PRE_BY_4 BSP_FLD32( 6, 27, 29 )
+#define RCC_CFGR_MCO2PRE_BY_5 BSP_FLD32( 7, 27, 29 )
+
+#define RCC_CFGR_MCO2 30
+#define RCC_CFGR_MCO2_MSK BSP_MSK32( 30, 31 )
+#define RCC_CFGR_MCO2_SYSCLK 0
+#define RCC_CFGR_MCO2_PLLI2S BSP_FLD32( 1, 30, 31 )
+#define RCC_CFGR_MCO2_HSE BSP_FLD32( 2, 30, 31 )
+#define RCC_CFGR_MCO2_PLL BSP_FLD32( 3, 30, 31 )
+
+#endif /* LIBBSP_ARM_STM32F4_STM32F4XXXX_RCC_H */
\ No newline at end of file
diff --git a/c/src/lib/libbsp/arm/stm32f4/preinstall.am b/c/src/lib/libbsp/arm/stm32f4/preinstall.am
index fd1604d..fe9a3b0 100644
--- a/c/src/lib/libbsp/arm/stm32f4/preinstall.am
+++ b/c/src/lib/libbsp/arm/stm32f4/preinstall.am
@@ -121,6 +121,10 @@ $(PROJECT_INCLUDE)/bsp/stm32f4xxxx_rcc.h: include/stm32f4xxxx_rcc.h $(PROJECT_IN
 	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/stm32f4xxxx_rcc.h
 PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/stm32f4xxxx_rcc.h
 
+$(PROJECT_INCLUDE)/bsp/stm32f4xxxx_flash.h: include/stm32f4xxxx_flash.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
+	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/stm32f4xxxx_flash.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/stm32f4xxxx_flash.h
+
 $(PROJECT_INCLUDE)/bsp/stm32_i2c.h: include/stm32_i2c.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
 	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/stm32_i2c.h
 PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/stm32_i2c.h
diff --git a/c/src/lib/libbsp/arm/stm32f4/startup/bspstart.c b/c/src/lib/libbsp/arm/stm32f4/startup/bspstart.c
index d337d3a..0d08458 100644
--- a/c/src/lib/libbsp/arm/stm32f4/startup/bspstart.c
+++ b/c/src/lib/libbsp/arm/stm32f4/startup/bspstart.c
@@ -17,10 +17,286 @@
 #include <bsp/irq.h>
 #include <bsp/bootcard.h>
 #include <bsp/irq-generic.h>
+#include <assert.h>
+#include <bsp/stm32f4.h>
 
-void bsp_start(void)
+#ifdef STM32F4_FAMILY_F4XXXX
+
+#include <bsp/stm32f4xxxx_rcc.h>
+#include <bsp/stm32f4xxxx_flash.h>
+
+static rtems_status_code set_system_clk(
+  uint32_t sys_clk,
+  uint32_t hse_clk,
+  uint32_t hse_flag
+);
+
+static void init_main_osc( void )
+{
+  volatile stm32f4_rcc *rcc = STM32F4_RCC;
+  rtems_status_code     status;
+
+  /* Revert to reset values */
+  rcc->cr |= RCC_CR_HSION;   /* turn on HSI */
+
+  while ( !( rcc->cr & RCC_CR_HSIRDY ) ) ;
+
+  rcc->cfgr &= 0x00000300; /* all prescalers to 0, clock source to HSI */
+
+  rcc->cr &= 0xF0F0FFFD;   /* turn off all clocks and PLL except HSI */
+
+  status = set_system_clk( STM32F4_SYSCLK / 1000000L,
+    STM32F4_HSE_OSCILLATOR / 1000000L,
+    1 );
+
+  assert( rtems_is_status_successful( status ) );
+}
+
+/**
+ * @brief Sets up clocks configuration.
+ *
+ * Set up clocks configuration to achieve desired system clock
+ * as close as possible with simple math.
+ *
+ * Limitations:
+ * It is assumed that 1MHz resolution is enough.
+ * Best fits for the clocks are achieved with multiplies of 42MHz.
+ * Even though APB1, APB2 and AHB are calculated user is still required
+ * to provide correct values for the bsp configuration for the:
+ * STM32F4_PCLK1
+ * STM32F4_PCLK2
+ * STM32F4_HCLK
+ * as those are used for the peripheral clocking calculations.
+ *
+ * @param sys_clk Desired system clock in MHz.
+ * @param hse_clk External clock speed in MHz.
+ * @param hse_flag Flag determining which clock source to use, 1 for HSE,
+ *                 0 for HSI.
+ *
+ * @retval RTEMS_SUCCESSFUL Configuration has been succesfully aplied for the
+ *                          requested clock speed.
+ * @retval RTEMS_TIMEOUT HSE clock didn't start or PLL didn't lock.
+ * @retval RTEMS_INVALID_NUMBER Requested clock speed is out of range.
+ */
+static rtems_status_code set_system_clk(
+  uint32_t sys_clk,
+  uint32_t hse_clk,
+  uint32_t hse_flag
+)
+{
+  volatile stm32f4_rcc   *rcc = STM32F4_RCC;
+  volatile stm32f4_flash *flash = STM32F4_FLASH;
+  long                    timeout = 0;
+
+  int src_clk = 0;
+
+  uint32_t pll_m = 0;
+  uint32_t pll_n = 0;
+  uint32_t pll_p = 0;
+  uint32_t pll_q = 0;
+
+  uint32_t ahbpre = 0;
+  uint32_t apbpre1 = 0;
+  uint32_t apbpre2 = 0;
+
+  if ( sys_clk == 16 && hse_clk != 16 ) {
+    /* Revert to reset values */
+    rcc->cr |= RCC_CR_HSION;   /* turn on HSI */
+
+    while ( !( rcc->cr & RCC_CR_HSIRDY ) ) ;
+
+    /* all prescalers to 0, clock source to HSI */
+    rcc->cfgr &= 0x00000300 | RCC_CFGR_SW_HSI;
+    rcc->cr &= 0xF0F0FFFD;   /* turn off all clocks and PLL except HSI */
+    flash->acr = 0; /* slow clock so no cache, no prefetch, no latency */
+
+    return RTEMS_SUCCESSFUL;
+  }
+
+  if ( sys_clk == hse_clk ) {
+    /* Revert to reset values */
+    rcc->cr |= RCC_CR_HSEON;   /* turn on HSE */
+    timeout = 400;
+
+    while ( !( rcc->cr & RCC_CR_HSERDY ) && --timeout ) ;
+
+    assert( timeout != 0 );
+
+    if ( timeout == 0 ) {
+      return RTEMS_TIMEOUT;
+    }
+
+    /* all prescalers to 0, clock source to HSE */
+    rcc->cfgr &= 0x00000300;
+    rcc->cfgr |= RCC_CFGR_SW_HSE;
+    /* turn off all clocks and PLL except HSE */
+    rcc->cr &= 0xF0F0FFFC | RCC_CR_HSEON;
+    flash->acr = 0; /* slow clock so no cache, no prefetch, no latency */
+
+    return RTEMS_SUCCESSFUL;
+  }
+
+  /*
+   * Lets use 1MHz input for PLL so we get higher VCO output
+   * this way we get better value for the PLL_Q divader for the USB
+   *
+   * Though you might want to use 2MHz as per CPU specification:
+   *
+   * Caution:The software has to set these bits correctly to ensure
+   * that the VCO input frequency ranges from 1 to 2 MHz.
+   * It is recommended to select a frequency of 2 MHz to limit PLL jitter.
+   */
+
+  if ( sys_clk > 180 ) {
+    return RTEMS_INVALID_NUMBER;
+  } else if ( sys_clk >= 96 ) {
+    pll_n = sys_clk << 1;
+    pll_p = RCC_PLLCFGR_PLLP_BY_2;
+  } else if ( sys_clk >= 48 ) {
+    pll_n = sys_clk << 2;
+    pll_p = RCC_PLLCFGR_PLLP_BY_4;
+  } else if ( sys_clk >= 24 ) {
+    pll_n = sys_clk << 3;
+    pll_p = RCC_PLLCFGR_PLLP_BY_8;
+  } else {
+    return RTEMS_INVALID_NUMBER;
+  }
+
+  if ( hse_clk == 0 || hse_flag == 0 ) {
+    src_clk = 16;
+    hse_flag = 0;
+  } else {
+    src_clk = hse_clk;
+  }
+
+  pll_m = src_clk; /* divide by the oscilator speed in MHz */
+
+  /* pll_q is a prescaler from VCO for the USB OTG FS, SDIO and RNG,
+   * best if results in the 48MHz for the USB
+   */
+  pll_q = ( (long) ( src_clk * pll_n + src_clk * pll_n / 2 ) ) / pll_m / 48;
+
+  if ( pll_q < 2 ) {
+    pll_q = 2;
+  }
+
+  /* APB1 prescaler, APB1 clock must be < 42MHz */
+  apbpre1 = ( sys_clk * 100 ) / 42;
+
+  if ( apbpre1 <= 100 ) {
+    apbpre1 = RCC_CFGR_PPRE1_BY_1;
+  } else if ( apbpre1 <= 200 ) {
+    apbpre1 = RCC_CFGR_PPRE1_BY_2;
+  } else if ( apbpre1 <= 400 ) {
+    apbpre1 = RCC_CFGR_PPRE1_BY_4;
+  } else if ( apbpre1 <= 800 ) {
+    apbpre1 = RCC_CFGR_PPRE1_BY_8;
+  } else if ( apbpre1 ) {
+    apbpre1 = RCC_CFGR_PPRE1_BY_16;
+  }
+
+  /* APB2 prescaler, APB2 clock must be < 84MHz */
+  apbpre2 = ( sys_clk * 100 ) / 84;
+
+  if ( apbpre2 <= 100 ) {
+    apbpre2 = RCC_CFGR_PPRE2_BY_1;
+  } else if ( apbpre2 <= 200 ) {
+    apbpre2 = RCC_CFGR_PPRE2_BY_2;
+  } else if ( apbpre2 <= 400 ) {
+    apbpre2 = RCC_CFGR_PPRE2_BY_4;
+  } else if ( apbpre2 <= 800 ) {
+    apbpre2 = RCC_CFGR_PPRE2_BY_8;
+  } else {
+    apbpre2 = RCC_CFGR_PPRE2_BY_16;
+  }
+
+  rcc->cr |= RCC_CR_HSION;   /* turn on HSI */
+
+  while ( ( !( rcc->cr & RCC_CR_HSIRDY ) ) ) ;
+
+  /* all prescalers to 0, clock source to HSI */
+  rcc->cfgr &= 0x00000300;
+  rcc->cfgr |= RCC_CFGR_SW_HSI;
+
+  while ( ( ( rcc->cfgr & RCC_CFGR_SWS_MSK ) != RCC_CFGR_SWS_HSI ) ) ;
+
+  /* turn off PLL */
+  rcc->cr &= ~( RCC_CR_PLLON | RCC_CR_PLLRDY );
+
+  /* turn on HSE */
+  if ( hse_flag ) {
+    rcc->cr |= RCC_CR_HSEON;
+    timeout = 400;
+
+    while ( ( !( rcc->cr & RCC_CR_HSERDY ) ) && timeout-- ) ;
+
+    assert( timeout != 0 );
+
+    if ( timeout == 0 ) {
+      return RTEMS_TIMEOUT;
+    }
+  }
+
+  rcc->pllcfgr &= 0xF0BC8000; /* clear PLL prescalers */
+
+  /* set pll parameters */
+  rcc->pllcfgr |= RCC_PLLCFGR_PLLM( pll_m ) | /* input divider */
+                  RCC_PLLCFGR_PLLN( pll_n ) | /* multiplier */
+                  pll_p |                     /* output divider from table */
+                                              /* HSE v HSI */
+                  ( hse_flag ? RCC_PLLCFGR_PLLSRC_HSE : RCC_PLLCFGR_PLLSRC_HSI )
+                  |
+                  RCC_PLLCFGR_PLLQ( pll_q );    /* PLLQ divider */
+
+  /* set prescalers for the internal busses */
+  rcc->cfgr |= apbpre1 |
+               apbpre2 |
+               ahbpre;
+
+  /*
+   * Set flash parameters, hard coded for now for fast system clocks.
+   * TODO implement some math to use flash on as low latancy as possible
+   */
+  flash->acr = FLASH_ACR_LATENCY( 5 ) | /* latency */
+               FLASH_ACR_ICEN |       /* instruction cache */
+               FLASH_ACR_DCEN;        /* data cache */
+
+  /* turn on PLL */
+  rcc->cr |= RCC_CR_PLLON;
+  timeout = 40000;
+
+  while ( ( !( rcc->cr & RCC_CR_PLLRDY ) ) && --timeout ) ;
+  
+  assert( timeout != 0 );
+
+  if ( timeout == 0 ) {
+    return RTEMS_TIMEOUT;
+  }
+
+  /* clock source to PLL */
+  rcc->cfgr = ( rcc->cfgr & ~RCC_CFGR_SW_MSK ) | RCC_CFGR_SW_PLL;
+
+  while ( ( ( rcc->cfgr & RCC_CFGR_SWS_MSK ) != RCC_CFGR_SWS_PLL ) ) ;
+
+  return RTEMS_SUCCESSFUL;
+}
+
+#endif /* STM32F4_FAMILY_F4XXXX */
+
+#ifdef STM32F4_FAMILY_F10XXX
+
+static void init_main_osc( void )
+{
+
+}
+
+#endif /* STM32F4_FAMILY_F10XXX */
+
+void bsp_start( void )
 {
-  stm32f4_gpio_set_config_array(&stm32f4_start_config_gpio [0]);
+  init_main_osc();
+
+  stm32f4_gpio_set_config_array( &stm32f4_start_config_gpio[ 0 ] );
 
   bsp_interrupt_initialize();
 }
-- 
2.1.0



More information about the devel mailing list