OpenMPTL - STM32F10X
C++ Microprocessor Template Library
rcc.hpp
Go to the documentation of this file.
1 /*
2  * OpenMPTL - C++ Microprocessor Template Library
3  *
4  * Copyright (C) 2012-2017 Axel Burri <axel@tty0.ch>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program. If not, see <http://www.gnu.org/licenses/>.
18  *
19  */
20 
21 #ifndef ARCH_RCC_HPP_INCLUDED
22 #define ARCH_RCC_HPP_INCLUDED
23 
24 #include <arch/reg/rcc.hpp>
25 #include <typelist.hpp>
26 #include <freq.hpp>
27 #include <type_traits>
28 
29 namespace mptl {
30 
31 
32 //////////////////// rcc ////////////////////
33 
34 
35 class rcc
36 {
37 public: /* ------ configuration traits ------ */
38 
39  /** Enable external high speed oscillator */
41 
42  /** Enable external high speed oscillator */
44 
45  /** Enable Internal low speed oscillator */
47 
48  /** Disable Internal low speed oscillator */
50 
51  /** Enable external low speed oscillator */
53 
54  /** Disable external low speed oscillator */
56 
58  /* Use LSE oscillator clock as RTC clock */
60 
61  /* Use LSI oscillator clock as RTC clock */
63 
64  /* Use HSE oscillator clock as RTC clock */
66  };
67 
68  /** Enable RTC clock */
70 
71 
72 public: /* ------ static member functions ------ */
73 
74  static void backup_domain_software_reset(void) {
77  }
78 
79  static void wait_hse_ready(void) {
80  while(RCC::CR::HSERDY::test() == false);
81  }
82  static bool wait_hse_ready(unsigned timeout) {
83  while((RCC::CR::HSERDY::test() == false) && timeout) {
84  timeout--;
85  }
86  return timeout;
87  }
88 
89  static void wait_lse_ready(void) {
90  while(RCC::BDCR::LSERDY::test() == false);
91  }
92 };
93 
94 
95 //////////////////// system_clock_hse ////////////////////
96 
97 
98 template< typename... Tp >
100 {
101  static void init(void) {
104  }
105 
106  static void configure(void) {
107  RCC::CFGR::reset_to< Tp... >();
108 
110  while(RCC::CR::PLLRDY::test() == false);
112  while(RCC::CFGR::SWS::PLL::test() == false);
113  }
114 };
115 
116 template< freq_t output_freq, freq_t hse_freq = mhz(8) >
118  static_assert(output_freq == !output_freq,
119  "unsupported system clock frequency (see available template specialisations below)");
120 };
121 
122 /* HCLK = SYSCLK, PCLK2 = HCLK, PCLK1 = HCLK */
123 /* PLLCLK = 8MHz / 2 * 6 = 24 MHz */
124 template<>
125 struct system_clock_hse< mhz(24), mhz(8) >
126 : public system_clock_hse_impl <
127  RCC::CFGR::HPRE ::DIV1,
128  RCC::CFGR::PPRE1 ::DIV1,
129  RCC::CFGR::PPRE2 ::DIV1,
130  RCC::CFGR::PLLSRC ::HSE,
131  RCC::CFGR::PLLXTPRE::HSE_DIV2,
132  RCC::CFGR::PLLMUL ::MUL6
133  >
134 {
135  static constexpr freq_t hclk_freq = mhz(24);
136  static constexpr freq_t pclk1_freq = hclk_freq;
137  static constexpr freq_t pclk2_freq = hclk_freq;
138 };
139 
140 /* HCLK = SYSCLK, PCLK2 = HCLK, PCLK1 = HCLK */
141 /* PLLCLK = 8MHz / 2 * 9 = 36 MHz */
142 template<>
143 struct system_clock_hse< mhz(36), mhz(8) >
144 : public system_clock_hse_impl <
145  RCC::CFGR::HPRE ::DIV1,
146  RCC::CFGR::PPRE1 ::DIV1,
147  RCC::CFGR::PPRE2 ::DIV1,
148  RCC::CFGR::PLLSRC ::HSE,
149  RCC::CFGR::PLLXTPRE::HSE_DIV2,
150  RCC::CFGR::PLLMUL ::MUL9
151  >
152 {
153  static constexpr freq_t hclk_freq = mhz(36);
154  static constexpr freq_t pclk1_freq = hclk_freq;
155  static constexpr freq_t pclk2_freq = hclk_freq;
156 };
157 
158 /* HCLK = SYSCLK, PCLK2 = HCLK, PCLK1 = HCLK/2 */
159 /* PLLCLK = 8MHz * 6 = 48 MHz */
160 template<>
161 struct system_clock_hse< mhz(48), mhz(8) >
162 : public system_clock_hse_impl <
163  RCC::CFGR::HPRE ::DIV1,
164  RCC::CFGR::PPRE1 ::DIV2,
165  RCC::CFGR::PPRE2 ::DIV1,
166  RCC::CFGR::PLLSRC ::HSE,
167  RCC::CFGR::PLLXTPRE::HSE_DIV1,
168  RCC::CFGR::PLLMUL ::MUL6
169  >
170 {
171  static constexpr freq_t hclk_freq = mhz(48);
172  static constexpr freq_t pclk1_freq = hclk_freq / 2;
173  static constexpr freq_t pclk2_freq = hclk_freq;
174 };
175 
176 /* HCLK = SYSCLK, PCLK2 = HCLK, PCLK1 = HCLK/2 */
177 /* PLLCLK = 8MHz * 7 = 56 MHz */
178 template<>
179 struct system_clock_hse< mhz(56), mhz(8) >
180 : public system_clock_hse_impl <
181  RCC::CFGR::HPRE ::DIV1,
182  RCC::CFGR::PPRE1 ::DIV2,
183  RCC::CFGR::PPRE2 ::DIV1,
184  RCC::CFGR::PLLSRC ::HSE,
185  RCC::CFGR::PLLXTPRE::HSE_DIV1,
186  RCC::CFGR::PLLMUL ::MUL7
187  >
188 {
189  static constexpr freq_t hclk_freq = mhz(56);
190  static constexpr freq_t pclk1_freq = hclk_freq / 2;
191  static constexpr freq_t pclk2_freq = hclk_freq;
192 };
193 
194 
195 /* HCLK = SYSCLK, PCLK2 = HCLK, PCLK1 = HCLK/2 */
196 /* PLLCLK = 8MHz * 9 = 72 MHz */
197 template<>
198 struct system_clock_hse< mhz(72), mhz(8) >
199 : public system_clock_hse_impl <
200  RCC::CFGR::HPRE ::DIV1,
201  RCC::CFGR::PPRE1 ::DIV2,
202  RCC::CFGR::PPRE2 ::DIV1,
203  RCC::CFGR::PLLSRC ::HSE,
204  RCC::CFGR::PLLXTPRE::HSE_DIV1,
205  RCC::CFGR::PLLMUL ::MUL9
206  >
207 {
208  static constexpr freq_t hclk_freq = mhz(72);
209  static constexpr freq_t pclk1_freq = hclk_freq / 2;
210  static constexpr freq_t pclk2_freq = hclk_freq;
211 };
212 
213 
214 //////////////////// peripheral clock traits ////////////////////
215 
216 
217 /*
218  * Clock resource declaration (enable peripheral clocks)
219  */
220 template<char> struct rcc_gpio_clock_resources;
221 template<unsigned> struct rcc_spi_clock_resources;
222 template<unsigned> struct rcc_usart_clock_resources;
223 template<unsigned> struct rcc_adc_clock_resources;
224 
228  >;
229 
230 /*
231  * Clock resource specialisation (enable peripheral clocks)
232  */
233 template<> struct rcc_gpio_clock_resources<'A'> : RCC::APB2ENR::IOPAEN { };
234 template<> struct rcc_gpio_clock_resources<'B'> : RCC::APB2ENR::IOPBEN { };
235 template<> struct rcc_gpio_clock_resources<'C'> : RCC::APB2ENR::IOPCEN { };
236 template<> struct rcc_gpio_clock_resources<'D'> : RCC::APB2ENR::IOPDEN { };
237 template<> struct rcc_gpio_clock_resources<'E'> : RCC::APB2ENR::IOPEEN { };
238 #if defined (STM32F10X_HD) || defined (STM32F10X_XL)
239 template<> struct rcc_gpio_clock_resources<'F'> : RCC::APB2ENR::IOPFEN { };
240 template<> struct rcc_gpio_clock_resources<'G'> : RCC::APB2ENR::IOPGEN { };
241 #endif
242 
244 #if !defined (STM32F10X_LD) && !defined (STM32F10X_LD_VL)
246 #endif
247 #if defined (STM32F10X_HD) || defined (STM32F10X_CL)
249 #endif
250 
253 #if !defined (STM32F10X_LD) && !defined (STM32F10X_LD_VL)
255 #endif
256 
258 #if !defined (STM32F10X_LD_VL) && !defined (STM32F10X_MD_VL)
260 #endif
261 #if defined (STM32F10X_HD) || defined (STM32F10X_XL)
262 template<> struct rcc_adc_clock_resources<1> : RCC::APB2ENR::ADC3EN { };
263 #endif
264 
265 } // namespace mptl
266 
267 #endif // ARCH_RCC_HPP_INCLUDED
Definition: rcc.hpp:117
static bool wait_hse_ready(unsigned timeout)
Definition: rcc.hpp:82
static __always_inline void reset_to(void)
static void backup_domain_software_reset(void)
Definition: rcc.hpp:74
unsigned int freq_t
Definition: rcc.hpp:223
Definition: rcc.hpp:221
regval< regbits_type, 0x3 > HSE
11: HSE oscillator clock divided by 128 used as RTC clock
Definition: rcc.hpp:405
regval< regbits_type, 0x2 > LSI
10: LSI oscillator clock used as RTC clock
Definition: rcc.hpp:404
Definition: rcc.hpp:220
typelist< RCC::APB1ENR::PWREN, RCC::APB1ENR::BKPEN > rcc_rtc_clock_resources
Definition: rcc.hpp:228
Definition: rcc.hpp:35
static void init(void)
Definition: rcc.hpp:101
typename mpl::make_typelist< sane_typelist<>, Tp... >::type typelist
static constexpr freq_t mhz(unsigned long long x)
Definition: rcc.hpp:57
static void wait_lse_ready(void)
Definition: rcc.hpp:89
regbits< type, 28, 1 > PWREN
Power interface clock enable.
Definition: rcc.hpp:383
regval< regbits_type, 0x1 > LSE
01: LSE oscillator clock used as RTC clock
Definition: rcc.hpp:403
static void configure(void)
Definition: rcc.hpp:106
Definition: rcc.hpp:222
Definition: rcc.hpp:99
static void wait_hse_ready(void)
Definition: rcc.hpp:79