STM32: add clocking driver.
authorarighi <arighi@38d2e660-2303-0410-9eaa-f027e97ec537>
Tue, 4 May 2010 08:55:10 +0000 (08:55 +0000)
committerarighi <arighi@38d2e660-2303-0410-9eaa-f027e97ec537>
Tue, 4 May 2010 08:55:10 +0000 (08:55 +0000)
git-svn-id: https://src.develer.com/svnoss/bertos/trunk@3605 38d2e660-2303-0410-9eaa-f027e97ec537

bertos/cpu/cortex-m3/drv/clock_stm32.c [new file with mode: 0644]
bertos/cpu/cortex-m3/drv/clock_stm32.h [new file with mode: 0644]

diff --git a/bertos/cpu/cortex-m3/drv/clock_stm32.c b/bertos/cpu/cortex-m3/drv/clock_stm32.c
new file mode 100644 (file)
index 0000000..2095959
--- /dev/null
@@ -0,0 +1,134 @@
+/**
+ * \file
+ * <!--
+ * This file is part of BeRTOS.
+ *
+ * Bertos is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * As a special exception, you may use this file as part of a free software
+ * library without restriction.  Specifically, if other files instantiate
+ * templates or use macros or inline functions from this file, or you compile
+ * this file and link it with other files to produce an executable, this
+ * file does not by itself cause the resulting executable to be covered by
+ * the GNU General Public License.  This exception does not however
+ * invalidate any other reasons why the executable file might be covered by
+ * the GNU General Public License.
+ *
+ * Copyright 2010 Develer S.r.l. (http://www.develer.com/)
+ *
+ * -->
+ *
+ * \brief STM32 Clocking driver.
+ *
+ * \author Andrea Righi <arighi@develer.com>
+ */
+
+#include <cfg/compiler.h>
+#include <cfg/debug.h>
+#include <io/stm32.h>
+#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 (file)
index 0000000..c675a5f
--- /dev/null
@@ -0,0 +1,237 @@
+/**
+ * \file
+ * <!--
+ * This file is part of BeRTOS.
+ *
+ * Bertos is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * As a special exception, you may use this file as part of a free software
+ * library without restriction.  Specifically, if other files instantiate
+ * templates or use macros or inline functions from this file, or you compile
+ * this file and link it with other files to produce an executable, this
+ * file does not by itself cause the resulting executable to be covered by
+ * the GNU General Public License.  This exception does not however
+ * invalidate any other reasons why the executable file might be covered by
+ * the GNU General Public License.
+ *
+ * Copyright 2010 Develer S.r.l. (http://www.develer.com/)
+ *
+ * -->
+ *
+ * \brief Low-level clocking driver for Cortex-M3 STM32.
+ *
+ * \author Andrea Righi <arighi@develer.com>
+ */
+
+#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 */