sorry, ignore this one.
2014-09-20 20:15 GMT+02:00 <tomasz.grego...@gmail.com>: > From: Tomasz Gregorek <tomasz.grego...@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 slow down Flash memory for the high speeds. > --- > c/src/lib/libbsp/arm/stm32f4/include/stm32f4.h | 10 + > .../libbsp/arm/stm32f4/include/stm32f4xxxx_flash.h | 45 +++++ > .../libbsp/arm/stm32f4/include/stm32f4xxxx_rcc.h | 94 +++++++++ > c/src/lib/libbsp/arm/stm32f4/startup/bspstart.c | 211 > +++++++++++++++++++++ > 4 files changed, 360 insertions(+) > create mode 100644 > c/src/lib/libbsp/arm/stm32f4/include/stm32f4xxxx_flash.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..ed08d76 > --- /dev/null > +++ b/c/src/lib/libbsp/arm/stm32f4/include/stm32f4xxxx_flash.h > @@ -0,0 +1,45 @@ > +/** > + * @file > + * @ingroup stm32f4_flash > + * @brief STM32F4XXXX FLASH support. > + */ > + > +/* > + * Copyright (c) 2012 Sebastian Huber. All rights reserved. > + * > + * embedded brains GmbH > + * Obere Lagerstr. 30 > + * 82178 Puchheim > + * Germany > + * <rt...@embedded-brains.de> > + * > + * 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; > + > +/** @} */ > + > +#endif /* LIBBSP_ARM_STM32F4_STM32F4XXXX_FLASH_H */ > 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..ce85b8e 100644 > --- a/c/src/lib/libbsp/arm/stm32f4/include/stm32f4xxxx_rcc.h > +++ b/c/src/lib/libbsp/arm/stm32f4/include/stm32f4xxxx_rcc.h > @@ -56,4 +56,98 @@ typedef struct { > > /** @} */ > > +#define RCC_CR_HSION BSP_BIT32(0) > +#define RCC_CR_HSIRDY BSP_BIT32(1) > +#define RCC_CR_HSITRIM 3 > +#define RCC_CR_HSICAL 8 > +#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 0 > +#define RCC_PLLCFGR_PLLN 6 > +#define RCC_PLLCFGR_PLLP 16 > + > +#define RCC_PLLCFGR_PLLSRC_HSE BSP_BIT32(22) > +#define RCC_PLLCFGR_PLLSRC_HSI 0 > + > +#define RCC_PLLCFGR_PLLQ 24 > + > + > +#define RCC_CFGR_SW 0 > +#define RCC_CFGR_SW_MASK 3 > +#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_MASK (3 << RCC_CFGR_SWS) > + > +#define RCC_CFGR_SWS_HSI 0 > +#define RCC_CFGR_SWS_HSE (1 << RCC_CFGR_SWS) > +#define RCC_CFGR_SWS_PLL (2 << RCC_CFGR_SWS) > + > +#define RCC_CFGR_HPRE 4 > +#define RCC_CFGR_HPRE_BY_1 0 > +#define RCC_CFGR_HPRE_BY_2 ( 8 << RCC_CFGR_HPRE) > +#define RCC_CFGR_HPRE_BY_4 ( 9 << RCC_CFGR_HPRE) > +#define RCC_CFGR_HPRE_BY_8 (10 << RCC_CFGR_HPRE) > +#define RCC_CFGR_HPRE_BY_16 (11 << RCC_CFGR_HPRE) > +#define RCC_CFGR_HPRE_BY_64 (12 << RCC_CFGR_HPRE) > +#define RCC_CFGR_HPRE_BY_128 (13 << RCC_CFGR_HPRE) > +#define RCC_CFGR_HPRE_BY_256 (14 << RCC_CFGR_HPRE) > +#define RCC_CFGR_HPRE_BY_512 (15 << RCC_CFGR_HPRE) > + > +#define RCC_CFGR_PPRE1 10 > +#define RCC_CFGR_PPRE1_BY_1 0 > +#define RCC_CFGR_PPRE1_BY_2 (4 << RCC_CFGR_PPRE1) > +#define RCC_CFGR_PPRE1_BY_4 (5 << RCC_CFGR_PPRE1) > +#define RCC_CFGR_PPRE1_BY_8 (6 << RCC_CFGR_PPRE1) > +#define RCC_CFGR_PPRE1_BY_16 (7 << RCC_CFGR_PPRE1) > + > +#define RCC_CFGR_PPRE2 13 > +#define RCC_CFGR_PPRE2_BY_1 0 > +#define RCC_CFGR_PPRE2_BY_2 (4 << RCC_CFGR_PPRE2) > +#define RCC_CFGR_PPRE2_BY_4 (5 << RCC_CFGR_PPRE2) > +#define RCC_CFGR_PPRE2_BY_8 (6 << RCC_CFGR_PPRE2) > +#define RCC_CFGR_PPRE2_BY_16 (7 << RCC_CFGR_PPRE2) > + > +#define RCC_CFGR_RTCPRE 16 > +#define RCC_CFGR_RTCPRE_SET(a) (a << RCC_CFGR_RTCPRE) > + > +#define RCC_CFGR_MCO1 21 > +#define RCC_CFGR_MCO1_HSI 0 > +#define RCC_CFGR_MCO1_LSE (1 << RCC_CFGR_MCO1) > +#define RCC_CFGR_MCO1_HSE (2 << RCC_CFGR_MCO1) > +#define RCC_CFGR_MCO1_PLL (3 << RCC_CFGR_MCO1) > + > +#define RCC_CFGR_I2SSRC BSP_BIT32(23) > + > +#define RCC_CFGR_MCO1PRE 24 > +#define RCC_CFGR_MCO1PRE_BY_1 0 > +#define RCC_CFGR_MCO1PRE_BY_2 (4 << RCC_CFGR_MCO1PRE) > +#define RCC_CFGR_MCO1PRE_BY_3 (5 << RCC_CFGR_MCO1PRE) > +#define RCC_CFGR_MCO1PRE_BY_4 (6 << RCC_CFGR_MCO1PRE) > +#define RCC_CFGR_MCO1PRE_BY_5 (7 << RCC_CFGR_MCO1PRE) > + > +#define RCC_CFGR_MCO2PRE 27 > +#define RCC_CFGR_MCO2PRE_BY_1 0 > +#define RCC_CFGR_MCO2PRE_BY_2 (4 << RCC_CFGR_MCO2PRE) > +#define RCC_CFGR_MCO2PRE_BY_3 (5 << RCC_CFGR_MCO2PRE) > +#define RCC_CFGR_MCO2PRE_BY_4 (6 << RCC_CFGR_MCO2PRE) > +#define RCC_CFGR_MCO2PRE_BY_5 (7 << RCC_CFGR_MCO2PRE) > + > +#define RCC_CFGR_MCO2 30 > +#define RCC_CFGR_MCO2_SYSCLK 0 > +#define RCC_CFGR_MCO2_PLLI2S (1 << RCC_CFGR_MCO2) > +#define RCC_CFGR_MCO2_HSE (2 << RCC_CFGR_MCO2) > +#define RCC_CFGR_MCO2_PLL (3 << RCC_CFGR_MCO2) > + > + > #endif /* LIBBSP_ARM_STM32F4_STM32F4XXXX_RCC_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..31823d1 100644 > --- a/c/src/lib/libbsp/arm/stm32f4/startup/bspstart.c > +++ b/c/src/lib/libbsp/arm/stm32f4/startup/bspstart.c > @@ -17,9 +17,220 @@ > #include <bsp/irq.h> > #include <bsp/bootcard.h> > #include <bsp/irq-generic.h> > +#include <bsp/stm32f4.h> > +#include <bsp/stm32f4xxxx_rcc.h> > +#include <bsp/stm32f4xxxx_flash.h> > + > +static rtems_status_code set_system_clk(uint32_t sysclk, uint32_t hseclk, > uint32_t hseflag); > + > +static void init_main_osc(void) > +{ > + volatile stm32f4_rcc *rcc = STM32F4_RCC; > + > + /* 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 */ > + > + set_system_clk(STM32F4_SYSCLK / 1000000L, STM32F4_HSE_OSCILLATOR / > 1000000L, 1); > +} > + > + > +/* > + * Sets up clocks configuration to achieve desired system clock > + * as close as possible with simple math > + */ > +static rtems_status_code set_system_clk(uint32_t sysclk, uint32_t hseclk, > uint32_t hseflag) > +{ > + volatile stm32f4_rcc *rcc = STM32F4_RCC; > + volatile stm32f4_flash *flash = STM32F4_FLASH; > + rtems_interrupt_level level; > + long timeout = 0; > + const long timeoutset = 10000000L; > + > + int srcclk = 0; > + > + int pll_m = 0; > + int pll_n = 0; > + int pll_p = 0; > + int pll_q = 0; > + //int cr; > + int ahbpre = 0; > + int apbpre1 = 0; > + int apbpre2 = 0; > + > + if (sysclk == 16) { > + /* Revert to reset values */ > + rcc->cr |= 0x00000001; /* turn on HSI */ > + while (! (rcc->cr & (1 << 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 */ > + > + flash->acr = 0; /* slow clock so no cache, no prefetch, no latency */ > + > + return RTEMS_SUCCESSFUL; > + } > + > + if (hseclk == 0 || hseflag == 0) { > + srcclk = 16; > + hseflag = 0; > + } > + else { > + srcclk = hseclk; > + } > + > + if (sysclk > 180) { > + return RTEMS_INVALID_NUMBER; > + } > + else if (sysclk > 96) { > + pll_n = sysclk; /* multpily by the desired speed in MHz */ > + pll_p = 0; /* divide by 2 */ > + } > + else if (sysclk > 48) { > + pll_n = sysclk >> 1; /* multpily by 2x the desired speed in MHz */ > + pll_p = 1; /* divide by 4 */ > + } > + else if (sysclk > 24) { > + pll_n = sysclk >> 2; /* multpily by 4x the desired speed in MHz */ > + pll_p = 3; /* divide by 8 */ > + } > + else { > + return RTEMS_INVALID_NUMBER; > + } > + > + /* > + * 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. > + */ > + pll_m = srcclk; /* divide by the oscilator speed in MHz */ > + pll_n <<= 1; /* multiply by requested clock x2 */ > + > + /* pll_q is a prescaler from VCO for the USB OTG FS, SDIO and RNG, > + * should result in the 48MHz for the USB > + */ > + pll_q = ((long)(srcclk * pll_n + srcclk * pll_n / 2)) / pll_m / 48; > + > + if (pll_q < 2) > + { > + pll_q = 2; > + } > + > + /* APB1 prescaler, APB1 clock must be < 42MHz */ > + apbpre1 = (sysclk * 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 = (sysclk * 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; > + } > + > + rtems_interrupt_disable(level); > + > + rcc->cr |= RCC_CR_HSION; /* turn on HSI */ > + timeout = timeoutset; > + while ((! (rcc->cr & RCC_CR_HSIRDY) ) && timeout--); > + > + if (timeout == 0) while(1); > + > + /* all prescalers to 0, clock source to HSI */ > + rcc->cfgr &= 0x00000300; > + rcc->cfgr |= RCC_CFGR_SW_HSI; > + > + timeout = timeoutset; > + while ( ( (rcc->cfgr & RCC_CFGR_SWS_MASK) != RCC_CFGR_SWS_HSI ) && > --timeout ); > + > + if (timeout == 0) while(1); > + > + /* turn off PLL */ > + rcc->cr &= ~ (RCC_CR_PLLON | RCC_CR_PLLRDY); > + > + if (hseflag) { > + rcc->cr |= RCC_CR_HSEON; > + timeout = timeoutset; > + while ((! (rcc->cr & RCC_CR_HSERDY) ) && timeout--); > + } > + > + rcc->pllcfgr &= 0xF0BC8000; /* clear PLL prescalers */ > + > + /* set pll parameters */ > + rcc->pllcfgr |=(pll_m << RCC_PLLCFGR_PLLM) // input divider > + | (pll_n << RCC_PLLCFGR_PLLN) // multiplier > + | (pll_p << RCC_PLLCFGR_PLLP) // output divider from table > + // HSE v HSI > + | (hseflag ? RCC_PLLCFGR_PLLSRC_HSE : > RCC_PLLCFGR_PLLSRC_HSI) > + | (pll_q << RCC_PLLCFGR_PLLQ); // PLLQ > + > + /* set prescalers for the internal busses */ > + rcc->cfgr |= apbpre1 > + | apbpre2 > + | ahbpre; > + > + /* set flash parameters, hard coded for now for fast system clocks */ > + flash->acr |= 5 // latency > + | (1 << 9) // instruction cache > + | (1 << 10);// data cache > + > + /* turn on PLL */ > + rcc->cr |= RCC_CR_PLLON; > + timeout = timeoutset; > + while ( (! (rcc->cr & RCC_CR_PLLRDY) ) && --timeout ); > + > + if (timeout == 0) while(1); > + > + /* clock source to PLL */ > + rcc->cfgr = (rcc->cfgr & ~RCC_CFGR_SW_MASK) | RCC_CFGR_SW_PLL; > + timeout = timeoutset; > + while ( ((rcc->cfgr & RCC_CFGR_SWS_MASK) != RCC_CFGR_SWS_PLL) && > --timeout ); > + //if (timeout == 0) while(1); > + > + rtems_interrupt_enable(level); > + > + return RTEMS_SUCCESSFUL; > +} > + > > void bsp_start(void) > { > + init_main_osc(); > + > stm32f4_gpio_set_config_array(&stm32f4_start_config_gpio [0]); > > bsp_interrupt_initialize(); > -- > 2.1.0 > >
_______________________________________________ devel mailing list devel@rtems.org http://lists.rtems.org/mailman/listinfo/devel