From 50f291725e77a72e120af2e6136e8c1092b4aaaa Mon Sep 17 00:00:00 2001 From: arighi Date: Tue, 4 May 2010 08:55:10 +0000 Subject: [PATCH] STM32: add clocking driver. git-svn-id: https://src.develer.com/svnoss/bertos/trunk@3605 38d2e660-2303-0410-9eaa-f027e97ec537 --- bertos/cpu/cortex-m3/drv/clock_stm32.c | 134 ++++++++++++++ bertos/cpu/cortex-m3/drv/clock_stm32.h | 237 +++++++++++++++++++++++++ 2 files changed, 371 insertions(+) create mode 100644 bertos/cpu/cortex-m3/drv/clock_stm32.c create mode 100644 bertos/cpu/cortex-m3/drv/clock_stm32.h diff --git a/bertos/cpu/cortex-m3/drv/clock_stm32.c b/bertos/cpu/cortex-m3/drv/clock_stm32.c new file mode 100644 index 00000000..20959595 --- /dev/null +++ b/bertos/cpu/cortex-m3/drv/clock_stm32.c @@ -0,0 +1,134 @@ +/** + * \file + * + * + * \brief STM32 Clocking driver. + * + * \author Andrea Righi + */ + +#include +#include +#include +#include "clock_stm32.h" + +struct RCC *RCC; + +INLINE int rcc_get_flag_status(uint32_t flag) +{ + uint32_t id; + reg32_t reg; + + /* Get the RCC register index */ + id = flag >> 5; + /* The flag to check is in CR register */ + if (id == 1) + reg = RCC->CR; + /* The flag to check is in BDCR register */ + else if (id == 2) + reg = RCC->BDCR; + /* The flag to check is in CSR register */ + else + reg = RCC->CSR; + /* Get the flag position */ + id = flag & FLAG_MASK; + + return reg & (1 << id); +} + +INLINE uint16_t pll_clock(void) +{ + int div, mul; + + /* Hopefully this is evaluate at compile time... */ + for (div = 2; div; div--) + for (mul = 2; mul <= 16; mul++) + if (CPU_FREQ >= (PLL_VCO / div * mul)) + break; + return mul << 8 | div; +} + +INLINE void rcc_pll_config(void) +{ + reg32_t reg = RCC->CFGR & CFGR_PLL_MASK; + + /* Evaluate clock parameters */ + uint16_t clock = pll_clock(); + uint32_t pll_mul = ((clock >> 8) - 2) << 18; + uint32_t pll_div = ((clock & 0xff) << 1 | 1) << 16; + + /* Set the PLL configuration bits */ + reg |= pll_div | pll_mul; + + /* Store the new value */ + RCC->CFGR = reg; + + /* Enable PLL */ + *CR_PLLON_BB = 1; +} + +INLINE void rcc_set_clock_source(uint32_t source) +{ + reg32_t reg; + + reg = RCC->CFGR & CFGR_SW_MASK; + reg |= source; + RCC->CFGR = reg; +} + +void clock_init(void) +{ + /* Initialize global RCC structure */ + RCC = (struct RCC *)RCC_BASE; + + /* Enable the internal oscillator */ + *CR_HSION_BB = 1; + while (!rcc_get_flag_status(RCC_FLAG_HSIRDY)); + + /* Clock the system from internal HSI RC (8 MHz) */ + rcc_set_clock_source(RCC_SYSCLK_HSI); + + /* Enable external oscillator */ + RCC->CR &= CR_HSEON_RESET; + RCC->CR &= CR_HSEBYP_RESET; + RCC->CR |= CR_HSEON_SET; + while (!rcc_get_flag_status(RCC_FLAG_HSERDY)); + + /* Initialize PLL according to CPU_FREQ */ + rcc_pll_config(); + while(!rcc_get_flag_status(RCC_FLAG_PLLRDY)); + + /* Set 1 wait state for the flash memory */ + *(reg32_t *)0x40022000 = 0x12; + + /* Clock the system from the PLL */ + rcc_set_clock_source(RCC_SYSCLK_PLLCLK); +} diff --git a/bertos/cpu/cortex-m3/drv/clock_stm32.h b/bertos/cpu/cortex-m3/drv/clock_stm32.h new file mode 100644 index 00000000..c675a5f8 --- /dev/null +++ b/bertos/cpu/cortex-m3/drv/clock_stm32.h @@ -0,0 +1,237 @@ +/** + * \file + * + * + * \brief Low-level clocking driver for Cortex-M3 STM32. + * + * \author Andrea Righi + */ + +#ifndef CLOCK_STM32_H +#define CLOCK_STM32_H + +/* RCC registers bit address */ +#define RCC_OFFSET (RCC_BASE - PERIPH_BASE) + +/** + * CR Register + */ +/*\{*/ +/* Alias word address of HSION bit */ +#define CR_OFFSET (RCC_OFFSET + 0x00) +#define HSION_BITNUMBER 0x00 +#define CR_HSION_BB ((reg32_t *)(PERIPH_BB_BASE + (CR_OFFSET * 32) + (HSION_BITNUMBER * 4))) + +/* Alias word address of PLLON bit */ +#define PLLON_BITNUMBER 0x18 +#define CR_PLLON_BB ((reg32_t *)(PERIPH_BB_BASE + (CR_OFFSET * 32) + (PLLON_BITNUMBER * 4))) + +/* Alias word address of CSSON bit */ +#define CSSON_BITNUMBER 0x13 +#define CR_CSSON_BB ((reg32_t *)(PERIPH_BB_BASE + (CR_OFFSET * 32) + (CSSON_BITNUMBER * 4))) +/*\}*/ + +/** + * CFGR Register + */ +/*\{*/ +/* Alias word address of USBPRE bit */ +#define CFGR_OFFSET (RCC_OFFSET + 0x04) +#define USBPRE_BITNUMBER 0x16 +#define CFGR_USBPRE_BB ((reg32_t *)(PERIPH_BB_BASE + (CFGR_OFFSET * 32) + (USBPRE_BITNUMBER * 4))) +/*\}*/ + +/** + * BDCR Register + */ +/*\{*/ +/* Alias word address of RTCEN bit */ +#define BDCR_OFFSET (RCC_OFFSET + 0x20) +#define RTCEN_BITNUMBER 0x0F +#define BDCR_RTCEN_BB ((reg32_t *)(PERIPH_BB_BASE + (BDCR_OFFSET * 32) + (RTCEN_BITNUMBER * 4))) + +/* Alias word address of BDRST bit */ +#define BDRST_BITNUMBER 0x10 +#define BDCR_BDRST_BB ((reg32_t *)(PERIPH_BB_BASE + (BDCR_OFFSET * 32) + (BDRST_BITNUMBER * 4))) +/*\}*/ + +/** + * CSR Register + */ +/*\{*/ +/* Alias word address of LSION bit */ +#define CSR_OFFSET (RCC_OFFSET + 0x24) +#define LSION_BITNUMBER 0x00 +#define CSR_LSION_BB ((reg32_t *)(PERIPH_BB_BASE + (CSR_OFFSET * 32) + (LSION_BITNUMBER * 4))) +/*\}*/ + +/** + * RCC registers bit mask + */ +/*\{*/ +/* CR register bit mask */ +#define CR_HSEBYP_RESET (0xFFFBFFFF) +#define CR_HSEBYP_SET (0x00040000) +#define CR_HSEON_RESET (0xFFFEFFFF) +#define CR_HSEON_SET (0x00010000) +#define CR_HSITRIM_MASK (0xFFFFFF07) + +/* CFGR register bit mask */ +#define CFGR_PLL_MASK (0xFFC0FFFF) +#define CFGR_PLLMull_MASK (0x003C0000) +#define CFGR_PLLSRC_MASK (0x00010000) +#define CFGR_PLLXTPRE_MASK (0x00020000) +#define CFGR_SWS_MASK (0x0000000C) +#define CFGR_SW_MASK (0xFFFFFFFC) +#define CFGR_HPRE_RESET_MASK (0xFFFFFF0F) +#define CFGR_HPRE_SET_MASK (0x000000F0) +#define CFGR_PPRE1_RESET_MASK (0xFFFFF8FF) +#define CFGR_PPRE1_SET_MASK (0x00000700) +#define CFGR_PPRE2_RESET_MASK (0xFFFFC7FF) +#define CFGR_PPRE2_SET_MASK (0x00003800) +#define CFGR_ADCPRE_RESET_MASK (0xFFFF3FFF) +#define CFGR_ADCPRE_SET_MASK (0x0000C000) + +/* CSR register bit mask */ +#define CSR_RVMF_SET (0x01000000) + +/* RCC Flag MASK */ +#define FLAG_MASK (0x1F) + +/* Typical VALUE of the HSI in Hz */ +#define HSI_VALUE (8000000) + +/* BDCR register base address */ +#define BDCR_BASE (PERIPH_BASE + BDCR_OFFSET) + +/* RCC Flag */ +#define RCC_FLAG_HSIRDY (0x20) +#define RCC_FLAG_HSERDY (0x31) +#define RCC_FLAG_PLLRDY (0x39) +#define RCC_FLAG_LSERDY (0x41) +#define RCC_FLAG_LSIRDY (0x61) +#define RCC_FLAG_PINRST (0x7A) +#define RCC_FLAG_PORRST (0x7B) +#define RCC_FLAG_SFTRST (0x7C) +#define RCC_FLAG_IWDGRST (0x7D) +#define RCC_FLAG_WWDGRST (0x7E) +#define RCC_FLAG_LPWRRST (0x7F) + +/* System clock source */ +#define RCC_SYSCLK_HSI (0x00000000) +#define RCC_SYSCLK_HSE (0x00000001) +#define RCC_SYSCLK_PLLCLK (0x00000002) + +/* PLL entry clock source */ +#define RCC_PLL_HSI_DIV2 (0x00000000) +#define RCC_PLL_HSE_DIV1 (0x00010000) +#define RCC_PLL_HSE_DIV2 (0x00030000) + +/* PLL multiplication factor */ +#define RCC_PLLMUL_2 (0x00000000) +#define RCC_PLLMUL_3 (0x00040000) +#define RCC_PLLMUL_4 (0x00080000) +#define RCC_PLLMUL_5 (0x000C0000) +#define RCC_PLLMUL_6 (0x00100000) +#define RCC_PLLMUL_7 (0x00140000) +#define RCC_PLLMUL_8 (0x00180000) +#define RCC_PLLMUL_9 (0x001C0000) +#define RCC_PLLMUL_10 (0x00200000) +#define RCC_PLLMUL_11 (0x00240000) +#define RCC_PLLMUL_12 (0x00280000) +#define RCC_PLLMUL_13 (0x002C0000) +#define RCC_PLLMUL_14 (0x00300000) +#define RCC_PLLMUL_15 (0x00340000) +#define RCC_PLLMUL_16 (0x00380000) +/*\}*/ + +/** + * RCC register: APB1 peripheral + */ +/*\{*/ +#define RCC_APB1_TIM2 (0x00000001) +#define RCC_APB1_TIM3 (0x00000002) +#define RCC_APB1_TIM4 (0x00000004) +#define RCC_APB1_WWDG (0x00000800) +#define RCC_APB1_SPI2 (0x00004000) +#define RCC_APB1_USART2 (0x00020000) +#define RCC_APB1_USART3 (0x00040000) +#define RCC_APB1_I2C1 (0x00200000) +#define RCC_APB1_I2C2 (0x00400000) +#define RCC_APB1_USB (0x00800000) +#define RCC_APB1_CAN (0x02000000) +#define RCC_APB1_BKP (0x08000000) +#define RCC_APB1_PWR (0x10000000) +#define RCC_APB1_ALL (0x1AE64807) +/*\}*/ + +/** + * RCC register: APB2 peripheral + */ +/*\{*/ +#define RCC_APB2_AFIO (0x00000001) +#define RCC_APB2_GPIOA (0x00000004) +#define RCC_APB2_GPIOB (0x00000008) +#define RCC_APB2_GPIOC (0x00000010) +#define RCC_APB2_GPIOD (0x00000020) +#define RCC_APB2_GPIOE (0x00000040) +#define RCC_APB2_ADC1 (0x00000200) +#define RCC_APB2_ADC2 (0x00000400) +#define RCC_APB2_TIM1 (0x00000800) +#define RCC_APB2_SPI1 (0x00001000) +#define RCC_APB2_USART1 (0x00004000) +#define RCC_APB2_ALL (0x00005E7D) +/*\}*/ + +/* Crystal frequency of the main oscillator (8MHz) */ +#define PLL_VCO 8000000 + +/* Reset and Clock Controller registers */ +struct RCC +{ + reg32_t CR; + reg32_t CFGR; + reg32_t CIR; + reg32_t APB2RSTR; + reg32_t APB1RSTR; + reg32_t AHBENR; + reg32_t APB2ENR; + reg32_t APB1ENR; + reg32_t BDCR; + reg32_t CSR; +}; + +/* RCC registers base */ +extern struct RCC *RCC; + +void clock_init(void); + +#endif /* CLOCK_STM32_h */ -- 2.25.1